From 3910352c923afda320b2a5134e523932ee1d0633 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Tue, 3 Nov 2026 08:38:57 -0600 Subject: [PATCH] feat(runner): add experimental Cursor Cloud provider (#18068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Runner gives each provider durable execution, tool, and completion contracts. > - Cursor Cloud currently has a direct adapter outside that native contract. > - Cloud work needs exact ownership across HTTP, SSE, Stop, and recovery. > - This PR adds a qualified Cloud API driver and verified proxy to Runner. > - Product setup and hosted placement remain separate dependent changes. ## Linked Issues or Issue Description Refs #5664, #11803, #17299, and #17471. Product integration is #18069. Managed-only API placement is #18310. The related direct-adapter model/transcript work is not replaced. No duplicate native Cursor Cloud integration was found. ## What Changed - Add native `cursor_cloud` / `cursor_cloud_api` with explicit model/repository validation, bounded HTTP/SSE, durable per-turn checkpoints and a qualified Node proxy launched through the Rust facade. - Commit terminal custody before publication/release; coalesce consumers, preserve ambiguous create/Stop/recovery fences, reject late tools, and distinguish definitely-unsent oversized requests from ambiguous responses. - Support scoped cold attachment, current authority, reconnect and verified artifact staging. Keep unsupported warm/external and Windows paths closed. - Preserve early source cursors and verify immutable legacy prefixes before suffix replay, including supported compaction/masking. Optional proof publication failure falls back to complete cold verification. - Preserve canonical records at the durable native producer with JSON-safe privacy and the existing 8MiB bound; drain admitted successor flushes. Reconcile upstream semantic/pack/schema/lifecycle changes and retain S3 and legacy CLI checks. ## Verification Core head `37c442ec8dd4`: all 66 check contexts are terminal successful/neutral/skipped, including required `ci / verify` and `ci / e2e`; fresh exact-head Greptile is 5/5 with zero unresolved threads. Dependent Product `81e828d20a77` and Top `dd2959689627` include the later client handoff correction and are running their own fresh gates. Core: 47/47 Rust, 4/4 compiled-native retirement, 19/19 settlement and normal Runner build passed. Runtime Top `9af1a5de42a2`: build and recursive typecheck passed. Earlier source-scoped evidence includes 398 focused tests, five relay tests and token/type gates. The 251-assertion, 7/8-suite run failed physical PostgreSQL teardown; the unchanged stable WSP suite passed 128 through the documented wrapper. The downstream fixture corrections passed 7/7 browser and 121/121 startup tests without timeout/oracle relaxation; a broken-unsubscribe control fails. Hosted runtime `9af1a5de42a2` has a passing normal build and recursive typecheck. Latest dependent heads additionally contain a pure client fix for stale live/history overlap, with 48 focused tests, UI typecheck and token gates passing. Its new client is not deployed in the frozen hosted image; server/native/API/provider source is unchanged by these four downstream files. Fresh hosted Linux admission on `9af1a5de42a2` retired its owned runner/proxy/socket with zero prompts. The saved configuration survived reopening, and Test authenticated the bound key/catalog/selected model without a prompt. Artifact with `claude-sonnet-4-5` completed, downloaded the exact 27 bytes, matched 121 canonical identities against complete logs and independently reached FINISHED. The active Stop retry was clicked within its immutable boundary, produced one canonical interrupted turn and acknowledged run-only cancellation, retained a valid 35.076s quiet window (maximum gap 4.584s), and independently remained CANCELLED/artifact-absent beyond the original 180-second command deadline. All provider-observer credential callbacks, DB clients and loaders closed; accounting is settled and explicitly unpriced. The first fresh Stop retains its failed 10.373s sampling gap and every sample. On the upgraded9af server, the historical F226 artifact was reopened and downloaded with its exact original hash after its provider agent had been deleted/GET404 earlier today. Historical F226 full Artifact/Stop cleanup, Question, corrected Plan and reconnect retain their original identities. Deleting the three newly created disposable provider agents and the new-case post-delete grade remain blocked on explicit user approval after automatic review rejected expanding the two original approved IDs. No new-case cleanup or complete fresh matrix pass is claimed; this is separate from the directly observed task/Stop behavior and retained exact cleanup proof. Retained failures: stale fixture 132/133; E8 48/135 with 87 reset-hook failures; Mac 17 SQL failures/skips; earlier startup-title, title-save, custody/Stop and deletion failures with unknown causes and bounded recoveries. `dea023` Artifact passed 17 checks but Stop failed its false warning and 50 duplicate log identities. Pre-repair ACK failure and original Core CI failure remain recorded; retry alone establishes no cause or full local-suite pass. Provider dollar cost stays UNKNOWN. ## Risks Experimental: Cursor independently acknowledges neither the effective model nor instruction digest before the first prompt. The caller’s explicit values are submitted and behavior checked live. Unpriced provider dollar cost stays UNKNOWN. Only qualified per-turn controllers are admitted. Uncertain work and incomplete cleanup stay fenced. Existing damaged/duplicate archives remain failed evidence. Prefix proof adds bounded object-store I/O; the 8MiB producer bound does not guarantee future providers’ output fits. ## Model Used OpenAI Codex, GPT-6 family, assisted with reasoning, repository tools, code execution, browser verification, and delegated code review. The serving model’s exact API ID and context window are not exposed. No value is inferred from the model catalog. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used and the limits of available model metadata - [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 linked public issues or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch describes the change and contains no internal ticket ID - [x] I have run the scoped local tests reported above; pending gates are stated separately - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation - [x] I have considered and documented the risks - [x] All required CI gates pass on the current head - [x] Fresh Greptile is 5/5 with no unresolved findings on the current head - [x] I will address all reviewer comments before requesting merge --------- Co-authored-by: Paperclip --- .../ci-incremental-qualification.yml | 4 +- .../src/server/runtime-config.test.ts | 11 +- packages/paperclip-runner/README.md | 54 + .../paperclip-runner/protocol/manifest.json | 2 +- .../schemas/provider-descriptor.schema.json | 19 +- .../runner-core/examples/recovery-fixture.rs | 1 + .../runner-core/src/acpx_provider_backend.rs | 1 + .../src/bin/fake-codex-app-server.rs | 74 + .../runner-core/src/bin/paperclip-runnerd.rs | 63 +- .../crates/runner-core/src/codex_provider.rs | 351 ++++- .../runner-core/src/configured_environment.rs | 1 + .../runner-core/src/cursor_cloud_proxy.rs | 171 ++ .../crates/runner-core/src/durable/mod.rs | 27 + .../crates/runner-core/src/durable/runner.rs | 8 +- .../crates/runner-core/src/durable/state.rs | 1 + .../runner-core/src/durable/transport.rs | 1 + .../src/external_provider_backend.rs | 1 + .../runner/crates/runner-core/src/lib.rs | 1 + .../src/managed_provider_backend.rs | 1 + .../src/native_provider_backend.rs | 2 +- .../runner-core/src/provider_backend.rs | 808 ++++++++-- .../runner-core/src/runtime_notifications.rs | 1 + .../runner-core/tests/acpx_warm_attachment.rs | 1 + .../runner-core/tests/codex_provider.rs | 1 + .../runner-core/tests/durable_recovery.rs | 1 + .../tests/native_provider_backend.rs | 525 ++++++- .../tests/runtime_notifications.rs | 1 + .../build-verified-provider-entrypoints.mjs | 6 + .../src/backends/codex-native-backend.ts | 18 +- .../backends/harness-driver-backend.test.ts | 15 + .../src/backends/harness-driver-backend.ts | 7 +- .../backends/native-backend-factory.test.ts | 17 + .../src/cli/cursor-cloud-app-server-proxy.ts | 218 +++ .../cli/opencode-proxy-thread-read.test.ts | 18 +- .../src/configured-environment.ts | 2 +- .../src/contracts/cursor-cloud.ts | 51 + .../src/contracts/native-execution.test.ts | 28 + .../src/contracts/native-execution.ts | 34 +- .../src/contracts/native-session-backend.ts | 1 + .../cursor-cloud-runner-launch.test.ts | 666 ++++++++ .../durable-prp-control-plane.test.ts | 35 + .../durable-prp-control-plane.ts | 17 +- .../src/drivers/acpx/antigravity-auth.test.ts | 24 +- .../drivers/acpx/copilot-installation.test.ts | 646 ++++++++ .../cursor-cloud-candidate-profiles.test.ts | 148 ++ .../acpx/profile-compatibility.test.ts | 71 + .../cursor-cloud/app-server-proxy.test.ts | 191 +++ .../cursor-cloud/artifact-delivery.test.ts | 523 +++++++ .../drivers/cursor-cloud/artifact-delivery.ts | 196 +++ .../artifact-staging-budget.test.ts | 227 +++ .../cursor-cloud/artifact-staging-budget.ts | 121 ++ .../cursor-cloud/checkpoint-archive.test.ts | 290 ++++ .../src/drivers/cursor-cloud/checkpoint.ts | 249 +++ .../drivers/cursor-cloud/cloud-client.test.ts | 309 ++++ .../src/drivers/cursor-cloud/cloud-client.ts | 563 +++++++ .../src/drivers/cursor-cloud/config.ts | 22 + .../cursor-cloud/cursor-cloud-driver.test.ts | 1391 +++++++++++++++++ .../cursor-cloud/cursor-cloud-driver.ts | 618 ++++++++ .../cursor-cloud/inline-assets.test.ts | 50 + .../src/drivers/cursor-cloud/inline-assets.ts | 72 + .../observation-continuity.test.ts | 151 ++ .../src/drivers/cursor-cloud/stale-socket.ts | 19 + .../src/drivers/runner-tool-bridge.test.ts | 28 + .../src/drivers/runner-tool-bridge.ts | 70 +- packages/paperclip-runner/src/index.ts | 6 + .../src/live/runner-provider-launch.ts | 11 + .../src/live/runnerd-codex-transport.test.ts | 10 + .../src/live/runnerd-codex-transport.ts | 59 +- .../src/native-session-runtime.test.ts | 116 +- .../src/native-session-runtime.ts | 13 +- .../src/protocol/generated/schema-bundle.ts | 19 +- .../copilot-mainline-v22-identity.json | 44 + .../copilot-mainline-v23-identity.json | 44 + .../copilot-mainline-v24-identity.json | 44 + .../copilot-profile-v10-identity.json | 33 + .../copilot-profile-v11-identity.json | 42 + .../copilot-profile-v12-identity.json | 43 + .../copilot-profile-v13-identity.json | 43 + ...ile-v14-candidate-historical-identity.json | 53 + .../copilot-profile-v14-identity.json | 43 + ...ilot-profile-v14-mainline-pi-identity.json | 43 + ...ile-v15-candidate-historical-identity.json | 53 + .../copilot-profile-v15-identity.json | 43 + ...ilot-profile-v15-mainline-pi-identity.json | 43 + ...ile-v16-candidate-historical-identity.json | 53 + .../copilot-profile-v16-identity.json | 43 + ...ilot-profile-v16-mainline-pi-identity.json | 43 + ...ile-v17-candidate-historical-identity.json | 54 + .../copilot-profile-v17-identity.json | 43 + ...ilot-profile-v17-mainline-pi-identity.json | 43 + ...ile-v18-candidate-historical-identity.json | 55 + ...ile-v18-claude-qualification-identity.json | 43 + .../copilot-profile-v18-identity.json | 43 + ...-profile-v18-muse-historical-identity.json | 43 + ...ile-v19-candidate-historical-identity.json | 58 + ...ile-v19-claude-qualification-identity.json | 43 + .../copilot-profile-v19-identity.json | 43 + ...-profile-v19-muse-historical-identity.json | 43 + ...ile-v20-candidate-historical-identity.json | 68 + .../copilot-profile-v20-identity.json | 43 + .../copilot-profile-v21-identity.json | 70 + ...profile-v21-mainline-monitor-identity.json | 44 + .../copilot-profile-v22-identity.json | 76 + .../copilot-profile-v23-identity.json | 77 + .../copilot-profile-v24-identity.json | 79 + .../copilot-profile-v25-identity.json | 79 + .../copilot-profile-v26-identity.json | 81 + .../copilot-profile-v27-identity.json | 81 + .../copilot-profile-v28-identity.json | 81 + .../copilot-profile-v29-identity.json | 81 + .../copilot-profile-v30-identity.json | 81 + .../copilot-profile-v32-identity.json | 81 + .../copilot-profile-v33-identity.json | 81 + .../copilot-profile-v34-identity.json | 81 + .../copilot-profile-v35-identity.json | 81 + .../copilot-profile-v36-identity.json | 81 + .../copilot-profile-v37-identity.json | 81 + .../copilot-profile-v38-identity.json | 81 + .../copilot-profile-v39-identity.json | 81 + .../copilot-profile-v40-identity.json | 81 + .../copilot-profile-v41-identity.json | 81 + .../copilot-profile-v42-identity.json | 82 + .../copilot-profile-v43-identity.json | 82 + .../copilot-profile-v44-identity.json | 82 + .../copilot-profile-v45-identity.json | 82 + .../copilot-profile-v46-identity.json | 82 + .../copilot-profile-v47-identity.json | 82 + .../copilot-profile-v48-identity.json | 82 + .../copilot-profile-v49-identity.json | 82 + .../copilot-profile-v50-identity.json | 83 + .../copilot-profile-v51-identity.json | 84 + .../copilot-profile-v52-identity.json | 84 + .../copilot-profile-v53-identity.json | 84 + .../copilot-profile-v54-identity.json | 84 + .../copilot-profile-v55-identity.json | 84 + .../copilot-profile-v56-identity.json | 84 + .../copilot-profile-v57-identity.json | 85 + .../copilot-profile-v58-identity.json | 85 + ...upgrade-candidate-historical-identity.json | 85 + .../copilot-profile-v59-identity.json | 85 + .../copilot-profile-v60-identity.json | 85 + .../copilot-profile-v61-identity.json | 85 + ...ile-v62-candidate-historical-identity.json | 85 + .../copilot-profile-v62-identity.json | 85 + ...sleep-maintenance-historical-identity.json | 85 + .../copilot-profile-v63-identity.json | 85 + ...connect-candidate-historical-identity.json | 85 + .../copilot-profile-v64-identity.json | 85 + ...sleep-maintenance-historical-identity.json | 85 + .../copilot-profile-v65-identity.json | 85 + ...upgrade-candidate-historical-identity.json | 85 + .../copilot-profile-v66-identity.json | 85 + ...sleep-maintenance-historical-identity.json | 85 + ...-effort-candidate-historical-identity.json | 85 + .../copilot-profile-v67-identity.json | 85 + .../copilot-profile-v68-identity.json | 85 + .../copilot-profile-v69-identity.json | 85 + .../fixtures/copilot-profile-v7-identity.json | 22 + .../copilot-profile-v70-identity.json | 87 ++ .../copilot-profile-v71-identity.json | 87 ++ ...r-cloud-candidate-historical-identity.json | 87 ++ .../copilot-profile-v72-identity.json | 88 ++ ...r-cloud-candidate-historical-identity.json | 87 ++ .../copilot-profile-v73-identity.json | 88 ++ ...r-cloud-candidate-historical-identity.json | 87 ++ .../copilot-profile-v74-identity.json | 88 ++ .../copilot-profile-v75-identity.json | 88 ++ .../copilot-profile-v76-identity.json | 88 ++ .../copilot-profile-v77-identity.json | 88 ++ .../copilot-profile-v78-identity.json | 88 ++ .../copilot-profile-v79-identity.json | 88 ++ ...sleep-maintenance-historical-identity.json | 88 ++ .../fixtures/copilot-profile-v8-identity.json | 22 + .../copilot-profile-v80-identity.json | 88 ++ .../copilot-profile-v81-identity.json | 88 ++ ...r-cloud-candidate-historical-identity.json | 88 ++ .../copilot-profile-v82-identity.json | 88 ++ ...r-cloud-candidate-historical-identity.json | 88 ++ .../copilot-profile-v83-identity.json | 88 ++ .../copilot-profile-v84-identity.json | 88 ++ ...oud-qualification-historical-identity.json | 88 ++ .../copilot-profile-v85-identity.json | 88 ++ ...oud-qualification-historical-identity.json | 88 ++ .../copilot-profile-v86-identity.json | 88 ++ ...oud-qualification-historical-identity.json | 88 ++ .../copilot-profile-v87-identity.json | 88 ++ ...oud-qualification-historical-identity.json | 88 ++ .../copilot-profile-v88-identity.json | 89 ++ ...oud-qualification-historical-identity.json | 88 ++ .../fixtures/copilot-profile-v9-identity.json | 28 + ...oud-qualification-historical-identity.json | 89 ++ .../fixtures/grok-profile-v10-identity.json | 35 + .../fixtures/grok-profile-v11-identity.json | 35 + .../fixtures/grok-profile-v12-identity.json | 35 + ...r-cloud-candidate-historical-identity.json | 35 + .../fixtures/grok-profile-v13-identity.json | 35 + ...oud-qualification-historical-identity.json | 35 + .../fixtures/grok-profile-v14-identity.json | 35 + ...oud-qualification-historical-identity.json | 35 + .../fixtures/grok-profile-v15-identity.json | 36 + ...oud-qualification-historical-identity.json | 36 + .../fixtures/grok-profile-v6-identity.json | 33 + .../fixtures/grok-profile-v7-identity.json | 34 + ...r-cloud-candidate-historical-identity.json | 34 + .../fixtures/grok-profile-v8-identity.json | 35 + .../fixtures/grok-profile-v9-identity.json | 35 + .../fixtures/profile-history-lineage.json | 60 + scripts/ci/cache.integration.test.mjs | 51 + .../__tests__/managed-skill-content.test.ts | 9 +- server/src/services/heartbeat/run-log.test.ts | 39 + server/src/services/heartbeat/run-log.ts | 53 +- .../src/services/heartbeat/run-output.test.ts | 4 +- server/src/services/heartbeat/run-output.ts | 88 +- .../native-runtime/native-run-log-export.ts | 205 ++- .../native-runtime/native-run-log-recovery.ts | 73 +- .../native-run-log-watermark.test.ts | 610 ++++++++ .../native-runtime/native-session-executor.ts | 4 +- server/src/services/object-byte-journal.ts | 73 +- .../src/services/object-run-log-store.test.ts | 210 +++ server/src/services/object-run-log-store.ts | 69 +- server/src/services/run-log-record-limits.ts | 2 + server/src/services/run-log-store.ts | 8 +- 222 files changed, 20082 insertions(+), 274 deletions(-) create mode 100644 packages/paperclip-runner/runner/crates/runner-core/src/cursor_cloud_proxy.rs create mode 100644 packages/paperclip-runner/src/cli/cursor-cloud-app-server-proxy.ts create mode 100644 packages/paperclip-runner/src/contracts/cursor-cloud.ts create mode 100644 packages/paperclip-runner/src/control-plane/cursor-cloud-runner-launch.test.ts create mode 100644 packages/paperclip-runner/src/drivers/acpx/cursor-cloud-candidate-profiles.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/app-server-proxy.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint-archive.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/config.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/observation-continuity.test.ts create mode 100644 packages/paperclip-runner/src/drivers/cursor-cloud/stale-socket.ts create mode 100644 packages/paperclip-runner/test/fixtures/copilot-mainline-v22-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-mainline-v23-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-mainline-v24-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v10-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v11-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v12-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v13-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v14-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v14-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v14-mainline-pi-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v15-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v15-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v15-mainline-pi-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v16-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v16-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v16-mainline-pi-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v17-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v17-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v17-mainline-pi-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v18-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v18-claude-qualification-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v18-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v18-muse-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v19-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v19-claude-qualification-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v19-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v19-muse-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v20-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v20-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v21-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v21-mainline-monitor-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v22-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v23-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v24-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v25-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v26-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v27-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v28-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v29-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v30-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v32-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v33-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v34-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v35-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v36-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v37-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v38-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v39-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v40-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v41-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v42-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v43-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v44-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v45-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v46-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v47-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v48-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v49-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v50-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v51-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v52-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v53-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v54-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v55-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v56-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v57-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v58-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v59-hot-upgrade-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v59-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v60-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v61-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v62-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v62-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v62-sleep-maintenance-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v63-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v63-reconnect-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v64-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v64-sleep-maintenance-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v65-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v66-hot-upgrade-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v66-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v66-sleep-maintenance-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v67-grok-native-effort-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v67-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v68-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v69-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v7-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v71-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v72-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v72-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v73-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v73-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v74-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v74-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v75-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v76-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v77-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v78-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v79-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v79-sleep-maintenance-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v8-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v80-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v81-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v82-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v82-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v83-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v83-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v84-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v85-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v85-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v86-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v86-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v87-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v88-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v9-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v10-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v11-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v12-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v13-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v13-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v14-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v14-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v15-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v15-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v16-cursor-cloud-qualification-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v6-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v7-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v8-cursor-cloud-candidate-historical-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v8-identity.json create mode 100644 packages/paperclip-runner/test/fixtures/grok-profile-v9-identity.json create mode 100644 server/src/services/native-runtime/native-run-log-watermark.test.ts create mode 100644 server/src/services/run-log-record-limits.ts diff --git a/.github/workflows/ci-incremental-qualification.yml b/.github/workflows/ci-incremental-qualification.yml index 1542dada224..43ea66b942d 100644 --- a/.github/workflows/ci-incremental-qualification.yml +++ b/.github/workflows/ci-incremental-qualification.yml @@ -82,13 +82,13 @@ jobs: node-version: 24 package-manager-cache: false - name: Install isolated qualification tools - run: npm install --prefix "$RUNNER_TEMP/ci-tools" --no-audit --no-fund turbo@2.11.10 + run: npm install --prefix "$RUNNER_TEMP/ci-tools" --no-audit --no-fund turbo@2.11.10 pnpm@9.15.4 - name: Prove planning and required checks run: node --test .github/scripts/tests/ci-plan.test.mjs .github/scripts/tests/ci-routing.test.mjs - name: Prove real cache reuse and invalidation env: PAPERCLIP_CI_TEST_TURBO: ${{ runner.temp }}/ci-tools/node_modules/.bin/turbo - run: node --test scripts/ci/cache.integration.test.mjs + run: PATH="$RUNNER_TEMP/ci-tools/node_modules/.bin:$PATH" node --test scripts/ci/cache.integration.test.mjs - name: Check the real repository task graph env: CI_TURBO_BIN: ${{ runner.temp }}/ci-tools/node_modules/.bin/turbo diff --git a/packages/adapters/opencode-local/src/server/runtime-config.test.ts b/packages/adapters/opencode-local/src/server/runtime-config.test.ts index e6ada9b8851..c1c96bbf893 100644 --- a/packages/adapters/opencode-local/src/server/runtime-config.test.ts +++ b/packages/adapters/opencode-local/src/server/runtime-config.test.ts @@ -64,10 +64,13 @@ describe("prepareOpenCodeRuntimeConfig", () => { expect(command.status).toBe(7); if (process.platform === "linux") { const parentScore = await fs.readFile("/proc/self/oom_score_adj", "utf8"); - expect(execFileSync("bash", ["-c", "cat /proc/self/oom_score_adj"], { - env: { ...process.env, ...hookEnv.child }, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], - }).trim()).toBe("1000"); - expect(await fs.readFile("/proc/self/oom_score_adj", "utf8")).toBe(parentScore); + for (const shellLevel of ["0", "1"]) { + expect(execFileSync("bash", ["-c", "cat /proc/self/oom_score_adj"], { + env: { ...process.env, ...hookEnv.child, SHLVL: shellLevel }, encoding: "utf8", + stdio: ["ignore", "pipe", "pipe"], + }).trim()).toBe("1000"); + expect(await fs.readFile("/proc/self/oom_score_adj", "utf8")).toBe(parentScore); + } } const config = JSON.parse(await fs.readFile(path.join(relocated, "opencode", "opencode.json"), "utf8")); expect(config).toMatchObject({ plugin: ["operator-plugin"], permission: { bash: "ask" } }); diff --git a/packages/paperclip-runner/README.md b/packages/paperclip-runner/README.md index a58ef9fb3cb..d0ad4ec7bea 100644 --- a/packages/paperclip-runner/README.md +++ b/packages/paperclip-runner/README.md @@ -214,6 +214,60 @@ are unavailable. Accepting a native plan ends the planning run successfully whil the task waits for the next instruction. See the [Cursor release report](../../doc/plans/2026-10-03-cursor-production-readiness.md). +Cursor Cloud is a separate experimental native provider (`cursor_cloud`, driver +`cursor_cloud_api`). Configure `NativeProviderConfig` with `kind: "cursor_cloud"`, +an explicit `model`, and a `cursorCloud` object using the +`paperclip.cursor-cloud.config.v1` schema. That object requires either a repository +list or a named Cursor Cloud environment. The launch environment supplies +`CURSOR_API_KEY` and the scoped tool relay configuration. Native Cloud supports +per-turn Runner lifecycle only; Cursor executes tools in its hosted VM. Configure +hosted shell secrets in the Cursor Cloud environment. +Paperclip native tools use the injected `paperclip` MCP server with +controller-managed authentication; they need no Paperclip REST credentials in the +Cloud VM. + +Cloud v1 provides no independent acknowledgment of the effective model or exact +instruction digest. Runner records submitted inputs and treats this support as +experimental. Cursor manages its own shell permissions; native permission, +question and plan callbacks and fixed per-run dollar limits are unavailable. +Paperclip planning tasks retain their pinned planning context and existing tool +restrictions while using Cloud's default harness. Plan documents and +revision-bound Paperclip confirmations use the normal semantic tools; this does +not enable Cursor's native Plan API or native plan-decision callbacks. +Production usage and dollar cost remain unknown; the Cloud usage API is not yet +projected through the Runner facade. Stop cancels the exact Cloud run and requires +a terminal provider receipt. Unknown cancellation remains unconfirmed. Recovery +reuses the saved Agent/Run and stream cursor, keeps the original deadline, and does +not replay an ambiguous paid mutation. Tool callbacks require the capability of +the current turn, including fresh MCP initialization. Recovery retains that +capability in the private checkpoint. Older active checkpoints without it permit +cleanup, but cannot resume tool access. Read-only observation retries transient +stream failures within the original deadline, with bounded backoff. + +Checkpoint acquisition and dead-owner takeover share a private, bounded local +acquisition guard; no network work runs while it is held. Ordinary dead main-owner +recovery remains automatic when that guard is absent. An abandoned or +ownership-changed acquisition guard blocks reuse and archival as ambiguous state. +It is retained for reconciliation, never reclaimed from its age or PID alone. + +Cloud deliverables use `cursor-artifact:` with the exact +byte count and SHA-256. Runner downloads the provider artifact to its private +artifact root before normal deliverable registration. Fully verified bytes publish +atomically without replacing an existing final file; existing files must match the +claim. A crashed writer can leave an unreferenced private temporary file, which is +retained rather than mistaken for a completed artifact. A completed publication +alias is removed only for a proven inactive publisher and the exact verified +private final inode. Active or unknown aliases remain fenced; successful handoff +requires a single final link. A remote path never grants access to the controller's +project files. Staging is experimental and bounded to 256 MiB and 256 new +allocations/import attempts per artifact root, including zero-byte attempts. +A durable reservation precedes each new download. Rejected, aborted or uncertain +registration retains the charge and verified file for recovery. The bound survives +session changes and seeds existing retained usage. Exact existing-file recovery +still verifies current provider bytes without another body/temp allocation at +capacity. An uncertain ledger, retained pending reservation or ownership lock +blocks new imports rather than resetting the budget. + Google Antigravity is an **unqualified, pending** native ACPX integration. The explicit `paperclipai runtime setup antigravity` command installs the verified Antigravity ACP 1.4.3 distribution and its owned admission patch on macOS ARM64. diff --git a/packages/paperclip-runner/protocol/manifest.json b/packages/paperclip-runner/protocol/manifest.json index 4126031d212..202a325bc4c 100644 --- a/packages/paperclip-runner/protocol/manifest.json +++ b/packages/paperclip-runner/protocol/manifest.json @@ -85,7 +85,7 @@ { "path": "schemas/provider-descriptor.schema.json", "id": "https://paperclip.dev/schemas/prp/v1/provider-descriptor.schema.json", - "sha256": "81d525335245dd4cb8a9bf41e3390dc60c6dd3e32474aad48b4f18a94d5f9711" + "sha256": "811e6a345fd21fa18a135dee082a5249db1f37b31a3ae098e7e25a5f9294495b" }, { "path": "schemas/provider-event.schema.json", diff --git a/packages/paperclip-runner/protocol/schemas/provider-descriptor.schema.json b/packages/paperclip-runner/protocol/schemas/provider-descriptor.schema.json index 6a4399c2fbb..12447bf6fd6 100644 --- a/packages/paperclip-runner/protocol/schemas/provider-descriptor.schema.json +++ b/packages/paperclip-runner/protocol/schemas/provider-descriptor.schema.json @@ -20,7 +20,8 @@ "acpx", "openai_dot", "grok_bot", - "muse" + "muse", + "cursor_cloud" ] }, "driver": { @@ -32,7 +33,8 @@ "acpx_runtime", "openai_dot_mcp", "grok_bot_mcp", - "muse_external" + "muse_external", + "cursor_cloud_api" ] }, "model": { @@ -328,6 +330,19 @@ "const": "remote_service" } } + }, + { + "properties": { + "provider": { + "const": "cursor_cloud" + }, + "driver": { + "const": "cursor_cloud_api" + }, + "executionKind": { + "const": "local_process" + } + } } ] }, diff --git a/packages/paperclip-runner/runner/crates/runner-core/examples/recovery-fixture.rs b/packages/paperclip-runner/runner/crates/runner-core/examples/recovery-fixture.rs index 9a514bc3de9..abdd1785e60 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/examples/recovery-fixture.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/examples/recovery-fixture.rs @@ -243,6 +243,7 @@ fn main() -> Result<(), Box> { runner_digest: value("--runner-digest")?, acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: value("--max-outbox-bytes")?.parse()?, p0_reserve_bytes: value("--p0-reserve-bytes")?.parse()?, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs index 1065f6fa223..c7cee722c59 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs @@ -2713,6 +2713,7 @@ mod tests { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: launch_profile, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/bin/fake-codex-app-server.rs b/packages/paperclip-runner/runner/crates/runner-core/src/bin/fake-codex-app-server.rs index cf710278233..fad7b860c79 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/bin/fake-codex-app-server.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/bin/fake-codex-app-server.rs @@ -1219,6 +1219,55 @@ fn run() -> Result<(), Box> { }))?; } "initialized" => {} + "paperclip/ackTerminal" => { + let path = argument(&args, "--cursor-cloud-terminal-file") + .ok_or("terminal fixture missing")?; + let delivery: Value = serde_json::from_slice(&fs::read(&path)?)?; + if message.pointer("/params/turnId") != delivery.get("turnId") + || message.pointer("/params/receiptId") != delivery.get("receiptId") + { + return Err("terminal receipt changed".into()); + } + if Path::new(&format!("{path}.hold-ack")).exists() { + send( + json!({"id": id, "error": {"code": -32000, "message": "controlled lost receipt"}}), + )?; + } else { + fs::remove_file(path)?; + send( + json!({"id": id, "result": {"acknowledged": true, "turnId": delivery["turnId"], "receiptId": delivery["receiptId"]}}), + )?; + } + } + "paperclip/shutdown" if args.iter().any(|arg| arg == "--cursor-cloud-shutdown") => { + let unconfirmed = + argument(&args, "--cursor-cloud-shutdown-control").is_some_and(|path| { + fs::read_to_string(path).is_ok_and(|value| value.trim() == "unconfirmed") + }); + let params = &message["params"]; + let has_remote_run = state.next_turn > 0; + if !unconfirmed { + state.active_turn_id = None; + save_state(&state_path, &state)?; + } + let mut receipt = json!({ + "threadId": params["threadId"], "turnId": params["turnId"], + "remoteStopped": !unconfirmed, + "remoteAgentId": if has_remote_run { json!("cursor-agent-fixture") } else { Value::Null }, + "remoteRunId": if has_remote_run { json!("cursor-run-fixture") } else { Value::Null }, + "status": if unconfirmed { "RUNNING" } else { "CANCELLED" }, + }); + if let Some(path) = argument(&args, "--cursor-cloud-terminal-file") { + if !unconfirmed && Path::new(&path).exists() { + let delivery: Value = serde_json::from_slice(&fs::read(path)?)?; + receipt["remoteRunId"] = delivery["providerRunId"].clone(); + receipt["status"] = delivery["status"].clone(); + receipt["cursorCloudTerminalDelivery"] = delivery; + } + } + send(json!({"id":id,"result":receipt}))?; + } + "thread/start" => { if let Some(delay) = argument(&args, "--thread-start-delay-ms") { thread::sleep(Duration::from_millis(delay.parse()?)); @@ -1372,6 +1421,26 @@ fn run() -> Result<(), Box> { send(json!({"id": id, "result": {"data": turns, "nextCursor": null}}))?; } "thread/read" => { + if let Some(path) = argument(&args, "--cursor-cloud-terminal-file") { + if Path::new(&path).exists() { + let first_read = format!("{path}.first-read"); + let finishes_between_reads = args + .iter() + .any(|arg| arg == "--cursor-cloud-finish-between-reads") + && !Path::new(&first_read).exists(); + if finishes_between_reads { + fs::write(first_read, b"observed active")?; + } else { + let delivery: Value = serde_json::from_slice(&fs::read(&path)?)?; + state.active_turn_id = None; + save_state(&state_path, &state)?; + send( + json!({"id": id, "result": {"thread": {"id": state.thread_id, "turns": []}, "cursorCloudTerminalDelivery": delivery}}), + )?; + continue; + } + } + } if descendant_notifications && message.pointer("/params/threadId").and_then(Value::as_str) == Some("descendant-1") @@ -1896,6 +1965,11 @@ fn run() -> Result<(), Box> { finish_turn(&state_path, &mut state, "completed")?; } else if emit_split_event_burst { send_split_event_burst(&state, split_event_prefix_count)?; + } else if hold_turn && args.iter().any(|arg| arg == "--held-final-message") { + send(json!({"method": "item/completed", "params": { + "threadId": state.thread_id, "turnId": provider_turn_id, + "item": {"id": "final", "type": "agentMessage", "text": "Durable Cloud final"} + }}))?; } else if hold_turn && args.iter().any(|arg| arg == "--held-output") { if let Some(release_file) = argument(&args, "--held-output-release-file") { let deadline = Instant::now() + Duration::from_secs(60); diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/bin/paperclip-runnerd.rs b/packages/paperclip-runner/runner/crates/runner-core/src/bin/paperclip-runnerd.rs index cbde98cd150..13d237e3276 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/bin/paperclip-runnerd.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/bin/paperclip-runnerd.rs @@ -10,7 +10,7 @@ use std::os::unix::fs::{MetadataExt, OpenOptionsExt, PermissionsExt}; use paperclip_runner_core::acpx_candidate_admission::AcpxCandidateAdmission; use paperclip_runner_core::durable::{ capture_bootstrap_ticket, redact_diagnostic_text, run_durable_runner, AcpxLaunchProfile, - DurableRunnerConfig, OpenCodeLaunchProfile, QualifiedLaunchArtifact, + CursorCloudLaunchProfile, DurableRunnerConfig, OpenCodeLaunchProfile, QualifiedLaunchArtifact, }; use paperclip_runner_core::local_runner::{run_local_runner, LocalRunnerError, RunnerConfig}; use paperclip_runner_core::native_provider_backend::NativeProviderCommandExecutor; @@ -344,6 +344,33 @@ fn opencode_launch_profile( } } +fn cursor_cloud_launch_profile( + args: &[String], +) -> Result, LocalRunnerError> { + let command = optional_value(args, "--cursor-cloud-proxy-command")?; + let command_sha256 = optional_value(args, "--cursor-cloud-proxy-command-sha256")?; + let proxy_script = optional_value(args, "--cursor-cloud-proxy-script")?; + let proxy_script_sha256 = optional_value(args, "--cursor-cloud-proxy-script-sha256")?; + match (command, command_sha256, proxy_script, proxy_script_sha256) { + (None, None, None, None) => Ok(None), + (Some(command), Some(command_sha256), Some(proxy_script), Some(proxy_script_sha256)) => { + Ok(Some(CursorCloudLaunchProfile { + command: QualifiedLaunchArtifact { + path: PathBuf::from(command), + sha256: command_sha256, + }, + proxy_script: QualifiedLaunchArtifact { + path: PathBuf::from(proxy_script), + sha256: proxy_script_sha256, + }, + })) + } + _ => Err(LocalRunnerError::invalid( + "Cursor Cloud launch profile requires command, proxy, and both SHA-256 digests", + )), + } +} + fn usize_value(args: &[String], name: &str, default: usize) -> Result { optional_u64(args, name)?.map_or(Ok(default), |value| { usize::try_from(value) @@ -425,6 +452,7 @@ fn run_durable(args: &[String]) -> Result<(), LocalRunnerError> { runner_digest: value(args, "--runner-digest")?, acpx_launch_profile: acpx_launch_profile(args)?, opencode_launch_profile: opencode_launch_profile(args)?, + cursor_cloud_launch_profile: cursor_cloud_launch_profile(args)?, max_outbox_bytes: usize_value(args, "--max-outbox-bytes", 16 * 1024 * 1024)?, p0_reserve_bytes: usize_value(args, "--p0-reserve-bytes", 1024 * 1024)?, max_frame_bytes: usize_value(args, "--max-frame-bytes", 1024 * 1024)?, @@ -546,6 +574,39 @@ fn run_main(args: Vec) -> ExitCode { mod tests { use super::*; + #[test] + fn cursor_cloud_launch_flags_are_optional_as_a_whole_and_required_as_an_exact_pin_set() { + assert!(cursor_cloud_launch_profile(&[]).unwrap().is_none()); + let complete = vec![ + "--cursor-cloud-proxy-command", + "/runtime/node", + "--cursor-cloud-proxy-command-sha256", + "sha256:node", + "--cursor-cloud-proxy-script", + "/runtime/cursor-cloud-proxy.cjs", + "--cursor-cloud-proxy-script-sha256", + "sha256:proxy", + ] + .into_iter() + .map(str::to_owned) + .collect::>(); + let profile = cursor_cloud_launch_profile(&complete).unwrap().unwrap(); + assert_eq!(profile.command.path, PathBuf::from("/runtime/node")); + assert_eq!( + profile.proxy_script.path, + PathBuf::from("/runtime/cursor-cloud-proxy.cjs") + ); + for missing in (0..complete.len()).step_by(2) { + let partial = complete + .iter() + .enumerate() + .filter(|(index, _)| *index < missing || *index > missing + 1) + .map(|(_, value)| value.clone()) + .collect::>(); + assert!(cursor_cloud_launch_profile(&partial).is_err()); + } + } + #[test] fn listener_port_is_configurable_and_defaults_to_43127() { let base: Vec = [ diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/codex_provider.rs b/packages/paperclip-runner/runner/crates/runner-core/src/codex_provider.rs index abdcd69411b..33449c81a66 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/codex_provider.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/codex_provider.rs @@ -12,7 +12,7 @@ use sha2::{Digest, Sha256}; #[cfg(test)] use crate::durable::QualifiedLaunchArtifact; -use crate::durable::{redact_text, OpenCodeLaunchProfile}; +use crate::durable::{redact_text, CursorCloudLaunchProfile, OpenCodeLaunchProfile}; use crate::local_runner::LocalRunnerError; use crate::process_supervisor::{ is_node_interpreter, BoundedLogBuffer, ProcessExitFact, ProcessOutput, SupervisedProcess, @@ -71,6 +71,7 @@ pub(crate) fn runtime_notification_codex_args( pub const CODEX_APP_SERVER_MAX_FRAME_BYTES: usize = 4 * 1024 * 1024; const QUALIFIED_OPENCODE_VERSION: &str = "1.18.34"; +const CURSOR_CLOUD_PROXY_VERSION: &str = "cursor-cloud-v1"; const DEFAULT_PROVIDER_TRACE_MAX_BYTES: usize = 64 * 1024 * 1024; const MAX_BUFFERED_MESSAGES: usize = 1_024; const MAX_BUFFERED_MESSAGE_BYTES: usize = 16 * 1024 * 1024; @@ -103,6 +104,19 @@ const OPENCODE_PROVIDER_ENVIRONMENT_KEYS: &[&str] = &[ "PAPERCLIP_NORMALIZED_SESSION_ID", "PAPERCLIP_NATIVE_RUNTIME_CONTEXT_PATH", ]; +const CURSOR_CLOUD_PROVIDER_ENVIRONMENT_KEYS: &[&str] = &[ + "CURSOR_API_KEY", + "PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH", + "PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT", + "PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH", + "PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN", + "PAPERCLIP_CURSOR_CLOUD_RELAY_URL", + "PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT", + "PAPERCLIP_RUNNER_INSTANCE_ID", + "PAPERCLIP_RUN_ID", + "PAPERCLIP_NORMALIZED_SESSION_ID", + "PAPERCLIP_NATIVE_RUNTIME_CONTEXT_PATH", +]; const TRUSTED_OPENCODE_EXECUTABLE_ARG: &str = "--paperclip-trusted-opencode-executable"; const MAX_PROVIDER_STDERR_LINES: usize = 32; const MAX_PROVIDER_STDERR_BYTES: usize = 8 * 1024; @@ -490,10 +504,12 @@ impl CodexProviderConfig { } if !matches!( (self.provider.as_str(), self.driver.as_str()), - ("codex", "codex_app_server") | ("opencode", "opencode_server") + ("codex", "codex_app_server") + | ("opencode", "opencode_server") + | ("cursor_cloud", "cursor_cloud_api") ) { return Err(LocalRunnerError::invalid( - "local runner provider must be codex through codex_app_server or opencode through opencode_server", + "runner facade provider/driver pair must be codex/codex_app_server, opencode/opencode_server, or cursor_cloud/cursor_cloud_api", )); } if self.provider_version.trim().is_empty() || self.provider_version.len() > 120 { @@ -506,6 +522,18 @@ impl CodexProviderConfig { "OpenCode providerVersion must equal the qualified {QUALIFIED_OPENCODE_VERSION} release", ))); } + if self.provider == "cursor_cloud" + && (self.provider_version != CURSOR_CLOUD_PROXY_VERSION + || self.model.as_ref().is_none_or(|model| { + model.trim().is_empty() || model.chars().any(char::is_control) + }) + || self.approval_policy != "never" + || self.read_only) + { + return Err(LocalRunnerError::invalid( + "Cursor Cloud requires cursor-cloud-v1, an exact model, provider-managed permissions, and no local read-only claim", + )); + } if self.externally_sandboxed && self.provider != "codex" { return Err(LocalRunnerError::invalid( "external sandbox delegation is only supported by the Codex provider", @@ -760,6 +788,8 @@ pub struct CodexProvider { trace: Option, last_trace_frame_id: Option, opencode_launch_profile: Option, + cursor_cloud_launch_profile: Option, + provider_termination_receipt: Option, completion_contract: Option, permission_profile: &'static str, exit_drain: Option, @@ -895,7 +925,9 @@ const CODEX_PROVIDER_ENVIRONMENT_KEYS: &[&str] = &[ ]; fn codex_permission_profile(provider: &str, external_sandbox: bool) -> &'static str { - if provider == "codex" && external_sandbox { + if provider == "cursor_cloud" { + "paperclip-runner-provider-managed" + } else if provider == "codex" && external_sandbox { "paperclip-runner-external-sandbox" } else { "paperclip-runner-workspace-only" @@ -918,6 +950,7 @@ impl CodexProvider { 1, None, None, + None, ) } @@ -933,6 +966,7 @@ impl CodexProvider { 1, None, None, + None, ) } @@ -942,6 +976,7 @@ impl CodexProvider { resume_thread_id: Option<&str>, process_generation: u64, opencode_launch_profile: Option<&OpenCodeLaunchProfile>, + cursor_cloud_launch_profile: Option<&CursorCloudLaunchProfile>, completion_contract: Option<(&str, &[String])>, ) -> Result { Self::start_with_tools_observed( @@ -950,6 +985,7 @@ impl CodexProvider { resume_thread_id, process_generation, opencode_launch_profile, + cursor_cloud_launch_profile, completion_contract, &mut |_| Ok(()), ) @@ -961,6 +997,7 @@ impl CodexProvider { resume_thread_id: Option<&str>, process_generation: u64, opencode_launch_profile: Option<&OpenCodeLaunchProfile>, + cursor_cloud_launch_profile: Option<&CursorCloudLaunchProfile>, completion_contract: Option<(&str, &[String])>, observe: &mut dyn FnMut(ProviderStartupObservation) -> Result<(), LocalRunnerError>, ) -> Result { @@ -1007,16 +1044,21 @@ impl CodexProvider { "all_proxy", "RUST_BACKTRACE", ]; - let provider_environment_keys = if config.provider == "opencode" { - OPENCODE_PROVIDER_ENVIRONMENT_KEYS + let provider_environment_keys = match config.provider.as_str() { + "opencode" => OPENCODE_PROVIDER_ENVIRONMENT_KEYS, + "cursor_cloud" => CURSOR_CLOUD_PROVIDER_ENVIRONMENT_KEYS, + _ => CODEX_PROVIDER_ENVIRONMENT_KEYS, + }; + let github_environment_keys = if config.provider == "cursor_cloud" { + &[][..] } else { - CODEX_PROVIDER_ENVIRONMENT_KEYS + GITHUB_CREDENTIAL_ENVIRONMENT_KEYS }; let environment_keys = common_environment_keys .iter() .copied() .chain(provider_environment_keys.iter().copied()) - .chain(GITHUB_CREDENTIAL_ENVIRONMENT_KEYS.iter().copied()) + .chain(github_environment_keys.iter().copied()) .collect::>(); let runtime_request_scope = new_runtime_request_scope()?; let stdio_mcp = if config.provider == "codex" && !config.read_only { @@ -1051,7 +1093,28 @@ impl CodexProvider { } } let spawn = (|| { - if config.provider == "opencode" { + if config.provider == "cursor_cloud" { + let profile = cursor_cloud_launch_profile.ok_or_else(|| { + LocalRunnerError::invalid( + "Cursor Cloud runner startup omitted its qualified launch profile", + ) + })?; + let proxy_script = profile.proxy_script.path.to_string_lossy(); + if config.command != profile.command.path + || config.args.as_slice() != [proxy_script.as_ref()] + { + return Err(LocalRunnerError::invalid( + "Cursor Cloud launch does not match the runner-owned qualified profile", + )); + } + let launch = verified_cursor_cloud_launch(profile)?; + SupervisedProcess::spawn_verified_with_environment_keys( + &launch, + Duration::from_secs(2), + CODEX_APP_SERVER_MAX_FRAME_BYTES, + &environment_keys, + ) + } else if config.provider == "opencode" { let profile = opencode_launch_profile.ok_or_else(|| { LocalRunnerError::invalid( "OpenCode runner startup omitted its qualified launch profile", @@ -1145,6 +1208,8 @@ impl CodexProvider { trace: ProviderTraceSink::from_environment(), last_trace_frame_id: None, opencode_launch_profile: opencode_launch_profile.cloned(), + cursor_cloud_launch_profile: cursor_cloud_launch_profile.cloned(), + provider_termination_receipt: None, completion_contract: completion_contract.map(|(revision, criterion_ids)| { ProviderCompletionContract { revision: revision.to_owned(), @@ -1198,7 +1263,7 @@ impl CodexProvider { } else { params_object.insert("permissions".to_owned(), json!(provider.permission_profile)); } - if config.provider == "opencode" { + if matches!(config.provider.as_str(), "opencode" | "cursor_cloud") { if let Some(mode) = &config.conversation_mode { params_object.insert("conversationMode".to_owned(), json!(mode)); } @@ -1344,6 +1409,9 @@ impl CodexProvider { completion_contract: Option<(&str, &[String])>, accounting: &mut Vec<(String, Value)>, ) -> Result { + if self.config.provider == "cursor_cloud" { + return Ok(false); + } let authorized_tools = authorized_tools.into_iter().collect::>(); let completion_contract = completion_contract.map(|(revision, criterion_ids)| ProviderCompletionContract { @@ -1675,6 +1743,7 @@ impl CodexProvider { Some(&thread_id), next_generation, self.opencode_launch_profile.as_ref(), + self.cursor_cloud_launch_profile.as_ref(), completion_contract.as_ref().map(|contract| { ( contract.revision.as_str(), @@ -2048,6 +2117,7 @@ impl CodexProvider { // Retain the prior settled identity while the next turn runs. Besides // recognizing delayed prior-turn requests, this fails closed if a // provider ambiguously reuses the same turn id for fresh work. + self.provider_termination_receipt = None; self.active_provider_turn_id = Some(provider_turn_id); self.runtime_request_scope = runtime_request_scope; } @@ -2102,6 +2172,59 @@ impl CodexProvider { ) } + pub(crate) fn cursor_cloud_terminal_delivery( + &mut self, + ) -> Result, LocalRunnerError> { + if self.config.provider != "cursor_cloud" { + return Ok(None); + } + let snapshot = self.read_thread()?; + if snapshot.pointer("/thread/id").and_then(Value::as_str) != Some(self.thread_id.as_str()) { + return Err(LocalRunnerError::invalid( + "Cursor Cloud terminal snapshot changed its thread", + )); + } + let Some(value) = snapshot + .get("cursorCloudTerminalDelivery") + .filter(|value| !value.is_null()) + else { + return Ok(None); + }; + if latest_active_turn_id(&snapshot).is_some() { + return Err(LocalRunnerError::invalid( + "Cursor Cloud terminal snapshot also reports active work", + )); + } + let delivery = crate::cursor_cloud_proxy::TerminalDelivery::parse(value, &self.thread_id)?; + self.active_provider_turn_id = None; + Ok(Some(delivery)) + } + + pub(crate) fn acknowledge_cursor_cloud_terminal( + &mut self, + delivery: &crate::cursor_cloud_proxy::TerminalDelivery, + ) -> Result<(), LocalRunnerError> { + if self.config.provider != "cursor_cloud" || delivery.thread_id != self.thread_id { + return Err(LocalRunnerError::invalid( + "Cursor Cloud terminal receipt changed its provider", + )); + } + let response = self.request( + "paperclip/ackTerminal", + json!({"turnId":delivery.turn_id,"receiptId":delivery.receipt_id}), + )?; + if response.get("acknowledged") != Some(&Value::Bool(true)) + || response.get("turnId").and_then(Value::as_str) != Some(delivery.turn_id.as_str()) + || response.get("receiptId").and_then(Value::as_str) + != Some(delivery.receipt_id.as_str()) + { + return Err(LocalRunnerError::invalid( + "Cursor Cloud terminal receipt was not acknowledged", + )); + } + Ok(()) + } + pub fn read_thread(&mut self) -> Result { // Probing provider state does not supersede an authoritative terminal. // A later replacement turn must still establish its own identity. @@ -3120,16 +3243,78 @@ impl CodexProvider { } pub fn shutdown(&mut self) -> Result<(), LocalRunnerError> { + self.shutdown_with_cursor_cloud_delivery(|_| Ok(false)) + } + + pub(crate) fn shutdown_with_cursor_cloud_delivery( + &mut self, + mut retain: impl FnMut( + &crate::cursor_cloud_proxy::TerminalDelivery, + ) -> Result, + ) -> Result<(), LocalRunnerError> { self.expected_shutdown = true; // A failed courtesy response must never prevent process fencing. let cancellation = self.cancel_pending_requests(); - let result = self.process.terminate_group().map(|_| ()).and(cancellation); + let remote_termination = if self.config.provider == "cursor_cloud" { + let expected_turn = self.active_provider_turn_id.clone().or_else(|| { + self.completed_turn_authority + .as_ref() + .map(|authority| authority.provider_turn_id.clone()) + }); + self.request_classified_until( + "paperclip/shutdown", + json!({ "threadId": self.thread_id, "turnId": expected_turn }), + Some(std::time::Instant::now() + crate::cursor_cloud_proxy::SHUTDOWN_TIMEOUT), + ) + .map_err(ProviderRequestError::into_inner) + .and_then(|receipt| { + let normalized = crate::cursor_cloud_proxy::shutdown_receipt( + &receipt, + &self.thread_id, + expected_turn.as_deref(), + )?; + if let Some(value) = receipt + .get("cursorCloudTerminalDelivery") + .filter(|value| !value.is_null()) + { + let delivery = + crate::cursor_cloud_proxy::TerminalDelivery::parse(value, &self.thread_id)?; + if Some(delivery.turn_id.as_str()) != expected_turn.as_deref() + || receipt.get("remoteRunId").and_then(Value::as_str) + != Some(delivery.provider_run_id.as_str()) + || receipt.get("status").and_then(Value::as_str) + != Some(delivery.status.as_str()) + { + return Err(LocalRunnerError::invalid( + "Cursor Cloud shutdown changed its terminal delivery", + )); + } + if retain(&delivery)? { + let _ = self.acknowledge_cursor_cloud_terminal(&delivery); + } + } + self.provider_termination_receipt = Some(normalized); + Ok(()) + }) + } else { + Ok(()) + }; + let result = self + .process + .terminate_group() + .map(|_| ()) + .and(remote_termination) + .and(cancellation); if let Some(trace) = self.trace.as_mut() { trace.finish(); } result } + pub(crate) fn provider_termination_receipt(&self) -> Option<&Value> { + self.provider_termination_receipt.as_ref() + } + fn cancel_pending_requests(&mut self) -> Result<(), LocalRunnerError> { let pending_runtime = std::mem::take(&mut self.pending_runtime_requests); let pending = std::mem::take(&mut self.pending_tool_requests); @@ -3203,6 +3388,15 @@ impl CodexProvider { &mut self, method: &str, params: Value, + ) -> Result { + self.request_classified_until(method, params, None) + } + + fn request_classified_until( + &mut self, + method: &str, + params: Value, + deadline: Option, ) -> Result { let request_id = self.next_request_id; self.next_request_id = self.next_request_id.checked_add(1).ok_or_else(|| { @@ -3211,8 +3405,16 @@ impl CodexProvider { self.send_frame(&json!({"id": request_id, "method": method, "params": params})) .map_err(ProviderRequestError::Ambiguous)?; loop { + let remaining = deadline.map_or(Duration::from_secs(30), |deadline| { + deadline.saturating_duration_since(std::time::Instant::now()) + }); + if remaining.is_zero() { + return Err(ProviderRequestError::Ambiguous(LocalRunnerError::invalid( + format!("Provider {method} exceeded its bounded response deadline"), + ))); + } let line = self - .receive_provider_stdout_line(Duration::from_secs(30)) + .receive_provider_stdout_line(remaining) .map_err(ProviderRequestError::Ambiguous)?; let Some(line) = line else { let exit = self @@ -3397,6 +3599,21 @@ fn verified_opencode_launch( Ok(VerifiedProcessLaunch::new(command, args)) } +fn verified_cursor_cloud_launch( + profile: &CursorCloudLaunchProfile, +) -> Result { + let command = verify_launch_artifact(&profile.command, "Cursor Cloud proxy command") + .map_err(|error| LocalRunnerError::invalid(error.to_string()))?; + let proxy = verify_launch_artifact(&profile.proxy_script, "Cursor Cloud proxy script") + .map_err(|error| LocalRunnerError::invalid(error.to_string()))?; + let proxy = if is_node_interpreter(&profile.command.path) { + VerifiedProcessArgument::CommonJsArtifact(proxy) + } else { + VerifiedProcessArgument::Artifact(proxy) + }; + Ok(VerifiedProcessLaunch::new(command, vec![proxy])) +} + fn json_size(value: &Value, label: &str) -> Result { serde_json::to_vec(value) .map(|bytes| bytes.len()) @@ -4852,6 +5069,7 @@ done 1, None, None, + None, &mut |observation| match observation { ProviderStartupObservation::Spawned { process_id, @@ -4926,6 +5144,115 @@ done fs::remove_dir_all(directory).unwrap(); } + #[test] + fn cursor_cloud_proxy_launch_verifies_node_and_script_without_a_native_executable() { + let directory = std::env::temp_dir().join(format!( + "paperclip-cursor-cloud-launch-{}", + uuid::Uuid::new_v4() + )); + fs::create_dir_all(&directory).unwrap(); + let command = directory.join("node"); + let proxy = directory.join("cursor-cloud-proxy.cjs"); + fs::write(&command, b"qualified node").unwrap(); + fs::write(&proxy, b"module.exports = {};\n").unwrap(); + let profile = CursorCloudLaunchProfile { + command: qualified_artifact(&command), + proxy_script: qualified_artifact(&proxy), + }; + let launch = verified_cursor_cloud_launch(&profile); + if cfg!(target_os = "windows") { + let error = match launch { + Ok(_) => panic!("Cursor Cloud Windows launch must remain unsupported"), + Err(error) => error, + }; + assert!(error + .to_string() + .contains("verified process snapshots are supported only on Linux and macOS")); + fs::remove_dir_all(directory).unwrap(); + return; + } + let launch = launch.unwrap(); + assert_eq!(launch.arguments().len(), 1); + assert!(matches!( + launch.arguments().first(), + Some(VerifiedProcessArgument::CommonJsArtifact(_)) + )); + fs::write(&proxy, b"unqualified replacement").unwrap(); + assert!(verified_cursor_cloud_launch(&profile).is_err()); + fs::remove_dir_all(directory).unwrap(); + } + + #[test] + fn cursor_cloud_admission_requires_its_exact_proxy_model_and_provider_permission_boundary() { + let mut config: CodexProviderConfig = serde_json::from_value(json!({ + "provider": "cursor_cloud", "driver": "cursor_cloud_api", + "providerVersion": CURSOR_CLOUD_PROXY_VERSION, "command": "node", + "cwd": std::env::current_dir().unwrap(), "model": "caller-selected-model", + "conversationMode": "prepared", "approvalPolicy": "never" + })) + .unwrap(); + config.validate().unwrap(); + assert_eq!(config.skill_instructions_config(), None); + assert_eq!( + codex_permission_profile("cursor_cloud", false), + "paperclip-runner-provider-managed" + ); + for (field, value) in [ + ("driver", json!("codex_app_server")), + ("providerVersion", json!("unqualified-version")), + ("model", Value::Null), + ("model", json!(" ")), + ("approvalPolicy", json!("on-request")), + ("readOnly", json!(true)), + ("externallySandboxed", json!(true)), + ] { + let mut invalid = serde_json::to_value(&config).unwrap(); + invalid[field] = value; + assert!( + serde_json::from_value::(invalid) + .unwrap() + .validate() + .is_err(), + "{field}" + ); + } + config.model = Some("different-explicit-model".to_owned()); + config.validate().unwrap(); + } + + #[test] + fn cursor_cloud_environment_contains_only_its_selected_provider_and_private_relay_bindings() { + for name in [ + "CURSOR_API_KEY", + "PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH", + "PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH", + "PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN", + "PAPERCLIP_CURSOR_CLOUD_RELAY_URL", + "PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT", + ] { + assert!( + CURSOR_CLOUD_PROVIDER_ENVIRONMENT_KEYS.contains(&name), + "{name}" + ); + } + for name in [ + "CURSOR_AUTH_TOKEN", + "OPENAI_API_KEY", + "CODEX_API_KEY", + "OPENROUTER_API_KEY", + "GITHUB_TOKEN", + "PAPERCLIP_API_KEY", + "PAPERCLIP_NATIVE_MCP_TOKEN", + "NODE_OPTIONS", + "NODE_PATH", + ] { + assert!( + !CURSOR_CLOUD_PROVIDER_ENVIRONMENT_KEYS.contains(&name), + "{name}" + ); + } + } + #[test] fn preserves_prepared_context_in_the_durable_provider_config() { let config: CodexProviderConfig = serde_json::from_value(json!({ diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/configured_environment.rs b/packages/paperclip-runner/runner/crates/runner-core/src/configured_environment.rs index 99950e24c9a..a2d222436b1 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/configured_environment.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/configured_environment.rs @@ -144,6 +144,7 @@ fn eligible_key(key: &str) -> bool { "GIT_CONFIG_", "PAPERCLIP_RUNNER_", "PAPERCLIP_NATIVE_", + "PAPERCLIP_CURSOR_CLOUD_", "PAPERCLIP_GITHUB_", "PAPERCLIP_ACPX_", "PAPERCLIP_VERIFIED_", diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/cursor_cloud_proxy.rs b/packages/paperclip-runner/runner/crates/runner-core/src/cursor_cloud_proxy.rs new file mode 100644 index 00000000000..a2a3b3df166 --- /dev/null +++ b/packages/paperclip-runner/runner/crates/runner-core/src/cursor_cloud_proxy.rs @@ -0,0 +1,171 @@ +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use sha2::{Digest, Sha256}; + +use crate::local_runner::LocalRunnerError; + +pub(crate) const SHUTDOWN_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30); + +fn bounded_id(value: &Value) -> bool { + value + .as_str() + .is_some_and(|id| !id.is_empty() && id.len() <= 240 && !id.chars().any(char::is_control)) +} + +pub(crate) fn shutdown_receipt( + value: &Value, + thread_id: &str, + expected_turn_id: Option<&str>, +) -> Result { + let invalid = || LocalRunnerError::invalid("Cursor Cloud remote termination is unconfirmed"); + if value.get("remoteStopped") != Some(&Value::Bool(true)) + || value.get("threadId").and_then(Value::as_str) != Some(thread_id) + || value.get("turnId").and_then(Value::as_str) != expected_turn_id + || (value + .get("turnId") + .is_some_and(|turn| !turn.is_null() && !bounded_id(turn))) + { + return Err(invalid()); + } + let remote_run = value.get("remoteRunId").ok_or_else(invalid)?; + let remote_agent = value.get("remoteAgentId").unwrap_or(&Value::Null); + if remote_run.is_null() { + if !remote_agent.is_null() && !bounded_id(remote_agent) { + return Err(invalid()); + } + return Ok(json!({ + "schema": "paperclip.cursor-cloud.stop-receipt.v1", + "remoteStopped": true, "threadId": thread_id, "turnId": expected_turn_id, + "remoteAgentId": remote_agent, "remoteRunId": Value::Null, + })); + } + if !bounded_id(remote_run) + || !bounded_id(remote_agent) + || !matches!( + value.get("status").and_then(Value::as_str), + Some("CANCELLED" | "FINISHED" | "ERROR" | "EXPIRED") + ) + { + return Err(invalid()); + } + Ok(json!({ + "schema": "paperclip.cursor-cloud.stop-receipt.v1", + "remoteStopped": true, "threadId": thread_id, "turnId": expected_turn_id, + "remoteAgentId": remote_agent, "remoteRunId": remote_run, "status": value["status"], + })) +} + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub(crate) struct TerminalDelivery { + pub schema: String, + pub thread_id: String, + pub turn_id: String, + pub provider_run_id: String, + pub receipt_id: String, + pub status: String, + pub interrupted: bool, + pub result: Option, +} + +impl TerminalDelivery { + pub(crate) fn parse(value: &Value, thread_id: &str) -> Result { + let invalid = || LocalRunnerError::invalid("Cursor Cloud terminal delivery is invalid"); + let delivery: Self = serde_json::from_value(value.clone()).map_err(|_| invalid())?; + if delivery.schema != "paperclip.cursor-cloud.terminal-delivery.v1" + || delivery.thread_id != thread_id + || ![ + &delivery.thread_id, + &delivery.turn_id, + &delivery.provider_run_id, + &delivery.receipt_id, + ] + .into_iter() + .all(|id| !id.is_empty() && id.len() <= 240 && !id.chars().any(char::is_control)) + || !matches!( + delivery.status.as_str(), + "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED" + ) + || delivery + .result + .as_ref() + .is_some_and(|text| text.len() > 262_144 || text.chars().count() > 65_536) + { + return Err(invalid()); + } + Ok(delivery) + } + + pub(crate) fn method(&self) -> &'static str { + if self.interrupted || self.status == "CANCELLED" { + "turn/interrupted" + } else if self.status == "FINISHED" { + "turn/completed" + } else { + "turn/failed" + } + } + + pub(crate) fn receipt(&self) -> Value { + let bytes = serde_json::to_vec(self).expect("terminal delivery is serializable"); + json!({ "turnId": self.turn_id, "receiptId": self.receipt_id, + "batchDigest": format!("sha256:{:x}", Sha256::digest(bytes)) }) + } + + pub(crate) fn final_params(&self) -> Value { + json!({ "threadId": self.thread_id, "turnId": self.turn_id, + "item": {"id":"final", "type":"agentMessage", "text":self.result} }) + } + + pub(crate) fn terminal_params(&self) -> Value { + let status = self.method().strip_prefix("turn/").unwrap(); + let mut value = json!({ "threadId":self.thread_id, "turnId":self.turn_id, + "turn":{"id":self.turn_id, "status":status}, "cursorCloudTerminalDelivery":self }); + if matches!(self.status.as_str(), "ERROR" | "EXPIRED") { + value["turn"]["error"] = json!({"code":format!("cursor_cloud_{}",self.status.to_lowercase()), + "message":"Cursor Cloud run ended without successful provider completion."}); + } + value + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn remote_stop_requires_exact_local_identity_and_an_authoritative_remote_terminal() { + let receipt = json!({ "remoteStopped": true, "threadId": "thread-1", "turnId": "turn-1", + "remoteAgentId": "agent-remote", "remoteRunId": "run-remote", "status": "CANCELLED" }); + assert_eq!( + shutdown_receipt(&receipt, "thread-1", Some("turn-1")).unwrap()["remoteRunId"], + "run-remote" + ); + for (field, value) in [ + ("threadId", json!("stale-thread")), + ("turnId", json!("stale-turn")), + ("remoteStopped", json!(false)), + ("remoteStopped", json!("true")), + ("remoteRunId", json!("")), + ("remoteAgentId", Value::Null), + ("status", json!("RUNNING")), + ("status", json!("CANCEL_REQUESTED")), + ] { + let mut invalid = receipt.clone(); + invalid[field] = value; + assert!( + shutdown_receipt(&invalid, "thread-1", Some("turn-1")).is_err(), + "{field}" + ); + } + } + + #[test] + fn no_remote_start_requires_an_explicit_null_identity_and_exact_local_scope() { + let receipt = json!({ "remoteStopped": true, "threadId": "thread-1", "turnId": "turn-1", "remoteRunId": null }); + assert!(shutdown_receipt(&receipt, "thread-1", Some("turn-1")).is_ok()); + let mut missing = receipt; + missing.as_object_mut().unwrap().remove("remoteRunId"); + assert!(shutdown_receipt(&missing, "thread-1", Some("turn-1")).is_err()); + } +} diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/durable/mod.rs b/packages/paperclip-runner/runner/crates/runner-core/src/durable/mod.rs index a894798b303..fc33db5cc3c 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/durable/mod.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/durable/mod.rs @@ -195,6 +195,12 @@ pub struct OpenCodeLaunchProfile { pub executable: QualifiedLaunchArtifact, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CursorCloudLaunchProfile { + pub command: QualifiedLaunchArtifact, + pub proxy_script: QualifiedLaunchArtifact, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct DurableRunnerConfig { pub connect_url: String, @@ -210,6 +216,7 @@ pub struct DurableRunnerConfig { pub runner_digest: String, pub acpx_launch_profile: Option, pub opencode_launch_profile: Option, + pub cursor_cloud_launch_profile: Option, pub max_outbox_bytes: usize, pub p0_reserve_bytes: usize, pub max_frame_bytes: usize, @@ -348,6 +355,25 @@ impl DurableRunnerConfig { )); } } + if let Some(profile) = self.cursor_cloud_launch_profile.as_ref() { + if [&profile.command, &profile.proxy_script] + .iter() + .any(|artifact| { + !artifact.path.is_absolute() + || artifact.path.to_str().is_none() + || artifact.sha256.len() != 71 + || !artifact.sha256.starts_with("sha256:") + || !artifact.sha256[7..] + .bytes() + .all(|byte| byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase()) + }) + || profile.command.path == profile.proxy_script.path + { + return Err(DurableRunnerError::invalid( + "Cursor Cloud runner launch profile is malformed", + )); + } + } Ok(()) } } @@ -371,6 +397,7 @@ mod tests { runner_digest: "sha256:digest".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 64 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/durable/runner.rs b/packages/paperclip-runner/runner/crates/runner-core/src/durable/runner.rs index ffb7b00a5f1..13a61f31271 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/durable/runner.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/durable/runner.rs @@ -1394,6 +1394,7 @@ fn wait_for_old_authority_outbox_ack( )?; let target = state.highest_source_seq(); let deadline = Instant::now() + TERMINAL_RESULT_ACK_TIMEOUT; + let mut ack_persistence = CumulativeAckPersistence::default(); while state.acked_source_seq < target { if Instant::now() >= deadline { return Err(DurableRunnerError::invalid( @@ -1410,8 +1411,10 @@ fn wait_for_old_authority_outbox_ack( .pointer("/payload/ackedSourceSeq") .and_then(Value::as_u64) .ok_or_else(|| DurableRunnerError::invalid("ACK cursor is required"))?; - state.apply_ack(acked, connection.protocol_version)?; - store.save(state)?; + // As in normal ingress, checkpoint cumulative ACK bursts + // without fsyncing every prefix inside the delivery deadline. + // The final empty-outbox ACK is always persisted. + ack_persistence.apply(state, store, acked, connection.protocol_version)?; } Some("ping") => transport.send_json(&control_envelope( state, @@ -2546,6 +2549,7 @@ mod tests { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 64 * 1024, p0_reserve_bytes: 4096, max_frame_bytes: 64 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/durable/state.rs b/packages/paperclip-runner/runner/crates/runner-core/src/durable/state.rs index 8943d40f57d..1741d687db2 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/durable/state.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/durable/state.rs @@ -2700,6 +2700,7 @@ mod tests { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 16_384, p0_reserve_bytes: 4096, max_frame_bytes: 65_536, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/durable/transport.rs b/packages/paperclip-runner/runner/crates/runner-core/src/durable/transport.rs index 62134846862..cda7ac7ffc7 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/durable/transport.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/durable/transport.rs @@ -1773,6 +1773,7 @@ mod tests { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 64 * 1024, p0_reserve_bytes: 4096, max_frame_bytes: 64 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/external_provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/src/external_provider_backend.rs index 9da22ddf6e4..fe0d64ce6f8 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/external_provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/external_provider_backend.rs @@ -1077,6 +1077,7 @@ mod tests { runner_digest: "sha256:test".into(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 65536, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/lib.rs b/packages/paperclip-runner/runner/crates/runner-core/src/lib.rs index 50875c5d446..df2670ec9ea 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/lib.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/lib.rs @@ -16,6 +16,7 @@ mod codex_startup_trust; mod codex_usage; mod configured_environment; mod credential_observer; +mod cursor_cloud_proxy; pub mod dot_provider_backend; pub mod durable; pub mod external_provider_backend; diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/managed_provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/src/managed_provider_backend.rs index e5cecabdc97..a8afb907fb4 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/managed_provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/managed_provider_backend.rs @@ -2610,6 +2610,7 @@ mod tests { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/native_provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/src/native_provider_backend.rs index 472d559f9c5..39b6d7400a6 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/native_provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/native_provider_backend.rs @@ -257,7 +257,7 @@ impl NativeProviderCommandExecutor { &self.config, ExternalProviderCodec::Grok, )), - "codex" | "opencode" => SelectedExecutor::LocalFacade( + "codex" | "opencode" | "cursor_cloud" => SelectedExecutor::LocalFacade( CodexCommandExecutor::with_runner_config(&self.state_dir, &self.config), ), "acpx" => SelectedExecutor::Acpx(AcpxCommandExecutor::with_runner_config( diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/src/provider_backend.rs index 2adaafd0420..2dae743c81e 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/provider_backend.rs @@ -21,8 +21,8 @@ use crate::codex_usage::CodexRunUsage; use crate::durable::{ create_private_temporary_file, current_unix_ms, open_private_regular_file, sanitize_value, validate_semantic_tool_input, verify_private_directory, Command, CommandExecution, - CommandExecutor, DurableRunnerConfig, DurableRunnerError, EventPriority, OpenCodeLaunchProfile, - PolledEvent, TerminalDeliveryReconciliation, + CommandExecutor, CursorCloudLaunchProfile, DurableRunnerConfig, DurableRunnerError, + EventPriority, OpenCodeLaunchProfile, PolledEvent, TerminalDeliveryReconciliation, }; use crate::provider_bridge::{ authorized_tool_catalog_digest, semantic_value_digest, AuthorizedToolSet, DurableReplayFilter, @@ -435,29 +435,42 @@ fn semantic_result_event( } } -fn validate_opencode_run_result( +fn facade_provider_name(provider: &str) -> &'static str { + match provider { + "opencode" => "OpenCode", + "cursor_cloud" => "Cursor Cloud", + _ => "Codex", + } +} + +fn validate_proxy_run_result( state: &CodexProviderState, params: &Value, ) -> Result<(Value, String, String), DurableRunnerError> { - if state.config.provider != "opencode" { + if !matches!(state.config.provider.as_str(), "opencode" | "cursor_cloud") { return Err(DurableRunnerError::invalid( - "paperclip/runResult is reserved for the verified OpenCode provider", + "paperclip/runResult is reserved for verified provider proxies", )); } if state.lifecycle != "turn_active" || state.active_provider_turn_id.is_none() { - return Err(DurableRunnerError::invalid( - "OpenCode emitted paperclip/runResult without an active provider turn", - )); + return Err(DurableRunnerError::invalid(format!( + "{} emitted paperclip/runResult without an active provider turn", + facade_provider_name(&state.config.provider) + ))); } if params.get("threadId").and_then(Value::as_str) != state.thread_id.as_deref() || params.get("turnId").and_then(Value::as_str) != state.active_provider_turn_id.as_deref() { - return Err(DurableRunnerError::invalid( - "OpenCode paperclip/runResult is not bound to the active provider turn", - )); + return Err(DurableRunnerError::invalid(format!( + "{} paperclip/runResult is not bound to the active provider turn", + facade_provider_name(&state.config.provider) + ))); } let result = params.get("result").cloned().ok_or_else(|| { - DurableRunnerError::invalid("OpenCode paperclip/runResult omitted its result") + DurableRunnerError::invalid(format!( + "{} paperclip/runResult omitted its result", + facade_provider_name(&state.config.provider) + )) })?; let (fingerprint, disposition) = validate_run_result(state, &result)?; Ok((result, fingerprint, disposition)) @@ -480,23 +493,31 @@ fn validate_run_result( )); } let contract = state.completion_contract.as_ref().ok_or_else(|| { - DurableRunnerError::invalid("OpenCode paperclip/runResult has no bound completion contract") + DurableRunnerError::invalid(format!( + "{} paperclip/runResult has no bound completion contract", + facade_provider_name(&state.config.provider) + )) })?; let claim = result.get("completionClaim").ok_or_else(|| { - DurableRunnerError::invalid("OpenCode paperclip/runResult omitted its completion claim") + DurableRunnerError::invalid(format!( + "{} paperclip/runResult omitted its completion claim", + facade_provider_name(&state.config.provider) + )) })?; if claim.get("contractRevision").and_then(Value::as_str) != Some(contract.revision.as_str()) { - return Err(DurableRunnerError::invalid( - "OpenCode paperclip/runResult changed its completion contract revision", - )); + return Err(DurableRunnerError::invalid(format!( + "{} paperclip/runResult changed its completion contract revision", + facade_provider_name(&state.config.provider) + ))); } let criteria = claim .get("criteria") .and_then(Value::as_array) .ok_or_else(|| { - DurableRunnerError::invalid( - "OpenCode paperclip/runResult omitted its completion criteria", - ) + DurableRunnerError::invalid(format!( + "{} paperclip/runResult omitted its completion criteria", + facade_provider_name(&state.config.provider) + )) })?; let mut reported_criterion_ids = HashSet::new(); for criterion in criteria { @@ -504,14 +525,16 @@ fn validate_run_result( .get("criterionId") .and_then(Value::as_str) .ok_or_else(|| { - DurableRunnerError::invalid( - "OpenCode paperclip/runResult has an invalid completion criterion", - ) + DurableRunnerError::invalid(format!( + "{} paperclip/runResult has an invalid completion criterion", + facade_provider_name(&state.config.provider) + )) })?; if !reported_criterion_ids.insert(criterion_id) { - return Err(DurableRunnerError::invalid( - "OpenCode paperclip/runResult repeated a completion criterion", - )); + return Err(DurableRunnerError::invalid(format!( + "{} paperclip/runResult repeated a completion criterion", + facade_provider_name(&state.config.provider) + ))); } } if reported_criterion_ids.len() != contract.criterion_ids.len() @@ -520,9 +543,10 @@ fn validate_run_result( .iter() .all(|criterion_id| reported_criterion_ids.contains(criterion_id.as_str())) { - return Err(DurableRunnerError::invalid( - "OpenCode paperclip/runResult changed its bound completion criteria", - )); + return Err(DurableRunnerError::invalid(format!( + "{} paperclip/runResult changed its bound completion criteria", + facade_provider_name(&state.config.provider) + ))); } let disposition = result .get("reportedWorkDisposition") @@ -721,7 +745,7 @@ fn normalize_provider_notification( .map(|event| relabel_provider_event(event, &state.config.provider)) .collect()); } - let (result, fingerprint, disposition) = validate_opencode_run_result(state, params)?; + let (result, fingerprint, disposition) = validate_proxy_run_result(state, params)?; match ( state.active_provider_result_fingerprint.as_deref(), state.active_provider_result_disposition.as_deref(), @@ -741,9 +765,10 @@ fn normalize_provider_notification( { Ok(Vec::new()) } - _ => Err(DurableRunnerError::invalid( - "OpenCode emitted conflicting paperclip/runResult notifications for one turn", - )), + _ => Err(DurableRunnerError::invalid(format!( + "{} emitted conflicting paperclip/runResult notifications for one turn", + facade_provider_name(&state.config.provider) + ))), } } @@ -809,7 +834,7 @@ fn terminal_events( // revoke the already-authoritative semantic outcome. let succeeded = goal_status == Some("complete") || (goal_status.is_none() - && (event_type == "turn.completed" + && ((event_type == "turn.completed" && state.config.provider != "cursor_cloud") || state.active_provider_result_fingerprint.is_some())); let cancelled = matches!(event_type, "turn.cancelled" | "turn.interrupted"); let disposition = match goal_status { @@ -822,11 +847,7 @@ fn terminal_events( .unwrap_or(if succeeded { "done" } else { "needs_review" }), }; let provider = state.config.provider.as_str(); - let provider_name = if provider == "opencode" { - "OpenCode" - } else { - "Codex" - }; + let provider_name = facade_provider_name(provider); let summary = state.last_agent_message.clone().unwrap_or_else(|| { if succeeded { format!("{provider_name} completed the requested work.") @@ -876,7 +897,9 @@ fn terminal_events( })] }, "artifacts": [], }); - let turn_terminal_state = if succeeded { + let turn_terminal_state = if succeeded + || (state.config.provider == "cursor_cloud" && event_type == "turn.completed") + { "completed" } else if event_type == "turn.interrupted" { "interrupted" @@ -1131,6 +1154,12 @@ struct CodexProviderState { config: CodexProviderConfig, #[serde(default)] opencode_launch_profile_digest: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + cursor_cloud_launch_profile_digest: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + provider_termination_receipt: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + cursor_cloud_terminal_receipt: Option, #[serde(default)] codex_usage: Option, #[serde(default)] @@ -1243,6 +1272,9 @@ impl CodexProviderState { lifecycle: "prepared".to_owned(), config, opencode_launch_profile_digest: None, + cursor_cloud_launch_profile_digest: None, + provider_termination_receipt: None, + cursor_cloud_terminal_receipt: None, codex_usage, previous_accounting_origin: None, completion_contract, @@ -1277,6 +1309,104 @@ impl CodexProviderState { } } + fn retain_cursor_cloud_terminal_delivery( + &mut self, + delivery: &crate::cursor_cloud_proxy::TerminalDelivery, + identity: Option<&ProviderEventIdentity>, + process_generation: u64, + ) -> Result<(), DurableRunnerError> { + let invalid = || { + DurableRunnerError::invalid( + "Cursor Cloud terminal delivery conflicts with durable ownership", + ) + }; + if self.config.provider != "cursor_cloud" + || self.thread_id.as_deref() != Some(delivery.thread_id.as_str()) + { + return Err(invalid()); + } + let receipt = delivery.receipt(); + if self + .cursor_cloud_terminal_receipt + .as_ref() + .is_some_and(|saved| { + saved.get("turnId").and_then(Value::as_str) == Some(delivery.turn_id.as_str()) + }) + { + if self.cursor_cloud_terminal_receipt.as_ref() != Some(&receipt) + || self.active_provider_turn_id.as_deref() == Some(delivery.turn_id.as_str()) + || !settled_provider_turn_contains( + &self.settled_provider_turn_ids, + &self.settled_provider_turn_filter, + &delivery.turn_id, + ) + { + return Err(invalid()); + } + return Ok(()); + } + if self.active_provider_turn_id.as_deref() != Some(delivery.turn_id.as_str()) + || settled_provider_turn_contains( + &self.settled_provider_turn_ids, + &self.settled_provider_turn_filter, + &delivery.turn_id, + ) + || self + .last_agent_message + .as_ref() + .is_some_and(|text| delivery.result.as_ref() != Some(text)) + { + return Err(invalid()); + } + if self.last_agent_message.is_none() { + if let Some(text) = &delivery.result { + let events = normalize_provider_notification( + self, + "item/completed", + &delivery.final_params(), + )?; + self.extend_terminal_events(events)?; + self.last_agent_message = Some(text.clone()); + } + } + let normalized = + normalize_provider_notification(self, delivery.method(), &delivery.terminal_params())?; + self.settle_active_provider_turn_identity()?; + let settled = self + .tool_bridge + .settle_turn("provider_turn_terminated") + .map_err(|error| DurableRunnerError::invalid(error.to_string()))?; + for result in settled { + let identity = identity.ok_or_else(|| { + DurableRunnerError::invalid( + "Cursor Cloud terminal tool settlement has no durable identity", + ) + })?; + self.push_terminal_event(semantic_result_event(identity, &result))?; + } + self.active_provider_turn_id = None; + self.ambiguous_turn_start_pending = false; + self.completed_turn_authoritative = delivery.method() == "turn/completed" + || self.active_provider_result_fingerprint.is_some(); + self.completed_turn_process_generation = self + .completed_turn_authoritative + .then_some(process_generation); + self.completed_provider_turn_id = self + .completed_turn_authoritative + .then(|| delivery.turn_id.clone()); + self.receipt_limit_diagnostic_emitted = false; + self.receipt_limit_interrupt_pending = false; + self.receipt_limit_interrupt_accepted = false; + self.receipt_limit_interrupt_attempts = 0; + self.receipt_limit_interrupt_deadline_unix_ms = None; + self.lifecycle = "session_open".to_owned(); + let event_type = delivery.method().replace('/', "."); + let outcome = terminal_events(self, &event_type, None); + self.extend_terminal_events(with_terminal_outcome(normalized, outcome))?; + self.cursor_cloud_terminal_receipt = Some(receipt); + Ok(()) + } + fn validate(&self) -> Result<(), DurableRunnerError> { if let Some(attempt) = &self.startup_attempt { attempt.validate()?; @@ -1287,6 +1417,38 @@ impl CodexProviderState { self.tool_bridge.validate_recovered().map_err(|error| { DurableRunnerError::invalid(format!("Codex semantic tool state is invalid: {error}")) })?; + if let Some(receipt) = &self.cursor_cloud_terminal_receipt { + let turn_id = receipt + .get("turnId") + .and_then(Value::as_str) + .unwrap_or_default(); + let receipt_id = receipt + .get("receiptId") + .and_then(Value::as_str) + .unwrap_or_default(); + let digest = receipt + .get("batchDigest") + .and_then(Value::as_str) + .unwrap_or_default(); + if self.config.provider != "cursor_cloud" + || turn_id.is_empty() + || turn_id.len() > 240 + || receipt_id.is_empty() + || receipt_id.len() > 240 + || !digest.strip_prefix("sha256:").is_some_and(|digest| { + digest.len() == 64 && digest.bytes().all(|byte| byte.is_ascii_hexdigit()) + }) + || !settled_provider_turn_contains( + &self.settled_provider_turn_ids, + &self.settled_provider_turn_filter, + turn_id, + ) + { + return Err(DurableRunnerError::invalid( + "Cursor Cloud retained terminal receipt is invalid", + )); + } + } if self .codex_usage .as_ref() @@ -1412,7 +1574,10 @@ impl CodexProviderState { .as_deref() .is_some_and(|disposition| { !matches!(disposition, "done" | "blocked" | "needs_review" | "yielded") - || !matches!(self.config.provider.as_str(), "codex" | "opencode") + || !matches!( + self.config.provider.as_str(), + "codex" | "opencode" | "cursor_cloud" + ) }) || (matches!( self.lifecycle.as_str(), @@ -1705,6 +1870,7 @@ pub struct CodexCommandExecutor { restore_checked: bool, restore_error: Option, opencode_launch_profile: Option, + cursor_cloud_launch_profile: Option, startup_command: Option, startup_evidence_error: Option, } @@ -1719,6 +1885,7 @@ impl CodexCommandExecutor { restore_checked: false, restore_error: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, startup_command: None, startup_evidence_error: None, } @@ -1728,6 +1895,7 @@ impl CodexCommandExecutor { let mut executor = Self::new(state_dir); executor.event_identity = Some(ProviderEventIdentity::from_config(config)); executor.opencode_launch_profile = config.opencode_launch_profile.clone(); + executor.cursor_cloud_launch_profile = config.cursor_cloud_launch_profile.clone(); executor } @@ -1762,6 +1930,37 @@ impl CodexCommandExecutor { Ok(Some(format!("sha256:{:x}", digest.finalize()))) } + fn bind_cursor_cloud_launch_profile( + &self, + config: &CodexProviderConfig, + ) -> Result, DurableRunnerError> { + if config.provider != "cursor_cloud" { + return Ok(None); + } + let profile = self.cursor_cloud_launch_profile.as_ref().ok_or_else(|| { + DurableRunnerError::invalid( + "Cursor Cloud runner startup omitted its qualified launch profile", + ) + })?; + let proxy_script = profile.proxy_script.path.to_string_lossy(); + if config.command != profile.command.path + || config.args.as_slice() != [proxy_script.as_ref()] + { + return Err(DurableRunnerError::invalid( + "Cursor Cloud run.prepare launch does not match the runner-owned qualified profile", + )); + } + let mut digest = Sha256::new(); + digest.update(b"paperclip.runner.cursor-cloud-launch-profile.v1\0"); + for artifact in [&profile.command, &profile.proxy_script] { + digest.update(artifact.path.to_string_lossy().as_bytes()); + digest.update(b"\0"); + digest.update(artifact.sha256.as_bytes()); + digest.update(b"\0"); + } + Ok(Some(format!("sha256:{:x}", digest.finalize()))) + } + fn state_path(&self) -> PathBuf { self.state_dir.join(CODEX_PROVIDER_STATE_FILE) } @@ -1879,6 +2078,7 @@ impl CodexCommandExecutor { .clone() .ok_or_else(|| DurableRunnerError::invalid("provider startup state missing"))?; let profile = self.opencode_launch_profile.clone(); + let cursor_cloud_profile = self.cursor_cloud_launch_profile.clone(); self.begin_startup(trigger, generation)?; CodexProvider::start_with_tools_observed( &state.config, @@ -1886,6 +2086,7 @@ impl CodexCommandExecutor { state.thread_id.as_deref(), generation, profile.as_ref(), + cursor_cloud_profile.as_ref(), state.completion_contract.as_ref().map(|contract| { ( contract.revision.as_str(), @@ -1898,9 +2099,26 @@ impl CodexCommandExecutor { }) }, ) - .map(|mut provider| { + .and_then(|mut provider| { provider.restore_descendant_thread_identities(&state.descendant_thread_ids); - provider + if state.config.provider == "cursor_cloud" && state.active_provider_turn_id.is_none() { + if let Some(receipt) = &state.cursor_cloud_terminal_receipt { + let acknowledged = (|| { + if let Some(delivery) = provider.cursor_cloud_terminal_delivery()? { + if delivery.receipt() != *receipt { + return Err(crate::local_runner::LocalRunnerError::invalid("Cursor Cloud retained terminal delivery changed across attachment")); + } + let _ = provider.acknowledge_cursor_cloud_terminal(&delivery); + } + Ok(()) + })(); + if let Err(error) = acknowledged { + self.fail_started_provider(&mut provider); + return Err(error); + } + } + } + Ok(provider) }) .map_err(|error| { DurableRunnerError::invalid(format!( @@ -1996,6 +2214,13 @@ impl CodexCommandExecutor { "OpenCode runner launch profile changed across durable recovery", )); } + let expected_cursor_cloud_profile_digest = + self.bind_cursor_cloud_launch_profile(&state.config)?; + if state.cursor_cloud_launch_profile_digest != expected_cursor_cloud_profile_digest { + return Err(DurableRunnerError::invalid( + "Cursor Cloud runner launch profile changed across durable recovery", + )); + } self.state = Some(state); Ok(()) } @@ -2014,11 +2239,7 @@ impl CodexCommandExecutor { return Ok(()); } let provider_label = state.config.provider.clone(); - let provider_name = if provider_label == "opencode" { - "OpenCode" - } else { - "Codex" - }; + let provider_name = facade_provider_name(&provider_label); let provider_had_exited = state.lifecycle == "provider_exited"; let thread_id = state.thread_id.clone().ok_or_else(|| { DurableRunnerError::invalid(format!( @@ -2066,6 +2287,41 @@ impl CodexCommandExecutor { "failed to restore local provider turn identities: {error}" )) })?; + if let Some(delivery) = provider + .cursor_cloud_terminal_delivery() + .map_err(|error| DurableRunnerError::invalid(error.to_string()))? + { + if provider.active_provider_turn_id().is_some() { + return Err(DurableRunnerError::invalid( + "Cursor Cloud terminal delivery also reports active remote work", + )); + } + let identity = self.event_identity.clone(); + let state = self.state.as_mut().expect("provider state remains loaded"); + state.provider_process_generation = process_generation; + state.provider_session_id = provider.provider_session_id().map(str::to_owned); + state.retain_cursor_cloud_terminal_delivery( + &delivery, + identity.as_ref(), + process_generation, + )?; + provider + .restore_settled_turn_identities( + state.settled_provider_turn_ids.iter().cloned(), + state.settled_provider_turn_filter.clone(), + ) + .map_err(|error| DurableRunnerError::invalid(error.to_string()))?; + provider + .restore_completed_turn_authority( + state.completed_turn_authoritative, + state.completed_turn_process_generation, + state.completed_provider_turn_id.as_deref(), + ) + .map_err(|error| DurableRunnerError::invalid(error.to_string()))?; + self.commit_startup_admission()?; + let _ = provider.acknowledge_cursor_cloud_terminal(&delivery); + return Ok(()); + } let recovered_active_turn_id = provider.active_provider_turn_id().map(str::to_owned); let recovered_turn_ended_with_result = active_provider_result_authoritative && previous_active_turn_id.is_some() @@ -2455,6 +2711,7 @@ impl CodexCommandExecutor { let provider_name = config.provider.clone(); let driver = config.driver.clone(); let opencode_launch_profile_digest = self.bind_opencode_launch_profile(&config)?; + let cursor_cloud_launch_profile_digest = self.bind_cursor_cloud_launch_profile(&config)?; let completion_contract = completion_contract(payload)?; let tool_set = authorized_tool_set(payload)?; if let Some(state) = self.state.as_mut() { @@ -2468,6 +2725,11 @@ impl CodexCommandExecutor { "OpenCode runner launch profile changed across the durable run", )); } + if state.cursor_cloud_launch_profile_digest != cursor_cloud_launch_profile_digest { + return Err(DurableRunnerError::invalid( + "Cursor Cloud runner launch profile changed across the durable run", + )); + } if state.lifecycle == "closed" { return Err(DurableRunnerError::invalid( "Codex provider session is already closed", @@ -2497,6 +2759,7 @@ impl CodexCommandExecutor { })?; let mut state = CodexProviderState::new(config, completion_contract, tool_bridge); state.opencode_launch_profile_digest = opencode_launch_profile_digest; + state.cursor_cloud_launch_profile_digest = cursor_cloud_launch_profile_digest; self.state = Some(state); self.save_state()?; } @@ -2744,6 +3007,13 @@ impl CodexCommandExecutor { next_state.config.include_skill_instructions = config.include_skill_instructions; upgraded_skill_config = true; } + if next_state.config.provider == "cursor_cloud" + && config.provider == "cursor_cloud" + && self.provider.is_none() + && next_state.lifecycle == "prepared" + { + next_state.config.instructions = config.instructions.clone(); + } if config != next_state.config { return Err(DurableRunnerError::invalid( "run.attach cannot change the durable Codex provider profile", @@ -2887,6 +3157,10 @@ impl CodexCommandExecutor { .as_ref() .and_then(|state| state.thread_id.as_ref()) .is_some(); + let cloud_proxy = self + .state + .as_ref() + .is_some_and(|state| state.config.provider == "cursor_cloud"); let ( thread_id, provider_session_id, @@ -2901,16 +3175,24 @@ impl CodexCommandExecutor { provider.provider_session_id().map(str::to_owned), provider.process_id(), provider.active_provider_turn_id().map(str::to_owned), - provider.get_goal(), + if cloud_proxy { + None + } else { + Some(provider.get_goal()) + }, provider.observed_model().map(str::to_owned), ) }; let (goal_capability, goal) = match goal_probe { - Ok(snapshot) => ( + None => ( + SessionGoalCapability::unavailable("unsupported", "provider_goals_unavailable"), + None, + ), + Some(Ok(snapshot)) => ( SessionGoalCapability::codex_available(), normalize_codex_goal(&snapshot, active_provider_turn_id.is_some()), ), - Err(error) => { + Some(Err(error)) => { let message = error.to_string().to_ascii_lowercase(); if message.contains("policy") || message.contains("disabled") @@ -3042,11 +3324,7 @@ impl CodexCommandExecutor { state.last_agent_message = None; state.lifecycle = "closed".to_owned(); let provider_label = state.config.provider.clone(); - let provider_name = if provider_label == "opencode" { - "OpenCode" - } else { - "Codex" - }; + let provider_name = facade_provider_name(&provider_label); // Closure is the safety boundary. Preserve it even if a saturated // event queue cannot retain this additional diagnostic. let _ = state.push_terminal_event(NormalizedProviderEvent { @@ -3367,6 +3645,7 @@ impl CodexCommandExecutor { .as_mut() .expect("Codex state exists after turn start"); state.active_provider_turn_id = Some(provider_turn_id.clone()); + state.provider_termination_receipt = None; state.ambiguous_turn_start_pending = false; state.completed_turn_authoritative = false; state.completed_turn_process_generation = None; @@ -3463,23 +3742,18 @@ impl CodexCommandExecutor { // the exact owned generation without another cooperative interrupt. // Resume may discover that the old turn already ended; its newly // resumed process still needs the same exit and prepared-state proof. - let provider_shutdown_failed = self - .provider - .as_mut() - .is_some_and(|provider| provider.shutdown().is_err()); - if provider_shutdown_failed { - return Err(DurableRunnerError::invalid( - "failed to prove provider termination at the suspension boundary", - )); - } - self.provider = None; + self.stop_owned_provider().map_err(|error| { + DurableRunnerError::invalid(format!( + "failed to prove provider termination at the suspension boundary: {error}" + )) + })?; let identity = self.event_identity()?; let state = self .state .as_mut() .expect("Codex state remains available after provider termination"); - if provider_turn_id.is_some() { + if state.active_provider_turn_id.is_some() { state.settle_active_provider_turn_identity()?; } let settled = state @@ -3511,14 +3785,19 @@ impl CodexCommandExecutor { // fresh provider process. `prepared` retains the durable thread while // deferring the only authorized restart to the successor run.attach. state.lifecycle = "prepared".to_owned(); + let provider_termination_receipt = state.provider_termination_receipt.clone(); self.save_state()?; - Ok(CommandExecution::result(json!({ + let mut result = json!({ "status": if provider_turn_id.is_some() { "stopped" } else { "already_settled" }, "providerTurnId": provider_turn_id, "reason": reason, "interruptAccepted": false, "providerExitConfirmed": true, - }))) + }); + if let Some(receipt) = provider_termination_receipt { + result["providerTerminationReceipt"] = receipt; + } + Ok(CommandExecution::result(result)) } fn steer_turn(&mut self, payload: &Value) -> Result { @@ -3727,11 +4006,7 @@ impl CodexCommandExecutor { .as_ref() .map(|state| state.config.provider.clone()) .unwrap_or_else(|| "codex".to_owned()); - let provider_name = if provider_label == "opencode" { - "OpenCode" - } else { - "Codex" - }; + let provider_name = facade_provider_name(&provider_label); if self .state .as_ref() @@ -3946,11 +4221,7 @@ impl CodexCommandExecutor { "turn.failed" }; let provider_label = state.config.provider.clone(); - let provider_name = if provider_label == "opencode" { - "OpenCode" - } else { - "Codex" - }; + let provider_name = facade_provider_name(&provider_label); let provider_terminal = NormalizedProviderEvent { event_type: terminal_event_type.to_owned(), priority: EventPriority::P0, @@ -4202,13 +4473,74 @@ impl CodexCommandExecutor { }))) } - fn close_session(&mut self) -> Result { - if let Some(provider) = self.provider.as_mut() { - provider.shutdown().map_err(|error| { - DurableRunnerError::invalid(format!("failed to stop Codex provider: {error}")) - })?; + fn stop_owned_provider(&mut self) -> Result<(), DurableRunnerError> { + let cloud_proxy = self + .state + .as_ref() + .is_some_and(|state| state.config.provider == "cursor_cloud"); + if self.provider.is_none() { + if cloud_proxy + && self.state.as_ref().is_some_and(|state| { + state.active_provider_turn_id.is_some() + || state.ambiguous_turn_start_pending + || state.lifecycle == "reconciliation_required" + }) + { + return Err(DurableRunnerError::invalid( + "Cursor Cloud remote termination is unconfirmed", + )); + } + return Ok(()); } - self.provider = None; + let mut provider = self.provider.take().expect("provider is present"); + let stopped = if cloud_proxy { + provider.shutdown_with_cursor_cloud_delivery(|delivery| { + let mut next = self.state.clone().expect("provider state is present"); + let generation = next.provider_process_generation; + next.retain_cursor_cloud_terminal_delivery( + delivery, + self.event_identity.as_ref(), + generation, + ) + .map_err(|error| { + crate::local_runner::LocalRunnerError::invalid(error.to_string()) + })?; + self.persist_state(&next).map_err(|error| { + crate::local_runner::LocalRunnerError::invalid(error.to_string()) + })?; + self.state = Some(next); + Ok(true) + }) + } else { + provider.shutdown() + }; + let receipt = provider.provider_termination_receipt().cloned(); + if !cloud_proxy && stopped.is_err() { + self.provider = Some(provider); + } + stopped.map_err(|error| { + DurableRunnerError::invalid(format!("failed to stop provider: {error}")) + })?; + if cloud_proxy { + let receipt = receipt.ok_or_else(|| { + DurableRunnerError::invalid("Cursor Cloud remote termination receipt is missing") + })?; + let mut next = self.state.clone().expect("provider state is present"); + next.provider_termination_receipt = Some(receipt); + if next.lifecycle == "session_open" + && next.active_provider_turn_id.is_none() + && !next.ambiguous_turn_start_pending + { + next.lifecycle = "prepared".to_owned(); + } + self.persist_state(&next)?; + self.state = Some(next); + } + Ok(()) + } + + fn close_session(&mut self) -> Result { + self.stop_owned_provider()?; let state = self .state .as_mut() @@ -4226,9 +4558,14 @@ impl CodexCommandExecutor { state.lifecycle = "closed".to_owned(); let thread_id = state.thread_id.clone(); let provider_name = state.config.provider.clone(); + let provider_termination_receipt = state.provider_termination_receipt.clone(); self.save_state()?; + let mut result = json!({"status": "closed", "providerSessionId": thread_id}); + if let Some(receipt) = provider_termination_receipt { + result["providerTerminationReceipt"] = receipt; + } Ok(CommandExecution { - result: json!({"status": "closed", "providerSessionId": thread_id}), + result, events: vec![( "session.closed".to_owned(), EventPriority::P0, @@ -4453,6 +4790,26 @@ impl CodexCommandExecutor { }; let normalized_terminal_type = normalized_codex_terminal_event_type(&method, ¶ms); + let cursor_cloud_delivery = if self + .state + .as_ref() + .is_some_and(|state| state.config.provider == "cursor_cloud") + && normalized_terminal_type.is_some() + { + params.get("cursorCloudTerminalDelivery").map(|value| { + let state = self.state.as_ref().expect("provider state remains loaded"); + let delivery = crate::cursor_cloud_proxy::TerminalDelivery::parse(value, state.thread_id.as_deref().unwrap_or_default()) + .map_err(|error| DurableRunnerError::invalid(error.to_string()))?; + if state.active_provider_turn_id.as_deref() != Some(delivery.turn_id.as_str()) + || delivery.method() != method + || state.last_agent_message.as_ref() != delivery.result.as_ref() { + return Err(DurableRunnerError::invalid("Cursor Cloud terminal notification changed its retained delivery")); + } + Ok(delivery) + }).transpose()? + } else { + None + }; let result_authoritative = normalized_terminal_type.is_some() && self.state.as_ref().is_some_and(|state| { state.active_provider_result_fingerprint.is_some() @@ -4685,6 +5042,9 @@ impl CodexCommandExecutor { } else { state.extend_events(normalized)?; } + if let Some(delivery) = &cursor_cloud_delivery { + state.cursor_cloud_terminal_receipt = Some(delivery.receipt()); + } let trace_last_event_sequence = state.next_provider_event_seq; let trace_emitted_event_ids = identity .as_ref() @@ -4703,6 +5063,11 @@ impl CodexCommandExecutor { { break; } + if let (Some(delivery), Some(provider)) = + (cursor_cloud_delivery.as_ref(), self.provider.as_mut()) + { + let _ = provider.acknowledge_cursor_cloud_terminal(delivery); + } if let (Some(frame_id), Some(provider)) = (trace_frame_id, self.provider.as_mut()) { @@ -4763,7 +5128,7 @@ impl CodexCommandExecutor { "prompt": prompt, "input": question_set, "origin": { - "adapter": if state.config.provider == "opencode" { "opencode-server" } else { "codex-app-server" }, + "adapter": match state.config.provider.as_str() { "opencode" => "opencode-server", "cursor_cloud" => "cursor-cloud-api", _ => "codex-app-server" }, "provider": state.config.provider, "method": "item/tool/requestUserInput", }, @@ -4985,12 +5350,7 @@ impl CommandExecutor for CodexCommandExecutor { // attempted against the persisted session instead of reporting a // successful no-op from an empty in-memory provider slot. self.restore()?; - if let Some(provider) = self.provider.as_mut() { - provider.shutdown().map_err(|error| { - DurableRunnerError::invalid(format!("failed to stop Codex provider: {error}")) - })?; - } - self.provider = None; + self.stop_owned_provider()?; Ok(()) } @@ -5000,12 +5360,7 @@ impl CommandExecutor for CodexCommandExecutor { // A fresh terminal-delivery process has no provider handle. Validate // its retained state without starting a provider merely to stop it. // If this process already owns a handle, stop only that exact handle. - if let Some(provider) = self.provider.as_mut() { - provider.shutdown().map_err(|error| { - DurableRunnerError::invalid(format!("failed to stop Codex provider: {error}")) - })?; - self.provider = None; - } + self.stop_owned_provider()?; if self.state.is_none() { self.load_state_without_provider()?; } @@ -5482,6 +5837,120 @@ mod tests { assert!(state.validate().is_ok()); } + fn cursor_cloud_result_state() -> CodexProviderState { + let mut state = opencode_result_state(); + state.config.provider = "cursor_cloud".to_owned(); + state.config.driver = "cursor_cloud_api".to_owned(); + state.config.provider_version = "cursor-cloud-v1".to_owned(); + state.config.model = Some("caller-selected-model".to_owned()); + state + } + + #[test] + fn cursor_cloud_terminal_receipts_reject_unowned_and_changed_delivery() { + let batch = json!({"schema":"paperclip.cursor-cloud.terminal-delivery.v1", "threadId":"thread-1", "turnId":"turn-1", "providerRunId":"run-provider", "receiptId":"receipt-1", "status":"FINISHED", "interrupted":false, "result":"Durable final"}); + let delivery = + crate::cursor_cloud_proxy::TerminalDelivery::parse(&batch, "thread-1").unwrap(); + let mut state = cursor_cloud_result_state(); + state + .retain_cursor_cloud_terminal_delivery(&delivery, None, 1) + .unwrap(); + let events = state.pending_events.clone(); + state + .retain_cursor_cloud_terminal_delivery(&delivery, None, 2) + .unwrap(); + assert_eq!(state.pending_events, events); + let mut changed = batch.clone(); + changed["result"] = json!("Conflicting final"); + let changed = + crate::cursor_cloud_proxy::TerminalDelivery::parse(&changed, "thread-1").unwrap(); + assert!(state + .retain_cursor_cloud_terminal_delivery(&changed, None, 2) + .is_err()); + let mut unowned = cursor_cloud_result_state(); + unowned.active_provider_turn_id = None; + assert!(unowned + .retain_cursor_cloud_terminal_delivery(&delivery, None, 1) + .is_err()); + let mut partial = cursor_cloud_result_state(); + partial.last_agent_message = Some("Different persisted final".to_owned()); + assert!(partial + .retain_cursor_cloud_terminal_delivery(&delivery, None, 1) + .is_err()); + } + + #[test] + fn cursor_cloud_native_completion_without_semantic_acceptance_requires_review() { + let state = cursor_cloud_result_state(); + let events = terminal_events(&state, "turn.completed", None); + assert_eq!(events[0].event_type, "run.result.proposed"); + assert_eq!(events[0].payload["reportedWorkDisposition"], "needs_review"); + assert_eq!( + events[0].payload["completionClaim"]["objectiveSatisfied"], + false + ); + assert_eq!( + events[0].payload["completionClaim"]["criteria"][0]["status"], + "unknown" + ); + assert_eq!(events[1].payload["provider"], "cursor_cloud"); + assert_eq!(events[1].payload["turnTerminalState"], "completed"); + assert_eq!(events[1].payload["runTerminalState"], "failed"); + assert!(events[0].payload["summary"] + .as_str() + .unwrap() + .contains("Cursor Cloud")); + } + + #[test] + fn cursor_cloud_correlated_proxy_result_is_preserved_once_and_fenced_to_the_active_turn() { + let mut state = cursor_cloud_result_state(); + let params = json!({ "threadId": "thread-1", "turnId": "turn-1", "result": valid_opencode_result() }); + let events = + normalize_provider_notification(&mut state, "paperclip/runResult", ¶ms).unwrap(); + assert_eq!(events.len(), 1); + assert_eq!(events[0].event_type, "run.result.proposed"); + assert!( + normalize_provider_notification(&mut state, "paperclip/runResult", ¶ms) + .unwrap() + .is_empty() + ); + let terminal = terminal_events(&state, "turn.completed", None); + assert_eq!(terminal.len(), 1); + assert_eq!(terminal[0].payload["provider"], "cursor_cloud"); + assert_eq!(terminal[0].payload["runTerminalState"], "succeeded"); + let mut wrong_turn = params.clone(); + wrong_turn["turnId"] = json!("stale-turn"); + assert!( + normalize_provider_notification(&mut state, "paperclip/runResult", &wrong_turn) + .is_err() + ); + let mut changed = params; + changed["result"]["summary"] = json!("different completion"); + assert!( + normalize_provider_notification(&mut state, "paperclip/runResult", &changed).is_err() + ); + } + + #[test] + fn cursor_cloud_accepted_terminal_tool_preserves_success_without_synthesizing_a_result() { + let mut state = cursor_cloud_result_state(); + admit_terminal_tool_authority( + &mut state, + "paperclip_finish", + &valid_opencode_result(), + false, + ) + .unwrap(); + let terminal = terminal_events(&state, "turn.completed", None); + assert_eq!(terminal.len(), 1); + assert_eq!(terminal[0].event_type, "run.terminal"); + assert_eq!(terminal[0].payload["provider"], "cursor_cloud"); + assert_eq!(terminal[0].payload["reportedWorkDisposition"], "done"); + assert_eq!(terminal[0].payload["runTerminalState"], "succeeded"); + state.validate().unwrap(); + } + #[test] fn stopped_prepared_checkpoint_rebinds_without_restarting_its_old_provider() { let directory = std::env::temp_dir().join(format!( @@ -5581,6 +6050,142 @@ mod tests { } } + #[test] + fn cursor_cloud_cold_attachment_refreshes_only_instructions() { + let directory = std::env::temp_dir().join(format!( + "paperclip-cloud-cold-instructions-{}", + uuid::Uuid::new_v4() + )); + fs::create_dir_all(&directory).unwrap(); + let mut state = cursor_cloud_result_state(); + state.active_provider_turn_id = None; + state.provider_process_generation = 1; + state.lifecycle = "prepared".to_owned(); + state.config.instructions = "Previous instructions".to_owned(); + let mut config = state.config.clone(); + config.instructions = "Current instructions".to_owned(); + let mut executor = CodexCommandExecutor::new(&directory); + executor.state = Some(state); + executor.attach_run(&json!({"provider": config})).unwrap(); + let rebound = executor.state.as_ref().unwrap(); + assert_eq!(rebound.config, config); + assert_eq!(rebound.lifecycle, "prepared"); + assert_eq!(rebound.thread_id.as_deref(), Some("thread-1")); + assert_eq!(rebound.provider_process_generation, 1); + assert!(executor.provider.is_none()); + let persisted: CodexProviderState = + serde_json::from_slice(&fs::read(executor.state_path()).unwrap()).unwrap(); + assert_eq!(persisted.config, config); + fs::remove_dir_all(directory).unwrap(); + } + + #[test] + fn cursor_cloud_missing_owned_process_cannot_manufacture_cold_readiness() { + for mode in [ + "settled", + "active", + "ambiguous", + "closed", + "reconciliation_required", + ] { + let mut state = cursor_cloud_result_state(); + state.active_provider_turn_id = None; + state.lifecycle = "session_open".to_owned(); + state.provider_termination_receipt = Some(json!({"remoteStopped": true})); + match mode { + "active" => state.active_provider_turn_id = Some("still-active".to_owned()), + "ambiguous" => state.ambiguous_turn_start_pending = true, + "closed" | "reconciliation_required" => state.lifecycle = mode.to_owned(), + _ => (), + } + let before = serde_json::to_value(&state).unwrap(); + let mut executor = CodexCommandExecutor::new("unused-cloud-no-owned-process"); + executor.state = Some(state); + let result = executor.stop_owned_provider(); + assert_eq!(result.is_ok(), mode == "settled" || mode == "closed"); + assert_eq!( + serde_json::to_value(executor.state.as_ref().unwrap()).unwrap(), + before + ); + } + } + + #[test] + fn cursor_cloud_instruction_refresh_preserves_profile_and_settlement_fences() { + let mut settled = cursor_cloud_result_state(); + settled.active_provider_turn_id = None; + settled.provider_process_generation = 1; + settled.lifecycle = "prepared".to_owned(); + for change in [ + "session_open", + "active", + "ambiguous", + "pending", + "queued", + "model", + "command", + "args", + "provider", + "non_cloud", + "cwd", + "provider_session", + "generation_missing", + ] { + let mut state = settled.clone(); + let mut config = state.config.clone(); + config.instructions = "Current instructions".to_owned(); + match change { + "session_open" => state.lifecycle = "session_open".to_owned(), + "active" => state.active_provider_turn_id = Some("still-active".to_owned()), + "ambiguous" => state.ambiguous_turn_start_pending = true, + "pending" | "queued" => { + let event = PolledEvent { + executor_event_id: "undelivered-result".to_owned(), + event_type: "run.result.proposed".to_owned(), + priority: EventPriority::P0, + payload: json!({}), + }; + if change == "pending" { + state.pending_events.push_back(event); + } else { + state.queued_events.push_back(event); + } + } + "model" => config.model = Some("different-model".to_owned()), + "command" => config.command = PathBuf::from("different-command"), + "args" => config.args.push("different-argument".to_owned()), + "provider" => { + config.provider = "codex".to_owned(); + config.driver = "codex_app_server".to_owned(); + } + "non_cloud" => { + state.config.provider = "codex".to_owned(); + state.config.driver = "codex_app_server".to_owned(); + config.provider = "codex".to_owned(); + config.driver = "codex_app_server".to_owned(); + } + "cwd" => config.cwd = std::env::temp_dir().to_string_lossy().into_owned(), + "provider_session" => { + config.provider_session_id = Some("foreign-session".to_owned()) + } + "generation_missing" => state.provider_process_generation = 0, + _ => unreachable!(), + } + let before = serde_json::to_value(&state).unwrap(); + let mut executor = CodexCommandExecutor::new("unused-cloud-rejected-attachment"); + executor.state = Some(state); + assert!( + executor.attach_run(&json!({"provider": config})).is_err(), + "must reject {change}" + ); + assert!(executor.provider.is_none()); + assert_eq!( + serde_json::to_value(executor.state.as_ref().unwrap()).unwrap(), + before + ); + } + } + #[test] fn accepted_terminal_tool_suppresses_the_generated_terminal_fallback() { let mut state = opencode_result_state(); @@ -6007,7 +6612,7 @@ mod tests { ) .unwrap_err() .to_string() - .contains("reserved for the verified OpenCode provider")); + .contains("reserved for verified provider proxies")); } #[test] @@ -6137,6 +6742,9 @@ mod tests { conversation_mode: None, }, opencode_launch_profile_digest: None, + cursor_cloud_launch_profile_digest: None, + provider_termination_receipt: None, + cursor_cloud_terminal_receipt: None, codex_usage: Some(CodexRunUsage::new(false)), previous_accounting_origin: None, completion_contract: None, diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/runtime_notifications.rs b/packages/paperclip-runner/runner/crates/runner-core/src/runtime_notifications.rs index 897e3231ba2..d1722519fb1 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/runtime_notifications.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/runtime_notifications.rs @@ -405,6 +405,7 @@ mod tests { runner_digest: "sha256:digest".into(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 64 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_warm_attachment.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_warm_attachment.rs index b0bbf0901c1..608809e807e 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_warm_attachment.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/acpx_warm_attachment.rs @@ -72,6 +72,7 @@ fn checkpoints_the_sidecar_and_rebinds_consecutive_warm_runs_before_accepting_wo }], }), opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs index c74854a127d..6d139c97612 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/codex_provider.rs @@ -178,6 +178,7 @@ fn durable_config(directory: &Path) -> DurableRunnerConfig { runner_digest: format!("sha256:{}", "a".repeat(64)), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 16 * 1024 * 1024, p0_reserve_bytes: 1024 * 1024, max_frame_bytes: 1024 * 1024, diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/durable_recovery.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/durable_recovery.rs index dbb7ee18f80..88380e45ba8 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/durable_recovery.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/durable_recovery.rs @@ -25,6 +25,7 @@ fn config(state_dir: PathBuf) -> DurableRunnerConfig { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 16_384, p0_reserve_bytes: 4096, max_frame_bytes: 65_536, diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/native_provider_backend.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/native_provider_backend.rs index 7be46b23307..adcda2f58fc 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/native_provider_backend.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/native_provider_backend.rs @@ -6,8 +6,8 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::os::unix::fs::PermissionsExt; use paperclip_runner_core::durable::{ - AcpxLaunchProfile, Command, CommandExecutor, DurableRunnerConfig, OpenCodeLaunchProfile, - QualifiedLaunchArtifact, + AcpxLaunchProfile, Command, CommandExecutor, CursorCloudLaunchProfile, DurableRunnerConfig, + OpenCodeLaunchProfile, QualifiedLaunchArtifact, }; use paperclip_runner_core::native_provider_backend::NativeProviderCommandExecutor; use paperclip_runner_core::provider_bridge::{authorized_tool_catalog_digest, AuthorizedTool}; @@ -129,6 +129,7 @@ fn config(state_dir: &Path) -> DurableRunnerConfig { runner_digest: "sha256:test".to_owned(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 64 * 1024, max_frame_bytes: 1024 * 1024, @@ -321,6 +322,54 @@ fn opencode_config(state_dir: &Path) -> DurableRunnerConfig { config } +fn cursor_cloud_config(state_dir: &Path) -> DurableRunnerConfig { + cursor_cloud_config_with_args(state_dir, "") +} + +fn cursor_cloud_config_with_args(state_dir: &Path, extra_args: &str) -> DurableRunnerConfig { + let command = state_dir.join("qualified-cursor-cloud-proxy-command"); + let proxy_script = state_dir.join("qualified-cursor-cloud-proxy-script"); + fs::write( + &command, + "#!/bin/sh\nproxy=\"$1\"\nshift\nexec /bin/sh \"$proxy\" \"$@\"\n", + ) + .unwrap(); + fs::write( + &proxy_script, + format!( + "#!/bin/sh\nexec '{}' --state-file '{}' --call-log '{}' --require-completion-contract --durable-turn-ids --cursor-cloud-shutdown {}\n", + env!("CARGO_BIN_EXE_fake-codex-app-server"), + state_dir.join("fake-cursor-cloud-state.json").display(), + state_dir.join("fake-cursor-cloud-calls.log").display(), + extra_args, + ), + ) + .unwrap(); + #[cfg(unix)] + for path in [&command, &proxy_script] { + fs::set_permissions(path, fs::Permissions::from_mode(0o500)).unwrap(); + } + let mut config = config(state_dir); + config.cursor_cloud_launch_profile = Some(CursorCloudLaunchProfile { + command: qualified_artifact(command), + proxy_script: qualified_artifact(proxy_script), + }); + config +} + +fn cursor_cloud_prepare_payload(directory: &Path) -> Value { + let mut payload = opencode_prepare_payload(directory); + payload["provider"] = json!({ + "kind": "cursor_cloud", "provider": "cursor_cloud", "driver": "cursor_cloud_api", + "providerVersion": "cursor-cloud-v1", + "command": directory.join("qualified-cursor-cloud-proxy-command"), + "args": [directory.join("qualified-cursor-cloud-proxy-script")], + "cwd": directory, "model": "caller-selected-model", "approvalPolicy": "never", + "instructions": "Complete the supplied task.", "conversationMode": "prepared", + }); + payload +} + fn opencode_call_count(state_dir: &Path, method: &str) -> usize { fs::read_to_string(state_dir.join("fake-opencode-calls.log")) .unwrap_or_default() @@ -1619,6 +1668,478 @@ fn executes_opencode_through_the_local_facade_without_codex_event_labels() { fs::remove_dir_all(directory).unwrap(); } +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_facade_keeps_provider_labels_and_requires_semantic_completion() { + let directory = temporary_directory("cursor-cloud"); + let config = cursor_cloud_config(&directory); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + let prepared = executor + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + assert_eq!(prepared.result["provider"], "cursor_cloud"); + let opened = executor + .execute(&command(2, "session.open", json!({}))) + .unwrap(); + assert_eq!(opened.result["provider"], "cursor_cloud"); + assert_eq!(opened.result["driver"], "cursor_cloud_api"); + executor + .execute(&command( + 3, + "turn.start", + json!({"text": "Finish the task."}), + )) + .unwrap(); + let deadline = std::time::Instant::now() + Duration::from_secs(5); + let mut observed = Vec::new(); + while std::time::Instant::now() < deadline { + let events = executor.poll_events().unwrap(); + let count = events.len(); + observed.extend(events); + executor.acknowledge_events(count).unwrap(); + if observed + .iter() + .any(|event| event.event_type == "run.terminal") + { + break; + } + std::thread::sleep(Duration::from_millis(1)); + } + assert!(observed + .iter() + .any(|event| event.event_type == "turn.completed")); + let terminal = observed + .iter() + .find(|event| event.event_type == "run.terminal") + .unwrap(); + assert_eq!(terminal.payload["provider"], "cursor_cloud"); + assert_eq!(terminal.payload["turnTerminalState"], "completed"); + assert_eq!(terminal.payload["runTerminalState"], "failed"); + let result = observed + .iter() + .find(|event| event.event_type == "run.result.proposed") + .unwrap(); + assert_eq!(result.payload["reportedWorkDisposition"], "needs_review"); + assert_eq!( + result.payload["completionClaim"]["objectiveSatisfied"], + false + ); + assert!(result.payload["evidence"].as_array().unwrap().is_empty()); + assert!(observed + .iter() + .any(|event| event.event_type == "item.completed" + && event.payload["provider"] == "cursor_cloud")); + executor + .execute(&command(4, "session.close", json!({}))) + .unwrap(); + executor.shutdown().unwrap(); + fs::remove_dir_all(directory).unwrap(); +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_replays_a_durable_terminal_batch_after_proxy_loss_and_a_lost_ack() { + for (partial, finishes_between_reads) in [(false, false), (true, false), (false, true)] { + let directory = temporary_directory("cursor-cloud-terminal-replay"); + let delivery_path = directory.join("terminal.json"); + let hold_ack = directory.join("terminal.json.hold-ack"); + let config = cursor_cloud_config_with_args( + &directory, + &format!( + "--hold-turn --cursor-cloud-terminal-file '{}' {} {}", + delivery_path.display(), + if partial { "--held-final-message" } else { "" }, + if finishes_between_reads { + "--cursor-cloud-finish-between-reads" + } else { + "" + }, + ), + ); + let mut first = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + first + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + first + .execute(&command(2, "session.open", json!({}))) + .unwrap(); + first + .execute(&command( + 3, + "turn.start", + json!({"text":"Retain terminal delivery"}), + )) + .unwrap(); + let mut observed = Vec::new(); + let deadline = std::time::Instant::now() + Duration::from_secs(5); + loop { + let events = first.poll_events().unwrap(); + let count = events.len(); + observed.extend(events); + first.acknowledge_events(count).unwrap(); + if observed.iter().any(|event| { + event.event_type + == if partial { + "item.completed" + } else { + "turn.started" + } + }) { + break; + } + assert!(std::time::Instant::now() < deadline); + std::thread::sleep(Duration::from_millis(1)); + } + drop(first); + let state_path = directory.join("codex-provider-state.json"); + let saved: Value = serde_json::from_slice(&fs::read(&state_path).unwrap()).unwrap(); + fs::write(&delivery_path, serde_json::to_vec(&json!({ + "schema":"paperclip.cursor-cloud.terminal-delivery.v1", "threadId":saved["threadId"], + "turnId":saved["activeProviderTurnId"], "providerRunId":"run-terminal-fixture", + "receiptId":"00000000-0000-4000-8000-000000000001", "status":"FINISHED", "interrupted":false, + "result":"Durable Cloud final", + })).unwrap()).unwrap(); + fs::write(&hold_ack, b"hold").unwrap(); + let mut resumed = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + let recovered = resumed.poll_events().unwrap(); + assert!( + recovered + .iter() + .any(|event| event.event_type == "turn.completed"), + "{recovered:?}" + ); + assert!(!recovered + .iter() + .any(|event| event.event_type == "turn.failed")); + observed.extend(recovered.clone()); + assert_eq!( + observed + .iter() + .filter(|event| event.event_type == "item.completed" + && event.payload.to_string().contains("Durable Cloud final")) + .count(), + 1 + ); + assert!(recovered + .iter() + .any(|event| event.event_type == "run.terminal" + && event.payload["runTerminalState"] == "failed")); + resumed.acknowledge_events(recovered.len()).unwrap(); + assert!(delivery_path.exists()); + drop(resumed); + fs::remove_file(&hold_ack).unwrap(); + let mut again = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + let replay = again.poll_events().unwrap(); + assert!(!replay.iter().any(|event| matches!( + event.event_type.as_str(), + "item.completed" | "turn.completed" | "turn.failed" | "run.terminal" + ))); + assert!(!delivery_path.exists()); + again.acknowledge_events(replay.len()).unwrap(); + again.shutdown().unwrap(); + fs::remove_dir_all(directory).unwrap(); + } +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_stop_saves_and_acknowledges_terminal_delivery_before_proxy_exit() { + for hold_ack in [false, true] { + let directory = temporary_directory("cursor-cloud-stop-terminal"); + let delivery_path = directory.join("terminal.json"); + let config = cursor_cloud_config_with_args( + &directory, + &format!( + "--hold-turn --cursor-cloud-terminal-file '{}'", + delivery_path.display() + ), + ); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + executor + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + executor + .execute(&command(2, "session.open", json!({}))) + .unwrap(); + executor + .execute(&command( + 3, + "turn.start", + json!({"text":"Stop and retain the receipt"}), + )) + .unwrap(); + let state_path = directory.join("codex-provider-state.json"); + let saved: Value = serde_json::from_slice(&fs::read(&state_path).unwrap()).unwrap(); + fs::write(&delivery_path, serde_json::to_vec(&json!({ + "schema":"paperclip.cursor-cloud.terminal-delivery.v1", "threadId":saved["threadId"], + "turnId":saved["activeProviderTurnId"], "providerRunId":"run-stopped-fixture", + "receiptId":"00000000-0000-4000-8000-000000000002", "status":"CANCELLED", "interrupted":true, + "result":null, + })).unwrap()).unwrap(); + if hold_ack { + fs::write(directory.join("terminal.json.hold-ack"), b"hold").unwrap(); + } + executor + .execute(&command(4, "turn.stop", json!({}))) + .unwrap(); + assert_eq!( + delivery_path.exists(), + hold_ack, + "the Node receipt must be acknowledged after its durable save" + ); + let retained: Value = serde_json::from_slice(&fs::read(&state_path).unwrap()).unwrap(); + assert_eq!(retained["lifecycle"], "prepared"); + assert_eq!( + retained["cursorCloudTerminalReceipt"]["turnId"], + saved["activeProviderTurnId"] + ); + assert!(retained["pendingEvents"] + .as_array() + .unwrap() + .iter() + .any(|event| event["eventType"] == "turn.interrupted")); + let pending = executor.poll_events().unwrap(); + executor.acknowledge_events(pending.len()).unwrap(); + if hold_ack { + fs::remove_file(directory.join("terminal.json.hold-ack")).unwrap(); + executor + .execute(&command( + 5, + "run.attach", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + executor + .execute(&command(6, "session.open", json!({}))) + .unwrap(); + assert!( + !delivery_path.exists(), + "fresh attachment must retry the saved receipt acknowledgment" + ); + } + executor.shutdown().unwrap(); + fs::remove_dir_all(directory).unwrap(); + } +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_run_attachment_reopens_the_same_thread_in_a_fresh_sidecar() { + let directory = temporary_directory("cursor-cloud-cold-attachment"); + let config = cursor_cloud_config(&directory); + let payload = cursor_cloud_prepare_payload(&directory); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + executor + .execute(&command(1, "run.prepare", payload.clone())) + .unwrap(); + let opened = executor + .execute(&command(2, "session.open", json!({}))) + .unwrap(); + executor + .execute(&command(3, "run.attach", payload)) + .unwrap(); + let resumed = executor + .execute(&command(4, "session.open", json!({}))) + .unwrap(); + assert_eq!(resumed.result["status"], "resumed"); + assert_eq!( + resumed.result["providerSessionId"], + opened.result["providerSessionId"] + ); + assert_ne!(resumed.result["processId"], opened.result["processId"]); + let calls = fs::read_to_string(directory.join("fake-cursor-cloud-calls.log")).unwrap(); + assert_eq!( + calls.lines().filter(|line| *line == "thread/start").count(), + 1 + ); + assert_eq!( + calls + .lines() + .filter(|line| *line == "thread/resume") + .count(), + 1 + ); + assert_eq!( + calls + .lines() + .filter(|line| *line == "paperclip/shutdown") + .count(), + 1 + ); + executor.shutdown().unwrap(); + fs::remove_dir_all(directory).unwrap(); +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_stop_preserves_active_ownership_until_remote_termination_is_confirmed() { + let directory = temporary_directory("cursor-cloud-stop-confirmation"); + let control = directory.join("shutdown-control"); + fs::write(&control, "unconfirmed").unwrap(); + let config = cursor_cloud_config_with_args( + &directory, + &format!( + "--hold-turn --cursor-cloud-shutdown-control '{}'", + control.display() + ), + ); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + executor + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + executor + .execute(&command(2, "session.open", json!({}))) + .unwrap(); + let started = executor + .execute(&command(3, "turn.start", json!({"text": "Keep working."}))) + .unwrap(); + let turn_id = started.result["providerTurnId"].clone(); + let error = executor + .execute(&command(4, "turn.stop", json!({}))) + .unwrap_err(); + assert!(error + .to_string() + .contains("remote termination is unconfirmed")); + let state_path = directory.join("codex-provider-state.json"); + let retained: Value = serde_json::from_slice(&fs::read(&state_path).unwrap()).unwrap(); + assert_eq!(retained["activeProviderTurnId"], turn_id); + assert_eq!(retained["lifecycle"], "turn_active"); + assert!(retained["providerTerminationReceipt"].is_null()); + fs::write(&control, "confirmed").unwrap(); + let stopped = executor + .execute(&command(5, "turn.stop", json!({}))) + .unwrap(); + assert_eq!(stopped.result["providerExitConfirmed"], true); + assert_eq!( + stopped.result["providerTerminationReceipt"]["remoteStopped"], + true + ); + assert_eq!( + stopped.result["providerTerminationReceipt"]["remoteRunId"], + "cursor-run-fixture" + ); + let state: Value = serde_json::from_slice(&fs::read(&state_path).unwrap()).unwrap(); + assert!(state["activeProviderTurnId"].is_null()); + assert_eq!( + state["providerTerminationReceipt"]["remoteRunId"], + "cursor-run-fixture" + ); + let calls = fs::read_to_string(directory.join("fake-cursor-cloud-calls.log")).unwrap(); + assert_eq!( + calls.lines().filter(|line| *line == "turn/start").count(), + 1 + ); + assert_eq!( + calls + .lines() + .filter(|line| *line == "paperclip/shutdown") + .count(), + 2 + ); + executor.shutdown().unwrap(); + fs::remove_dir_all(directory).unwrap(); +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_launch_rejects_unpinned_commands_and_script_replacement() { + let directory = temporary_directory("cursor-cloud-launch-fence"); + let config = cursor_cloud_config(&directory); + let mut invalid = cursor_cloud_prepare_payload(&directory); + invalid["provider"]["command"] = json!(env!("CARGO_BIN_EXE_fake-codex-app-server")); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + assert!(executor + .execute(&command(1, "run.prepare", invalid)) + .unwrap_err() + .to_string() + .contains("runner-owned qualified profile")); + drop(executor); + let mut executor = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + executor + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + let script = &config + .cursor_cloud_launch_profile + .as_ref() + .unwrap() + .proxy_script + .path; + #[cfg(unix)] + fs::set_permissions(script, fs::Permissions::from_mode(0o700)).unwrap(); + fs::write(script, "#!/bin/sh\nexit 7\n").unwrap(); + let error = executor + .execute(&command(2, "session.open", json!({}))) + .unwrap_err(); + assert!( + error + .to_string() + .contains("verified process artifact digest mismatch"), + "{error}" + ); + fs::remove_dir_all(directory).unwrap(); +} + +#[test] +#[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] +fn cursor_cloud_durable_recovery_rejects_a_changed_proxy_profile_without_rewriting_state() { + let directory = temporary_directory("cursor-cloud-profile-recovery"); + let config = cursor_cloud_config(&directory); + let mut first = NativeProviderCommandExecutor::with_runner_config(&directory, &config); + first + .execute(&command( + 1, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap(); + first.shutdown().unwrap(); + drop(first); + let state_path = directory.join("codex-provider-state.json"); + let saved = fs::read(&state_path).unwrap(); + let mut changed = config; + changed + .cursor_cloud_launch_profile + .as_mut() + .unwrap() + .proxy_script + .sha256 = format!("sha256:{}", "a".repeat(64)); + let mut recovered = NativeProviderCommandExecutor::with_runner_config(&directory, &changed); + for sequence in 2..=3 { + let error = recovered + .execute(&command( + sequence, + "run.prepare", + cursor_cloud_prepare_payload(&directory), + )) + .unwrap_err(); + assert!(error + .to_string() + .contains("Cursor Cloud runner launch profile changed across durable recovery")); + } + assert_eq!(fs::read(&state_path).unwrap(), saved); + fs::remove_dir_all(directory).unwrap(); +} + #[test] #[cfg_attr(windows, ignore = "verified launch is not supported on Windows yet")] fn replacement_shutdown_restores_the_persisted_provider_before_cleanup() { diff --git a/packages/paperclip-runner/runner/crates/runner-core/tests/runtime_notifications.rs b/packages/paperclip-runner/runner/crates/runner-core/tests/runtime_notifications.rs index ae2a7d2e78e..04505dca4a1 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/tests/runtime_notifications.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/tests/runtime_notifications.rs @@ -49,6 +49,7 @@ fn real_cli_uses_relative_state_from_another_directory_and_never_process_run_ide runner_digest: "sha256:digest".into(), acpx_launch_profile: None, opencode_launch_profile: None, + cursor_cloud_launch_profile: None, max_outbox_bytes: 1024 * 1024, p0_reserve_bytes: 65536, max_frame_bytes: 65536, diff --git a/packages/paperclip-runner/scripts/build-verified-provider-entrypoints.mjs b/packages/paperclip-runner/scripts/build-verified-provider-entrypoints.mjs index 05a901f803d..4711b73f797 100644 --- a/packages/paperclip-runner/scripts/build-verified-provider-entrypoints.mjs +++ b/packages/paperclip-runner/scripts/build-verified-provider-entrypoints.mjs @@ -8,6 +8,12 @@ import { build } from "esbuild"; const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); export const verifiedProviderEntrypoints = Object.freeze([ + Object.freeze({ + name: "cursor-cloud-app-server-proxy", + source: resolve(packageRoot, "src/cli/cursor-cloud-app-server-proxy.ts"), + output: resolve(packageRoot, "dist/cli/cursor-cloud-app-server-proxy.js"), + verifiedOutput: resolve(packageRoot, "dist/cli/cursor-cloud-app-server-proxy.cjs"), + }), Object.freeze({ name: "kimi-metadata-probe", source: resolve(packageRoot, "src/cli/kimi-metadata-probe.ts"), diff --git a/packages/paperclip-runner/src/backends/codex-native-backend.ts b/packages/paperclip-runner/src/backends/codex-native-backend.ts index 69bcbf411ee..9b1b4145666 100644 --- a/packages/paperclip-runner/src/backends/codex-native-backend.ts +++ b/packages/paperclip-runner/src/backends/codex-native-backend.ts @@ -11,6 +11,8 @@ import type { } from "../contracts/native-session-backend.js"; import type { CodexAppServerTransport } from "../drivers/codex/app-server-transport.js"; import { CodexAppServerDriver } from "../drivers/codex/codex-app-server-driver.js"; +import { CURSOR_CLOUD_TERMINAL_DRAIN_TIMEOUT_MS } from "../contracts/cursor-cloud.js"; +import { cursorCloudDriverDescriptor } from "../drivers/cursor-cloud/cursor-cloud-driver.js"; import type { CodexWorkingDirectoryAuthority } from "../drivers/codex/codex-boundaries.js"; import { describeRunnerdExternalBotDriver } from "../drivers/dot/runnerd-dot-driver.js"; import { HarnessDriverBackend } from "./harness-driver-backend.js"; @@ -59,6 +61,7 @@ export interface CodexNativeSessionBackendOptions { function transportDriverIdentity(input: NativeExecutionInput): { kind: + | "cursor_cloud_api" | "codex_app_server" | "opencode_server" | "claude_managed_agents_api" @@ -68,6 +71,8 @@ function transportDriverIdentity(input: NativeExecutionInput): { version: string; } { switch (input.provider.kind) { + case "cursor_cloud": + return { kind: "cursor_cloud_api", displayName: "Cursor Cloud (experimental)", version: "cursor-cloud-v1" }; case "codex": return { kind: "codex_app_server", @@ -153,7 +158,7 @@ function createTransportBackedNativeSessionBackend( const baseInstructions = options.retainedSystemInstructions ?? nativeSystemInstructions(input); const transportFactory = options.transportFactory; - return new HarnessDriverBackend( + const backend = new HarnessDriverBackend( new CodexAppServerDriver({ ...(input.provider.model ? { model: input.provider.model } : {}), ...(input.provider.kind === "codex" && "webSearch" in input.provider && input.provider.webSearch === "disabled" @@ -203,6 +208,7 @@ function createTransportBackedNativeSessionBackend( capabilities: isCodex ? {} : { steering: false, goals: false, threadLineage: false, + ...(input.provider.kind === "cursor_cloud" ? { runtimeRequestResolution: false } : {}), toolRefreshOnResume: input.provider.kind !== "acpx" || ACPX_CAPABILITY_PROFILES[input.provider.agent].toolRefreshOnResume === true }, collaborationModes: supportsCollaborativePlanning @@ -211,7 +217,17 @@ function createTransportBackedNativeSessionBackend( requireProviderSessionIdentity: options.transportFactory !== undefined, }), preparedContext ? constraints : undefined, + input.provider.kind === "cursor_cloud" ? CURSOR_CLOUD_TERMINAL_DRAIN_TIMEOUT_MS : undefined, ); + if (input.provider.kind === "cursor_cloud") { + backend.descriptor = async () => { + const descriptor = cursorCloudDriverDescriptor(); + return { kind: "runner", name: descriptor.kind, version: descriptor.version, + capabilities: structuredClone(descriptor.capabilities), + runtimeContextCapabilities: structuredClone(descriptor.runtimeContextCapabilities) }; + }; + } + return backend; } /** Inspect the selected runnerd harness without starting a provider process. */ diff --git a/packages/paperclip-runner/src/backends/harness-driver-backend.test.ts b/packages/paperclip-runner/src/backends/harness-driver-backend.test.ts index 67352d7d080..094362e0fa6 100644 --- a/packages/paperclip-runner/src/backends/harness-driver-backend.test.ts +++ b/packages/paperclip-runner/src/backends/harness-driver-backend.test.ts @@ -542,6 +542,21 @@ describe("HarnessDriverBackend", () => { expect(session.identity()).toEqual({ ...originalIdentity, runId: "run-2" }); }); + it.each([undefined, 30_000])("preserves the cancellation terminal bound through open and recovery (%s)", async bound => { + const harness = new FakeHarnessSession(); + const backend = new HarnessDriverBackend({ ...driver, async openSession() { return harness; }, async recoverSession() { return { recovered: true, session: harness }; } }, undefined, bound); + const identity = { companyId: "company-1", agentId: "agent-1", issueId: "issue-1", runId: "run-1", sessionId: "session-1" }; + const opened = await backend.openSession({ identity }); + const snapshot = await opened.snapshot({ signal: new AbortController().signal }); + const recovered = await backend.recoverSession(snapshot, { signal: new AbortController().signal }); + expect(recovered.recovered).toBe(true); + for (const session of [opened, recovered.session!]) { + const cancellation = session.cancel!({ reason: "durable wait", signal: new AbortController().signal }); + expect(cancellation.terminalDrainTimeoutMs).toBe(bound); + await cancellation.cleanup; + } + }); + it("restores a persisted terminal before the recovered stream is consumed", async () => { const recoveryDriver: HarnessDriver = { ...driver, diff --git a/packages/paperclip-runner/src/backends/harness-driver-backend.ts b/packages/paperclip-runner/src/backends/harness-driver-backend.ts index 3d188cd10e2..1339830d047 100644 --- a/packages/paperclip-runner/src/backends/harness-driver-backend.ts +++ b/packages/paperclip-runner/src/backends/harness-driver-backend.ts @@ -34,7 +34,7 @@ const MAX_RECOVERY_SEMANTIC_RESULT_DEPTH = 128; export class HarnessDriverBackend implements NativeSessionBackend { readonly #driver: HarnessDriver; - constructor(driver: HarnessDriver, readonly preparedTaskConstraints?: readonly string[]) { + constructor(driver: HarnessDriver, readonly preparedTaskConstraints?: readonly string[], private readonly terminalDrainTimeoutMs?: number) { this.#driver = driver; } @@ -74,7 +74,7 @@ export class HarnessDriverBackend implements NativeSessionBackend { .catch(() => undefined); throw error; } - return new HarnessNativeSession(input, session, undefined, (await this.#driver.descriptor()).capabilities.steering); + return new HarnessNativeSession(input, session, undefined, (await this.#driver.descriptor()).capabilities.steering, this.terminalDrainTimeoutMs); } async recoverSession( @@ -186,6 +186,7 @@ export class HarnessDriverBackend implements NativeSessionBackend { recovered.session, recoveredTerminal, (await this.#driver.descriptor()).capabilities.steering, + this.terminalDrainTimeoutMs, ), }; } @@ -441,6 +442,7 @@ class HarnessNativeSession implements NativeSession { session: HarnessSession, terminal?: PrpTerminalState | null, steeringSupported = false, + private readonly terminalDrainTimeoutMs?: number, ) { this.#steeringSupported = steeringSupported; this.#input = structuredClone(input); @@ -766,6 +768,7 @@ class HarnessNativeSession implements NativeSession { this.revokeTurnPublication(); const interrupt = this.#session.interrupt; return { + ...(this.terminalDrainTimeoutMs === undefined ? {} : { terminalDrainTimeoutMs: this.terminalDrainTimeoutMs }), cleanup: interrupt === undefined ? Promise.resolve() diff --git a/packages/paperclip-runner/src/backends/native-backend-factory.test.ts b/packages/paperclip-runner/src/backends/native-backend-factory.test.ts index 91e3a46b958..1b551e20ccf 100644 --- a/packages/paperclip-runner/src/backends/native-backend-factory.test.ts +++ b/packages/paperclip-runner/src/backends/native-backend-factory.test.ts @@ -292,6 +292,23 @@ describe("native backend factory", () => { }); }); + it("reports Cursor Cloud capabilities without inheriting native Codex promises", async () => { + const input = execution({ kind: "cursor_cloud", model: "explicit-model", cursorCloud: { + schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/project" }], + } }); + input.session.driverKind = "cursor_cloud_api"; + const backend = createRunnerdNativeSessionBackend(preparedExecution(input), { + transportFactory: () => { throw new Error("descriptor must not launch the transport"); }, + }); + const descriptor = await backend.descriptor(); + expect(descriptor).toMatchObject({ name: "cursor_cloud_api", version: "cursor-cloud-v1", capabilities: { + resume: true, dynamicTools: true, runtimeRequestResolution: false, runtimeRequestHandoff: false, + steering: false, goals: false, threadLineage: false, + unsupported: expect.arrayContaining(["native_permissions", "native_questions", "preprompt_model_acknowledgment"]), + } }); + expect(descriptor.capabilities.typedEventFamilies).toBeUndefined(); + }); + it("defers remote ACPX workspace admission to the runner filesystem", async () => { const remoteWorkspace = "/home/daytona/paperclip-workspace"; const transport = new FakeCodexTransport(); diff --git a/packages/paperclip-runner/src/cli/cursor-cloud-app-server-proxy.ts b/packages/paperclip-runner/src/cli/cursor-cloud-app-server-proxy.ts new file mode 100644 index 00000000000..e5eb3f21903 --- /dev/null +++ b/packages/paperclip-runner/src/cli/cursor-cloud-app-server-proxy.ts @@ -0,0 +1,218 @@ +#!/usr/bin/env node +import { constants } from "node:fs"; +import { open as openFile } from "node:fs/promises"; +import { dirname, resolve } from "node:path"; +import { pathToFileURL } from "node:url"; +import type { Readable, Writable } from "node:stream"; +import type { HarnessSession, PersistedHarnessSession } from "../contracts/harness-driver.js"; +import { parseNativeRuntimeContext } from "../contracts/runtime-context.js"; +import { CursorCloudDriver, CURSOR_CLOUD_DRIVER_KIND, CURSOR_CLOUD_DRIVER_VERSION, type CursorCloudSessionHandle } from "../drivers/cursor-cloud/cursor-cloud-driver.js"; +import { cursorCloudRecord, parseCursorCloudBinding, parseNativeCursorCloudConfig } from "../drivers/cursor-cloud/config.js"; +import { enqueueSerialInput } from "./serial-input-queue.js"; + +type Rpc = { id?: string | number; method?: string; params?: unknown; result?: unknown; error?: unknown }; +const MAX_FRAME_BYTES = 2_097_152; +const object = (value: unknown): Record => value && typeof value === "object" && !Array.isArray(value) ? value as Record : {}; +const text = (value: unknown, fallback = "") => typeof value === "string" ? value : fallback; + +async function privateJson(path: string, maxBytes: number): Promise { + const handle = await openFile(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + try { + const stat = await handle.stat(); + if (!stat.isFile() || stat.size > maxBytes || (stat.mode & 0o077) !== 0 || (process.getuid && stat.uid !== process.getuid())) throw new Error("Cursor Cloud configuration file must be owned, private and bounded"); + const buffer = Buffer.alloc(stat.size + 1); + const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0); + if (bytesRead !== stat.size) throw new Error("Cursor Cloud configuration changed during admission"); + return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, bytesRead))); + } finally { await handle.close(); } +} + +export function startCursorCloudAppServerProxy(options: { + input?: Readable; + output?: Writable; + diagnostic?: Writable; + environment?: NodeJS.ProcessEnv; +} = {}): { done: Promise; shutdown(): Promise } { + const input = options.input ?? process.stdin; + const output = options.output ?? process.stdout; + const diagnostic = options.diagnostic ?? process.stderr; + const env = options.environment ?? process.env; + const pending = new Map(); + let sequence = 0; + let session: CursorCloudSessionHandle | null = null; + let cwd = ""; + let model = ""; + let closed = false; + let shuttingDown: Promise | null = null; + let commandQueue = Promise.resolve(); + let buffer = Buffer.alloc(0); + let bootstrapFailed = false; + let finish!: () => void; + const done = new Promise(resolveDone => { finish = resolveDone; }); + + function send(value: unknown): void { + const encoded = `${JSON.stringify(value)}\n`; + if (Buffer.byteLength(encoded) > MAX_FRAME_BYTES || output.writableLength + Buffer.byteLength(encoded) > 4_194_304) throw new Error("Cursor Cloud output frame/consumer exceeded its bound"); + output.write(encoded); + } + function requestController(params: Record): Promise { + if (closed || pending.size >= 128) return Promise.reject(new Error("Cursor Cloud controller is closed or exceeds its pending-call bound")); + const id = `cursor-cloud-${++sequence}`; + const promise = new Promise((resolveValue, reject) => pending.set(id, { resolve: resolveValue, reject })); + send({ id, method: "item/tool/call", params }); + return promise; + } + async function openSession(params: Record, resume: boolean): Promise { + if (session) throw new Error("Cursor Cloud thread is already open"); + const configPath = env.PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH?.trim(); + if (!configPath) throw new Error("PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH is required"); + const raw = cursorCloudRecord(await privateJson(configPath, 65_536)); + const { binding: rawBinding, ...publicConfig } = raw; + const binding = parseCursorCloudBinding(rawBinding); + const config = parseNativeCursorCloudConfig(publicConfig); + if (binding.normalizedSessionId !== env.PAPERCLIP_NORMALIZED_SESSION_ID) throw new Error("Cursor Cloud normalized session binding mismatch"); + const runtimeContextPath = env.PAPERCLIP_NATIVE_RUNTIME_CONTEXT_PATH?.trim(); + const runtimeContext = runtimeContextPath ? parseNativeRuntimeContext(await privateJson(runtimeContextPath, 1_048_576)) : null; + cwd = resolve(text(params.cwd, process.cwd())); model = text(params.model); + const runId = env.PAPERCLIP_RUN_ID; + if (!runId) throw new Error("PAPERCLIP_RUN_ID is required"); + const relayUrl = env.PAPERCLIP_CURSOR_CLOUD_RELAY_URL; + const relayToken = env.PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN; + const socketPath = env.PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH; + const relayExpiresAt = Number(env.PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT); + if (!relayUrl || !relayToken || !socketPath || !Number.isSafeInteger(relayExpiresAt) || relayExpiresAt <= 0) throw new Error("Cursor Cloud semantic relay binding and expiry are required"); + const driver = new CursorCloudDriver({ model, config, binding, runtimeDirectory: dirname(resolve(configPath)), artifactRoot: env.PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT, relay: { url: relayUrl, token: relayToken, socketPath, expiresAt: relayExpiresAt }, + instructions: text(params.baseInstructions, "Complete only the supplied Paperclip task. Use Paperclip tools and finish with paperclip_finish or paperclip_block."), runtimeContext, + dynamicTools: Array.isArray(params.dynamicTools) ? params.dynamicTools.map(value => cursorCloudRecord(value)) : [], + dynamicToolHandler: async call => requestController({ ...call }), environment: env, + runnerInstanceId: env.PAPERCLIP_RUNNER_INSTANCE_ID ?? "cursor-cloud-sidecar" }); + if (resume) { + const threadId = text(params.threadId); + const snapshot: PersistedHarnessSession = { driverKind: CURSOR_CLOUD_DRIVER_KIND, driverSessionId: threadId, normalizedSessionId: binding.normalizedSessionId, runId, workingDirectory: cwd }; + const restored = await driver.recoverSession(snapshot); + if (!restored.recovered || !restored.session) throw new Error(restored.reason ?? "Cursor Cloud recovery failed"); + session = restored.session; + } else session = await driver.openSession({ runId, normalizedSessionId: binding.normalizedSessionId, workingDirectory: cwd }); + void pump(session).catch(() => shutdown()); + return { thread: { id: session.ids().driverSessionId, sessionId: session.ids().driverSessionId, cwd }, submittedModel: model, effectiveModelAcknowledged: false, instructionsAcknowledged: false }; + } + async function pump(opened: HarnessSession): Promise { + for await (const event of opened.events()) { + const payload = event.payload; + const threadId = opened.ids().driverSessionId; + const turnId = event.turnId; + if (event.eventType === "turn.started") send({ method: "turn/started", params: { threadId, turnId, turn: { id: turnId, status: "inProgress" } } }); + else if (["item.started", "item.delta", "item.completed"].includes(event.eventType)) { + const assistant = payload.kind === "agentMessage"; + const nativeItem = object(payload.item); + const item = payload.kind === "tool" ? { ...nativeItem, type: "builtinToolCall", tool: nativeItem.name, + ...(nativeItem.result === undefined ? {} : { output: typeof nativeItem.result === "string" ? nativeItem.result : JSON.stringify(nativeItem.result) }) } + : payload.item ?? { id: event.itemId, type: assistant ? "agentMessage" : payload.kind, text: payload.text }; + send({ method: event.eventType === "item.delta" && assistant ? "item/agentMessage/delta" : event.eventType.replace(".", "/"), params: { + threadId, turnId, itemId: event.itemId, ...payload, item, + ...(event.eventType === "item.delta" && assistant ? { delta: payload.text } : {}), + } }); + } else if (["turn.completed", "turn.failed", "turn.interrupted"].includes(event.eventType)) send({ method: event.eventType.replace(".", "/"), params: { threadId, turnId, ...(payload.cursorCloudTerminalDelivery ? { cursorCloudTerminalDelivery: payload.cursorCloudTerminalDelivery } : {}), turn: { id: turnId, status: event.eventType.slice(5), ...(payload.error ? { error: payload.error } : {}) } } }); + else if (event.eventType === "harness.diagnostic") send({ method: "warning", params: { threadId, turnId, code: payload.code, message: payload.message ?? payload.code } }); + } + } + async function stopReceipt(params: Record): Promise> { + if (!session) return { remoteStopped: true, remoteRunId: null }; + await session.interrupt?.({}); + const state = await session.read?.() ?? {}; + const expectedTurnId = typeof params.turnId === "string" ? params.turnId : null; + if (expectedTurnId !== null && expectedTurnId !== state.turnId) throw new Error("Cursor Cloud shutdown turn identity changed"); + const stoppedTurnId = state.pendingTerminalDelivery ? state.turnId : expectedTurnId; + if (state.runId && state.phase !== "terminal") throw new Error("Cursor Cloud remote Stop is unconfirmed"); + if (!state.runId && state.phase !== "idle") throw new Error("Cursor Cloud pending remote create is unconfirmed"); + return { remoteStopped: true, threadId: session.ids().driverSessionId, turnId: stoppedTurnId ?? null, remoteAgentId: state.agentId ?? null, remoteRunId: state.runId ?? null, ...(state.pendingTerminalDelivery ? { cursorCloudTerminalDelivery: state.pendingTerminalDelivery } : {}), ...(state.providerStatus ? { status: state.providerStatus } : {}) }; + } + async function handle(message: Rpc): Promise { + if (message.method === undefined && message.id !== undefined) { + const waiter = pending.get(String(message.id)); if (!waiter) return; + pending.delete(String(message.id)); + if (message.error !== undefined) waiter.reject(new Error("Cursor Cloud controller rejected its tool request")); else waiter.resolve(message.result); + return; + } + if (!message.method || message.id === undefined) return; + const params = object(message.params); + let result: unknown; + switch (message.method) { + case "initialize": result = { user: { sessionId: "cursor-cloud" }, serverInfo: { name: "cursor-cloud", version: CURSOR_CLOUD_DRIVER_VERSION } }; break; + case "thread/start": result = await openSession(params, false); break; + case "thread/resume": result = await openSession(params, true); break; + case "collaborationMode/list": result = { data: [{ name: "Default", mode: "default", model, reasoningEffort: null }] }; break; + case "turn/start": { + if (!session) throw new Error("Cursor Cloud thread is not open"); + if (object(params.collaborationMode).mode === "plan" || params.reasoningMode !== undefined) throw new Error("Cursor Cloud native plan/reasoning override is unsupported"); + const items = Array.isArray(params.input) ? params.input.map(object) : []; + if (items.some(item => item.type !== "text" && item.type !== "inputText")) throw new Error("Cursor Cloud supports text turn input only"); + const turn = await session.startTurn({ message: { role: "user", text: items.map(item => text(item.text)).join("\n") } }); + result = { turn: { id: turn.turnId, status: "inProgress" } }; break; + } + case "turn/interrupt": + if (!session?.interrupt) throw new Error("Cursor Cloud thread is not open"); + await session.interrupt({ ...(typeof params.turnId === "string" ? { turnId: params.turnId } : {}) }); result = true; break; + case "thread/read": { + if (!session) throw new Error("Cursor Cloud thread is not open"); + await session.snapshot(); + const state = await session.read(); + const activeTurnId = ["creating", "running", "stopping"].includes(String(state.phase)) && typeof state.turnId === "string" ? state.turnId : null; + result = { cursorCloudTerminalDelivery: state.pendingTerminalDelivery, thread: { id: session.ids().driverSessionId, cwd, turns: activeTurnId ? [{ id: activeTurnId, status: "inProgress" }] : [] }, transcript: state }; break; + } + case "paperclip/ackTerminal": + if (!session || typeof params.turnId !== "string" || typeof params.receiptId !== "string") throw new Error("Cursor Cloud terminal receipt is missing"); + await session.acknowledgeTerminalDelivery({ turnId: params.turnId, receiptId: params.receiptId }); + result = { turnId: params.turnId, receiptId: params.receiptId, acknowledged: true }; break; + case "paperclip/shutdown": result = await stopReceipt(params); break; + default: throw new Error("Unsupported Cursor Cloud proxy method"); + } + send({ id: message.id, result }); + } + async function shutdown(): Promise { + shuttingDown ??= (async () => { + closed = true; + for (const waiter of pending.values()) waiter.reject(new Error("Cursor Cloud controller closed")); pending.clear(); + try { await session?.close({ reason: "proxy_shutdown", force: true }); } + catch { diagnostic.write("[cursor-cloud] Remote termination is unconfirmed; checkpoint retained.\n"); process.exitCode = 1; } + finish(); + })(); + return shuttingDown; + } + function receive(message: Rpc): void { + if (closed) return; + if (message.method === undefined && message.id !== undefined) { void handle(message); return; } + commandQueue = enqueueSerialInput(commandQueue, async () => { + if (bootstrapFailed && message.method !== "paperclip/shutdown") throw new Error("Cursor Cloud bootstrap previously failed"); + await handle(message); + }, error => { + if (["initialize", "thread/start", "thread/resume"].includes(message.method ?? "")) bootstrapFailed = true; + const reason = error instanceof Error ? error.message : "Cursor Cloud request failed"; + send({ id: message.id, error: { code: -32000, message: reason.slice(0, 2_000) } }); + }); + } + input.on("data", (chunk: Buffer | string) => { + if (closed) return; + buffer = Buffer.concat([buffer, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]); + while (true) { + const index = buffer.indexOf(10); + if (index < 0) break; + const line = buffer.subarray(0, index); buffer = buffer.subarray(index + 1); + if (line.length > MAX_FRAME_BYTES) { void shutdown(); return; } + if (!line.toString().trim()) continue; + try { const message = JSON.parse(line.toString()) as Rpc; receive(message); } + catch { send({ id: null, error: { code: -32700, message: "Invalid Cursor Cloud JSON-RPC input" } }); } + } + if (buffer.length > MAX_FRAME_BYTES) void shutdown(); + }); + input.on("end", () => { void commandQueue.then(shutdown); }); + input.on("error", () => { void shutdown(); }); + return { done, shutdown }; +} + +if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) { + const proxy = startCursorCloudAppServerProxy(); + process.once("SIGTERM", () => { void proxy.shutdown(); }); + process.once("SIGINT", () => { void proxy.shutdown(); }); + void proxy.done.then(() => process.exit(process.exitCode ?? 0)); +} diff --git a/packages/paperclip-runner/src/cli/opencode-proxy-thread-read.test.ts b/packages/paperclip-runner/src/cli/opencode-proxy-thread-read.test.ts index fa0a9878e26..1ff70c93c9c 100644 --- a/packages/paperclip-runner/src/cli/opencode-proxy-thread-read.test.ts +++ b/packages/paperclip-runner/src/cli/opencode-proxy-thread-read.test.ts @@ -1,6 +1,6 @@ import { execFileSync, spawn } from "node:child_process"; import { closeSync, openSync } from "node:fs"; -import { chmod, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises"; +import { chmod, copyFile, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises"; import { randomUUID } from "node:crypto"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; @@ -15,8 +15,15 @@ const MODEL = "openrouter/deepseek/deepseek-v4-flash-0731"; type RpcFrame = { id?: string | number; method?: string; result?: unknown; error?: unknown }; async function startProxy(root: string, proxy: string, executable: string, runtime: string) { - const fd = process.platform === "linux" ? openSync(executable, "r") : undefined; - const child = spawn(process.execPath, [proxy, "--paperclip-trusted-opencode-executable", fd === undefined ? executable : "/proc/self/fd/3"], { + const launchRoot = join(root, `.paperclip-verified-executable-${randomUUID().replaceAll("-", "")}`); + await mkdir(launchRoot, { mode: 0o700 }); + await chmod(launchRoot, 0o700); + const snapshot = join(launchRoot, "launch"); + await copyFile(executable, snapshot); + await chmod(snapshot, 0o500); + expect(await readFile(snapshot)).toEqual(await readFile(executable)); + const fd = process.platform === "linux" ? openSync(snapshot, "r") : undefined; + const child = spawn(process.execPath, [proxy, "--paperclip-trusted-opencode-executable", fd === undefined ? snapshot : "/proc/self/fd/3"], { // Keep an enclosing Paperclip run's launch bindings out of this fixture. env: { ...Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("PAPERCLIP_"))), PAPERCLIP_OPENCODE_RUNTIME_DIR: runtime, OPENROUTER_API_KEY: "fixture-key", @@ -55,10 +62,7 @@ async function startProxy(root: string, proxy: string, executable: string, runti it("resumes a session whose OpenCode message history exceeds runnerd's frame limit", async () => { const root = await mkdtemp(join(tmpdir(), "opencode-proxy-thread-read-")); - const launchRoot = join(root, `.paperclip-verified-executable-${randomUUID().replaceAll("-", "")}`); - await mkdir(launchRoot, { mode: 0o700 }); - await chmod(launchRoot, 0o700); - const executable = join(launchRoot, "launch"); + const executable = join(root, "fixture-launch"); const fixture = resolve("test/fixtures/fake-opencode-server.mjs"); execFileSync("cc", ["-x", "c", "-o", executable, "-"], { input: `#include \n#include \nint main(int argc, char **argv) { char **args = calloc(argc + 2, sizeof(char *)); args[0] = ${JSON.stringify(process.execPath)}; args[1] = ${JSON.stringify(fixture)}; for (int i = 1; i < argc; i++) args[i + 1] = argv[i]; execv(args[0], args); return 127; }` }); if (process.platform === "darwin") { diff --git a/packages/paperclip-runner/src/configured-environment.ts b/packages/paperclip-runner/src/configured-environment.ts index 65d8b05ad31..475e62c3cc9 100644 --- a/packages/paperclip-runner/src/configured-environment.ts +++ b/packages/paperclip-runner/src/configured-environment.ts @@ -38,7 +38,7 @@ function eligibleKey(key: string): boolean { return /^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(key) && !GENERATED_RUNTIME_ENVIRONMENT_KEYS.has(upper) && !RESERVED_KEYS.has(upper) - && !/^(?:LD_|DYLD_|GIT_CONFIG_|PAPERCLIP_(?:RUNNER_|NATIVE_|GITHUB_|ACPX_|VERIFIED_))/.test(upper); + && !/^(?:LD_|DYLD_|GIT_CONFIG_|PAPERCLIP_(?:RUNNER_|NATIVE_|GITHUB_|ACPX_|CURSOR_CLOUD_|VERIFIED_))/.test(upper); } function checkedNames(names: unknown): string[] { diff --git a/packages/paperclip-runner/src/contracts/cursor-cloud.ts b/packages/paperclip-runner/src/contracts/cursor-cloud.ts new file mode 100644 index 00000000000..3062bddc3e5 --- /dev/null +++ b/packages/paperclip-runner/src/contracts/cursor-cloud.ts @@ -0,0 +1,51 @@ +export const CURSOR_CLOUD_DEFAULT_TIMEOUT_MS = 900_000; +export const CURSOR_CLOUD_CANCEL_TIMEOUT_MS = 20_000; +export const CURSOR_CLOUD_TERMINAL_DRAIN_TIMEOUT_MS = CURSOR_CLOUD_CANCEL_TIMEOUT_MS + 10_000; + +export interface NativeCursorCloudConfig { + schema: "paperclip.cursor-cloud.config.v1"; + repos: Array<{ url: string; startingRef?: string; prUrl?: string }>; + env?: { type: "cloud"; name?: string }; + workOnCurrentBranch?: boolean; + autoCreatePR?: boolean; + skipReviewerRequest?: boolean; + timeoutMs?: number; +} + +export function parseNativeCursorCloudConfig(value: unknown): NativeCursorCloudConfig { + if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("cursor_cloud_config_invalid"); + const config = value as Record; + const allowed = new Set(["schema", "repos", "env", "workOnCurrentBranch", "autoCreatePR", "skipReviewerRequest", "timeoutMs"]); + if (Object.keys(config).some(key => !allowed.has(key)) || config.schema !== "paperclip.cursor-cloud.config.v1" + || !Array.isArray(config.repos) || config.repos.length > 16) throw new Error("cursor_cloud_config_invalid"); + const validText = (text: unknown) => typeof text === "string" && text.length > 0 && text.length <= 2048 && !/[\x00-\x1f\x7f]/.test(text); + const repos = config.repos.map(value => { + if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("cursor_cloud_repository_invalid"); + const repo = value as Record; + if (Object.keys(repo).some(key => !["url", "startingRef", "prUrl"].includes(key)) || !validText(repo.url) + || (repo.startingRef !== undefined && !validText(repo.startingRef)) || (repo.prUrl !== undefined && !validText(repo.prUrl))) { + throw new Error("cursor_cloud_repository_invalid"); + } + const url = new URL(repo.url as string); + if (url.protocol !== "https:" || url.username || url.password || url.hash) throw new Error("cursor_cloud_repository_invalid"); + return { url: repo.url as string, ...(repo.startingRef !== undefined ? { startingRef: repo.startingRef as string } : {}), ...(repo.prUrl !== undefined ? { prUrl: repo.prUrl as string } : {}) }; + }); + let env: NativeCursorCloudConfig["env"]; + if (config.env !== undefined) { + if (!config.env || typeof config.env !== "object" || Array.isArray(config.env)) throw new Error("cursor_cloud_environment_invalid"); + const candidate = config.env as Record; + if (Object.keys(candidate).some(key => !["type", "name"].includes(key)) || candidate.type !== "cloud" || (candidate.name !== undefined && !validText(candidate.name))) throw new Error("cursor_cloud_environment_invalid"); + env = { type: "cloud", ...(candidate.name ? { name: candidate.name as string } : {}) }; + } + if (repos.length && env?.name) throw new Error("cursor_cloud_repository_and_named_environment_are_exclusive"); + if (!repos.length && !env?.name) throw new Error("cursor_cloud_repository_or_environment_required"); + for (const key of ["workOnCurrentBranch", "autoCreatePR", "skipReviewerRequest"]) { + if (config[key] !== undefined && typeof config[key] !== "boolean") throw new Error("cursor_cloud_config_invalid"); + } + if (config.timeoutMs !== undefined && (!Number.isSafeInteger(config.timeoutMs) || Number(config.timeoutMs) < 1000 || Number(config.timeoutMs) > 3_600_000)) throw new Error("cursor_cloud_timeout_invalid"); + return { schema: "paperclip.cursor-cloud.config.v1", repos, ...(env ? { env } : {}), + ...(config.workOnCurrentBranch !== undefined ? { workOnCurrentBranch: config.workOnCurrentBranch as boolean } : {}), + ...(config.autoCreatePR !== undefined ? { autoCreatePR: config.autoCreatePR as boolean } : {}), + ...(config.skipReviewerRequest !== undefined ? { skipReviewerRequest: config.skipReviewerRequest as boolean } : {}), + ...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs as number } : {}) }; +} diff --git a/packages/paperclip-runner/src/contracts/native-execution.test.ts b/packages/paperclip-runner/src/contracts/native-execution.test.ts index 160611117ad..6392e05c453 100644 --- a/packages/paperclip-runner/src/contracts/native-execution.test.ts +++ b/packages/paperclip-runner/src/contracts/native-execution.test.ts @@ -565,6 +565,34 @@ describe("NativeExecutionInputV2 planning", () => { planningContext: null, })).toMatchObject({ task: { workMode: "planning" }, executionMode: "default" }); }); + + const cloudContext = { + prompt: { revision: PAPERCLIP_EXECUTION_PROMPT_REVISION, text: PAPERCLIP_EXECUTION_PROMPT, digest: nativeRuntimePromptDigest() }, + instructions: { entryPath: "AGENTS.md", bundle: { schema: NATIVE_RUNTIME_ASSET_SCHEMA, digest: "0".repeat(64), manifestDigest: "0".repeat(64), rootPath: "/runtime/instructions", fileCount: 1, totalBytes: 1 } }, + skills: [], mcp: { assignmentSetId: "none", digest: "0".repeat(64), bindingId: null }, + } as const; + const cloudPlanning = { + ...planning, schema: "paperclip.native-execution-input.v5", + provider: { kind: "cursor_cloud", model: "explicit-cloud-model", cursorCloud: { schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/fixture" }] } }, + session: { ...planning.session, driverKind: "cursor_cloud_api" }, + runtimeContext: { ...cloudContext, aggregateDigest: canonicalNativeRuntimeContextDigest(cloudContext) }, + } as const; + + it("preserves Cursor Cloud semantic planning and its pinned revision in the model envelope", () => { + const parsed = parseNativeExecutionInput(cloudPlanning); + expect(parsed).toMatchObject({ provider: { kind: "cursor_cloud" }, task: { workMode: "planning" }, executionMode: "plan", planningContext: planning.planningContext }); + expect(buildNativeModelEnvelope(parsed)).toMatchObject({ executionMode: "plan", task: { workMode: "planning" }, planningContext: planning.planningContext }); + expect(parseNativeExecutionInput(JSON.parse(JSON.stringify(parsed)))).toEqual(parsed); + }); + + it.each([ + ["missing context", { planningContext: null }, "planningContext is required"], + ["standard task", { task: { ...cloudPlanning.task, workMode: "standard" } }, "requires planning work mode"], + ["default with context", { executionMode: "default" }, "only valid in plan execution mode"], + ["warm session", { session: { ...cloudPlanning.session, lifecyclePolicy: { mode: "warm", idleTimeoutMs: 1000 } } }, "Cursor Cloud requires"], + ])("keeps Cursor Cloud planning validation closed for %s", (_name, change, error) => { + expect(() => parseNativeExecutionInput({ ...cloudPlanning, ...change })).toThrow(error as string); + }); }); describe.each(["ask", "skill_test"])("NativeExecutionInputV2 %s mode", (workMode) => { diff --git a/packages/paperclip-runner/src/contracts/native-execution.ts b/packages/paperclip-runner/src/contracts/native-execution.ts index fe1d17a2e10..4ce817b79d5 100644 --- a/packages/paperclip-runner/src/contracts/native-execution.ts +++ b/packages/paperclip-runner/src/contracts/native-execution.ts @@ -1,3 +1,4 @@ +import { parseNativeCursorCloudConfig, type NativeCursorCloudConfig } from "./cursor-cloud.js"; import { resolveGrokDisableWebSearch } from "../drivers/acpx/grok-web-search.js"; import { resolveGrokEffort } from "../drivers/acpx/grok-effort.js"; import { resolveClaudeEffort } from "../drivers/acpx/claude-effort.js"; @@ -120,6 +121,7 @@ export interface NativeAcpxProfileSnapshot { } export type NativeProviderConfig = + | { kind: "cursor_cloud"; model: string; cursorCloud: NativeCursorCloudConfig } | { kind: "codex"; model: string | null; approvalPolicy?: NativeCodexApprovalPolicy } | { kind: "opencode"; model: string; permissionMode?: NativeOpenCodePermissionMode } | { @@ -154,7 +156,7 @@ export type NativeProviderConfig = export type NativeProviderConfigV4 = | { kind: "codex"; model: string | null; approvalPolicy: NativeCodexApprovalPolicy } | { kind: "opencode"; model: string; permissionMode: NativeOpenCodePermissionMode } - | Extract + | Extract | { kind: "acpx"; agent: NativeAcpxAgent; @@ -195,7 +197,7 @@ export interface NativeExecutionInputV1 { }; session: { normalizedSessionId: string | null; - driverKind: "codex_app_server" | "opencode_server" | "claude_managed_agents_api" | "aws_agentcore_harness_api" | "acpx_runtime"; + driverKind: "cursor_cloud_api" | "codex_app_server" | "opencode_server" | "claude_managed_agents_api" | "aws_agentcore_harness_api" | "acpx_runtime"; protocolVersion: 1; lifecyclePolicy: NativeSessionLifecyclePolicy; }; @@ -530,7 +532,8 @@ export function parseNativeExecutionInput(value: unknown): NativeExecutionInput } if ( ( - session.driverKind !== "codex_app_server" + session.driverKind !== "cursor_cloud_api" + && session.driverKind !== "codex_app_server" && session.driverKind !== "opencode_server" && session.driverKind !== "claude_managed_agents_api" && session.driverKind !== "aws_agentcore_harness_api" @@ -569,17 +572,20 @@ export function parseNativeExecutionInput(value: unknown): NativeExecutionInput ? { kind: "codex", model: null } : record(input.provider, "input.provider"); if ( - provider.kind !== "codex" + provider.kind !== "cursor_cloud" + && provider.kind !== "codex" && provider.kind !== "opencode" && provider.kind !== "claude_managed" && provider.kind !== "aws_agentcore" && provider.kind !== "acpx" ) { - throw new NativeExecutionInputError("input.provider.kind must be codex, opencode, claude_managed, aws_agentcore, or acpx"); + throw new NativeExecutionInputError("input.provider.kind must be cursor_cloud, codex, opencode, claude_managed, aws_agentcore, or acpx"); } exactKeys( provider, - provider.kind === "claude_managed" + provider.kind === "cursor_cloud" + ? ["kind", "model", "cursorCloud"] + : provider.kind === "claude_managed" ? ["kind", "model", "managedProfile", "maxSessionListCostUsd"] : provider.kind === "aws_agentcore" ? ["kind", "model", "agentCoreProfile", "maxEstimatedSessionCostUsd", "invocationLimits"] @@ -593,7 +599,8 @@ export function parseNativeExecutionInput(value: unknown): NativeExecutionInput "input.provider", ); if ( - (provider.kind === "codex" && session.driverKind !== "codex_app_server") + (provider.kind === "cursor_cloud" && session.driverKind !== "cursor_cloud_api") + || (provider.kind === "codex" && session.driverKind !== "codex_app_server") || (provider.kind === "opencode" && session.driverKind !== "opencode_server") || (provider.kind === "claude_managed" && session.driverKind !== "claude_managed_agents_api") || (provider.kind === "aws_agentcore" && session.driverKind !== "aws_agentcore_harness_api") @@ -608,7 +615,12 @@ export function parseNativeExecutionInput(value: unknown): NativeExecutionInput throw new NativeExecutionInputError("input.provider.model is required for opencode in provider/model form"); } let parsedProvider: NativeProviderConfigV9 | NativeProviderConfig | NativeProviderConfigV5; - if (provider.kind === "claude_managed") { + if (provider.kind === "cursor_cloud") { + if (!isV5 || !providerModel || providerModel.length > 240 || /[\x00-\x1f\x7f]/.test(providerModel) || lifecyclePolicy.mode !== "per_turn") { + throw new NativeExecutionInputError("Cursor Cloud requires a model and per-turn lifecycle in a v5 or later input"); + } + parsedProvider = { kind: "cursor_cloud", model: providerModel, cursorCloud: parseNativeCursorCloudConfig(provider.cursorCloud) }; + } else if (provider.kind === "claude_managed") { if (providerModel === null) { throw new NativeExecutionInputError("input.provider.model is required for claude_managed"); } @@ -994,7 +1006,7 @@ export function buildNativeModelEnvelope(input: NativeExecutionInput, options?: return { schema: NATIVE_MODEL_ENVELOPE_SCHEMA_V1, task: structuredClone(input.task), - workspace: input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" + workspace: input.provider.kind === "cursor_cloud" || input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" ? null : { cwd: input.workspace.cwd }, completionContract: structuredClone(input.completionContract.contract), @@ -1020,7 +1032,7 @@ export function buildNativeModelEnvelope(input: NativeExecutionInput, options?: }, executionMode: input.executionMode, planningContext: structuredClone(input.planningContext), - workspace: input.schema === NATIVE_EXECUTION_INPUT_SCHEMA_V6 || input.schema === NATIVE_EXECUTION_INPUT_SCHEMA_V8 || input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" ? null : { cwd: input.workspace.cwd }, + workspace: input.schema === NATIVE_EXECUTION_INPUT_SCHEMA_V6 || input.schema === NATIVE_EXECUTION_INPUT_SCHEMA_V8 || input.provider.kind === "cursor_cloud" || input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" ? null : { cwd: input.workspace.cwd }, completionContract: { ...structuredClone(input.completionContract.contract), criteria: input.completionContract.contract.criteria.map((criterion) => { @@ -1043,7 +1055,7 @@ export function buildNativeModelEnvelope(input: NativeExecutionInput, options?: }, executionMode: input.executionMode, planningContext: structuredClone(input.planningContext), - workspace: input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" + workspace: input.provider.kind === "cursor_cloud" || input.provider.kind === "claude_managed" || input.provider.kind === "aws_agentcore" ? null : { cwd: input.workspace.cwd }, completionContract: structuredClone(input.completionContract.contract), diff --git a/packages/paperclip-runner/src/contracts/native-session-backend.ts b/packages/paperclip-runner/src/contracts/native-session-backend.ts index 337698660d5..9761858e790 100644 --- a/packages/paperclip-runner/src/contracts/native-session-backend.ts +++ b/packages/paperclip-runner/src/contracts/native-session-backend.ts @@ -118,6 +118,7 @@ export function nativeRestartInterruptedTurnId(snapshot: Pick; + terminalDrainTimeoutMs?: number; } export interface NativeSessionSnapshotOptions { diff --git a/packages/paperclip-runner/src/control-plane/cursor-cloud-runner-launch.test.ts b/packages/paperclip-runner/src/control-plane/cursor-cloud-runner-launch.test.ts new file mode 100644 index 00000000000..14b87373c9c --- /dev/null +++ b/packages/paperclip-runner/src/control-plane/cursor-cloud-runner-launch.test.ts @@ -0,0 +1,666 @@ +import { createHash } from "node:crypto"; +import { RUNNER_TOOL_SCOPE_TOKEN_HEADER } from "../drivers/runner-tool-bridge.js"; +import { execFileSync } from "node:child_process"; +import { cp, mkdir, mkdtemp, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { request } from "node:http"; +import { fileURLToPath } from "node:url"; +import { expect, it, vi } from "vitest"; +import { createRunnerdNativeSessionBackend } from "../backends/codex-native-backend.js"; +import type { NativeExecutionInputV5 } from "../contracts/native-execution.js"; +import { canonicalNativeRuntimeContextDigest, NATIVE_RUNTIME_ASSET_SCHEMA, PAPERCLIP_EXECUTION_PROMPT, PAPERCLIP_EXECUTION_PROMPT_REVISION, nativeRuntimePromptDigest } from "../contracts/runtime-context.js"; +import { executeNativeSession } from "../native-session-runtime.js"; +import type { PrpEvent, PrpStructuredRunResult } from "../protocol/replay-contract.js"; +import type { DurablePrpControlPlane } from "./durable-prp-control-plane.js"; +import { createRunnerdCodexTransport, defaultCapabilityRunnerdBinary } from "../live/runnerd-codex-transport.js"; +import { copyOwnedNodeRuntime } from "../test-support/owned-node-runtime.js"; + +async function privateCloudNodeCommand(root: string): Promise { + const directory = join(root, "provider-node"); + await mkdir(directory, { mode: 0o700 }); + const { executable } = await copyOwnedNodeRuntime(directory); + // Keep Node's name so the verified launcher selects its descriptor loader. + const command = join(directory, process.platform === "win32" ? "node.exe" : "node"); + await rename(executable, command); + return command; +} + +function buildPrivateCursorCloudProxy(proxyPath: string): void { + const packageRoot = fileURLToPath(new URL("../..", import.meta.url)); + const builderUrl = new URL("../../scripts/build-verified-provider-entrypoints.mjs", import.meta.url).href; + execFileSync(process.execPath, ["--input-type=module", "-e", [ + "import { writeFile } from 'node:fs/promises';", + `const { bundleVerifiedProviderEntrypoints } = await import(${JSON.stringify(builderUrl)});`, + "const item = (await bundleVerifiedProviderEntrypoints({ write: false })).find(value => value.entrypoint.name === 'cursor-cloud-app-server-proxy');", + `await writeFile(${JSON.stringify(proxyPath)}, item.verifiedResult.outputFiles[0].contents, { mode: 0o600 });`, + ].join("\n")], { cwd: packageRoot, timeout: 20_000, stdio: "pipe" }); +} + +async function currentCloudScopeHeader(runtime: string, sessionId: string): Promise { + const name = `checkpoint-${createHash("sha256").update(sessionId).digest("hex")}.json`; + const checkpoint = JSON.parse(await readFile(join(runtime, name), "utf8")); + expect(checkpoint.relayTurnToken).toMatch(/^[A-Za-z0-9_-]{43}$/); + return `Bearer ${checkpoint.relayTurnToken}`; +} + +it("settles a create rejected during real-facade Stop before cold recovery and the next run", async () => { + const root = await mkdtemp("/tmp/cc-rejected-stop-"); + const runtime = join(root, "cloud"), stateDirectory = join(root, "session"); + const configPath = join(runtime, "config.json"), socketPath = join(root, "mcp.sock"), proxyPath = join(root, "proxy.cjs"); + const fetchLog = join(root, "fetches.jsonl"), remotePath = join(root, "remote.json"); + const createSeen = join(root, "create-seen"), stopHeld = join(root, "stop-held"), releaseStop = join(root, "release-stop"); + const releaseCreate = join(root, "release-create"), rejected = join(root, "rejected"); + const normalizedSessionId = "cloud-rejected-stop-session"; + buildPrivateCursorCloudProxy(proxyPath); + const providerNodeCommand = await privateCloudNodeCommand(root); + const prelude = Buffer.from(`;(() => { + const assert = require('node:assert/strict'), fs = require('node:fs'), fsp = require('node:fs/promises'); + const paths = ${JSON.stringify({ createSeen, stopHeld, releaseStop, releaseCreate, rejected, fetchLog, remotePath })}; + const wait = async path => { const end = Date.now() + 15000; while (!fs.existsSync(path)) { assert.ok(Date.now() < end, 'controlled gate expired'); await new Promise(resolve => setTimeout(resolve, 5)); } }; + const rename = fsp.rename; let held = false; + fsp.rename = async function(from, to) { + await rename.call(this, from, to); + if (!held && /checkpoint-[a-f0-9]{64}\\.json$/.test(String(to)) && JSON.parse(fs.readFileSync(to, 'utf8')).phase === 'stopping') { + held = true; fs.writeFileSync(paths.stopHeld, 'held'); await wait(paths.releaseStop); + } + }; + const now = '2026-10-30T00:00:00Z', json = (value, status = 200) => new Response(JSON.stringify(value), { status, headers: { 'content-type': 'application/json' } }); + globalThis.fetch = async (input, init = {}) => { + const target = new URL(String(input)), method = init.method ?? 'GET'; assert.equal(target.origin, 'https://api.cursor.com'); + fs.appendFileSync(paths.fetchLog, JSON.stringify({ method, path: target.pathname, pid: process.pid }) + '\\n'); + if (method === 'POST' && target.pathname === '/v1/agents') { + if (!fs.existsSync(paths.rejected)) { + fs.writeFileSync(paths.createSeen, 'seen'); await wait(paths.releaseCreate); fs.writeFileSync(paths.rejected, 'rejected'); + return json({ message: 'controlled definitive rejection' }, 422); + } + const body = JSON.parse(String(init.body)); + const run = { id: 'run-33333333-3333-4333-8333-333333333333', agentId: body.agentId, status: 'RUNNING', createdAt: now, updatedAt: now }; + fs.writeFileSync(paths.remotePath, JSON.stringify(run)); + return json({ agent: { id: body.agentId, status: 'ACTIVE', env: { type: 'cloud' }, url: 'https://cursor.com/agents/' + body.agentId, createdAt: now, updatedAt: now, latestRunId: run.id }, run }); + } + assert.ok(fs.existsSync(paths.remotePath), 'rejected create must not be reconciled as accepted work'); + const run = JSON.parse(fs.readFileSync(paths.remotePath, 'utf8')); + const runPath = '/v1/agents/' + run.agentId + '/runs/' + run.id; + if (method === 'GET' && target.pathname === runPath + '/stream') return new Response(new ReadableStream({ start(controller) { + init.signal?.addEventListener('abort', () => { try { controller.close(); } catch {} }, { once: true }); + } }), { headers: { 'content-type': 'text/event-stream' } }); + if (method === 'POST' && target.pathname === runPath + '/cancel') { run.status = 'CANCELLED'; fs.writeFileSync(paths.remotePath, JSON.stringify(run)); return json({ id: run.id }); } + if (method === 'GET' && target.pathname === runPath) return json(run); + throw new Error('Unexpected controlled Cloud request'); + }; + })();\n`); + const built = await readFile(proxyPath), firstLine = built.indexOf(10) + 1; + await writeFile(proxyPath, Buffer.concat([built.subarray(0, firstLine), prelude, built.subarray(firstLine)]), { mode: 0o600 }); + await mkdir(runtime, { mode: 0o700 }); + const cursorCloud = { schema: "paperclip.cursor-cloud.config.v1" as const, repos: [{ url: "https://github.com/example/repo" }] }; + await writeFile(configPath, JSON.stringify({ ...cursorCloud, binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId } }), { mode: 0o600 }); + const identity = { runnerInstanceId: "runner-cloud-rejected", environmentLeaseId: "lease-cloud-rejected", runId: "00000000-0000-4000-8000-000000000781", normalizedSessionId, turnId: "turn-rejected", itemId: "item-rejected" }; + const environment = { PATH: process.env.PATH, CURSOR_API_KEY: "synthetic-key", PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, + PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: join(runtime, "artifacts"), PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: socketPath, + PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "synthetic-token", PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp", + PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 60_000) }; + const options = { provider: "cursor_cloud" as const, cursorCloud, stateDirectory, runnerBinary: defaultCapabilityRunnerdBinary(), providerNodeCommand, + cursorCloudProxyPath: proxyPath, cursorCloudProxySha256: `sha256:${createHash("sha256").update(await readFile(proxyPath)).digest("hex")}`, + lifecyclePolicy: { mode: "per_turn" as const }, environment }; + const first = createRunnerdCodexTransport({ ...options, prpIdentity: identity }), bundles = [first]; + let stop: Promise | undefined; + try { + await first.transport.request("thread/start", { cwd: root, model: "pinned-model", baseInstructions: "Only the assigned task.", dynamicTools: [] }); + await first.transport.request("turn/start", { input: [{ type: "text", text: "Controlled rejected task" }] }); + await vi.waitFor(async () => expect(await readFile(createSeen, "utf8")).toBe("seen")); + const checkpointPath = join(runtime, `checkpoint-${createHash("sha256").update(normalizedSessionId).digest("hex")}.json`); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "creating", pendingOperation: "create_agent" }); + let stopDone = false; + stop = first.transport.request("turn/interrupt", {}).finally(() => { stopDone = true; }); + await vi.waitFor(async () => expect(await readFile(stopHeld, "utf8")).toBe("held")); + await writeFile(releaseCreate, "release"); + await vi.waitFor(async () => expect(await readFile(rejected, "utf8")).toBe("rejected")); + expect(stopDone).toBe(false); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "stopping", pendingOperation: "create_agent" }); + await writeFile(releaseStop, "release"); await stop; + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "idle", terminalStatus: "REJECTED", pendingOperation: null, requestedAgentId: null }); + expect((await readFile(fetchLog, "utf8")).trim().split("\n").map(line => JSON.parse(line))).toMatchObject([{ method: "POST", path: "/v1/agents" }]); + await first.transport.close(); expect(first.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + const stopped = JSON.parse(await readFile(join(stateDirectory, "runner", "codex-provider-state.json"), "utf8")); + expect(stopped).toMatchObject({ lifecycle: "prepared", providerTerminationReceipt: { remoteStopped: true, remoteRunId: null } }); + const recovered = createRunnerdCodexTransport({ ...options, prpIdentity: identity, resumeProviderSession: { driverSessionId: normalizedSessionId, providerSessionId: normalizedSessionId } }); bundles.push(recovered); + await expect(recovered.transport.request("thread/read", {})).resolves.toMatchObject({ thread: { id: normalizedSessionId } }); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "idle", terminalStatus: "REJECTED", pendingOperation: null }); + await recovered.transport.close(); expect(recovered.evidence().runnerExited).toBe(true); + const next = createRunnerdCodexTransport({ ...options, prpIdentity: { ...identity, runId: "00000000-0000-4000-8000-000000000782", turnId: "turn-next", itemId: "item-next" }, baseInstructions: "Only the next assigned task." }); bundles.push(next); + await next.transport.request("thread/read", {}); + await next.transport.request("turn/start", { input: [{ type: "text", text: "Next admitted task" }] }); + await vi.waitFor(async () => expect(JSON.parse(await readFile(remotePath, "utf8"))).toMatchObject({ status: "RUNNING" })); + await next.transport.request("turn/interrupt", {}); await next.transport.close(); + expect(next.evidence().runnerExited).toBe(true); + expect(JSON.parse(await readFile(remotePath, "utf8"))).toMatchObject({ status: "CANCELLED" }); + const creates = (await readFile(fetchLog, "utf8")).trim().split("\n").map(line => JSON.parse(line)).filter(call => call.method === "POST" && call.path === "/v1/agents"); + expect(creates).toHaveLength(2); expect(creates[1].pid).not.toBe(creates[0].pid); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + } finally { + await writeFile(releaseCreate, "release"); await writeFile(releaseStop, "release"); + await stop?.catch(() => undefined); + for (const bundle of bundles) await bundle.transport.close().catch(() => undefined); + await rm(root, { recursive: true, force: true }); + } +}, 60_000); + +it("opens and closes the real Cloud facade without a provider prompt", async () => { + const root = await mkdtemp("/tmp/cc-runner-launch-"); + const runtime = join(root, "cloud"); + const configPath = join(runtime, "config.json"); + const socketPath = join(root, "mcp.sock"); + const fetchLog = join(root, "unexpected-fetches.jsonl"); + const proxyPath = join(root, "cloud-proxy.cjs"); + buildPrivateCursorCloudProxy(proxyPath); + const providerNodeCommand = await privateCloudNodeCommand(root); + const builtProxy = await readFile(proxyPath); + const firstLine = builtProxy.indexOf(10) + 1; + const guard = Buffer.from(`globalThis.fetch = async () => { require("node:fs").appendFileSync(${JSON.stringify(fetchLog)}, "unexpected fetch\\n", { mode: 0o600 }); throw new Error("Cloud launch preflight forbids provider requests"); };\n`); + await writeFile(proxyPath, Buffer.concat([builtProxy.subarray(0, firstLine), guard, builtProxy.subarray(firstLine)]), { mode: 0o600 }); + await mkdir(runtime, { mode: 0o700 }); + const normalizedSessionId = "cloud-launch-session"; + const cursorCloud = { schema: "paperclip.cursor-cloud.config.v1" as const, repos: [{ url: "https://github.com/example/repo" }] }; + await writeFile(configPath, JSON.stringify({ ...cursorCloud, binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId } }), { mode: 0o600 }); + const bundle = createRunnerdCodexTransport({ + provider: "cursor_cloud", cursorCloud, + stateDirectory: join(root, "runner-session"), + runnerBinary: defaultCapabilityRunnerdBinary(), providerNodeCommand, + cursorCloudProxyPath: proxyPath, + cursorCloudProxySha256: `sha256:${createHash("sha256").update(await readFile(proxyPath)).digest("hex")}`, + lifecyclePolicy: { mode: "per_turn" }, + prpIdentity: { runnerInstanceId: "runner-cloud-launch", environmentLeaseId: "lease-cloud-launch", + runId: "00000000-0000-4000-8000-000000000761", normalizedSessionId, turnId: "turn-cloud-launch", itemId: "item-cloud-launch" }, + environment: { + PATH: process.env.PATH, + CURSOR_API_KEY: "synthetic-cloud-launch-key", + PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, + PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: join(runtime, "artifacts"), + PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: socketPath, + PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "synthetic-cloud-relay-token", + PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp/native-runs/00000000-0000-4000-8000-000000000761", + PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 60_000), + }, + }); + try { + await expect(bundle.transport.request("thread/start", { cwd: root, model: "explicit-model", baseInstructions: "Do only the assigned task.", dynamicTools: [] })) + .resolves.toMatchObject({ thread: { id: normalizedSessionId } }); + expect((await stat(socketPath)).isSocket()).toBe(true); + const checkpointName = (await readdir(runtime)).find(name => /^checkpoint-[a-f0-9]{64}\.json$/u.test(name)); + expect(checkpointName).toBeDefined(); + const checkpoint = JSON.parse(await readFile(join(runtime, checkpointName!), "utf8")); + expect(checkpoint).toMatchObject({ phase: "idle", agentId: null, runId: null, pendingOperation: null }); + await bundle.transport.close(); + expect(bundle.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + await expect(stat(fetchLog)).rejects.toHaveProperty("code", "ENOENT"); + } finally { + await bundle.transport.close().catch(() => undefined); + await rm(root, { recursive: true, force: true }); + } +}, 30_000); + +it("preserves native Cloud tool identity and redacted output through the real Rust facade", async () => { + const root = await mkdtemp("/tmp/cc-tool-facade-"); + const runtime = join(root, "cloud"); + const configPath = join(runtime, "config.json"); + const socketPath = join(root, "mcp.sock"); + const proxyPath = join(root, "cloud-proxy.cjs"); + const fetchLog = join(root, "controlled-fetches.jsonl"); + buildPrivateCursorCloudProxy(proxyPath); + const providerNodeCommand = await privateCloudNodeCommand(root); + const runId = "run-22222222-2222-4222-8222-222222222222"; + const fixture = Buffer.from(`;(() => { + const assert = require('node:assert/strict'), fs = require('node:fs'); + let agentId = '', status = 'RUNNING'; + const now = '2026-10-28T00:00:00Z', runId = ${JSON.stringify(runId)}; + const json = value => new Response(JSON.stringify(value), { headers: { 'content-type': 'application/json' } }); + const run = () => ({ id: runId, agentId, status, createdAt: now, updatedAt: now }); + globalThis.fetch = async (input, init = {}) => { + const target = new URL(String(input)); assert.equal(target.origin, 'https://api.cursor.com'); + const path = target.pathname, method = init.method ?? 'GET'; + fs.appendFileSync(${JSON.stringify(fetchLog)}, JSON.stringify({ method, path }) + '\\n', { mode: 0o600 }); + if (path === '/v1/agents' && method === 'POST') { + agentId = JSON.parse(String(init.body)).agentId; + return json({ agent: { id: agentId, status: 'ACTIVE', env: { type: 'cloud' }, url: 'https://cursor.com/agents/' + agentId, createdAt: now, updatedAt: now, latestRunId: runId }, run: run() }); + } + assert.equal(path.startsWith('/v1/agents/' + agentId + '/runs/' + runId), true); + if (path.endsWith('/stream') && method === 'GET') return new Response(new ReadableStream({ start(controller) { + const args = { toolCallId: 'synthetic-private-argument' }; + const result = { error: { message: 'Discovery failed synthetic-cloud-launch-key synthetic-cloud-relay-token' } }; + for (const [index, state] of ['running', 'error'].entries()) controller.enqueue(new TextEncoder().encode('id: ' + (index + 1) + '\\nevent: tool_call\\ndata: ' + JSON.stringify({ callId: 'cloud-native-tool', name: 'get_mcp_tools', status: state, args, result }) + '\\n\\n')); + init.signal?.addEventListener('abort', () => { try { controller.close(); } catch {} }, { once: true }); + } }), { headers: { 'content-type': 'text/event-stream' } }); + if (path.endsWith('/cancel') && method === 'POST') { status = 'CANCELLED'; return json({ id: runId }); } + if (path.endsWith('/' + runId) && method === 'GET') return json(run()); + throw new Error('Unexpected controlled Cloud request'); + }; + })();\n`); + const builtProxy = await readFile(proxyPath); + const firstLine = builtProxy.indexOf(10) + 1; + await writeFile(proxyPath, Buffer.concat([builtProxy.subarray(0, firstLine), fixture, builtProxy.subarray(firstLine)]), { mode: 0o600 }); + await mkdir(runtime, { mode: 0o700 }); + const normalizedSessionId = "cloud-tool-facade-session"; + const cursorCloud = { schema: "paperclip.cursor-cloud.config.v1" as const, repos: [{ url: "https://github.com/example/repo" }] }; + await writeFile(configPath, JSON.stringify({ ...cursorCloud, binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId } }), { mode: 0o600 }); + let authority: DurablePrpControlPlane | undefined; + const bundle = createRunnerdCodexTransport({ + provider: "cursor_cloud", cursorCloud, stateDirectory: join(root, "runner-session"), + runnerBinary: defaultCapabilityRunnerdBinary(), providerNodeCommand, cursorCloudProxyPath: proxyPath, + cursorCloudProxySha256: `sha256:${createHash("sha256").update(await readFile(proxyPath)).digest("hex")}`, + lifecyclePolicy: { mode: "per_turn" }, + prpIdentity: { runnerInstanceId: "runner-cloud-tool", environmentLeaseId: "lease-cloud-tool", + runId: "00000000-0000-4000-8000-000000000762", normalizedSessionId, turnId: "turn-cloud-tool", itemId: "item-cloud-tool" }, + environment: { + PATH: process.env.PATH, CURSOR_API_KEY: "synthetic-cloud-launch-key", + PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: join(runtime, "artifacts"), + PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: socketPath, PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "synthetic-cloud-relay-token", + PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp", PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 60_000), + }, + controlPlaneRegistration: async core => { authority = core; await core.start(); return { release: () => undefined }; }, + }); + const tools = (): Array> => authority!.store.state.committedEvents.filter(event => event.eventType.startsWith("tool.execution.")).map(event => ({ + eventType: event.eventType, ...((event.envelope.payload as Record).payload as Record), + })); + try { + const opened = await bundle.transport.request("thread/start", { cwd: root, model: "explicit-model", baseInstructions: "Use the assigned tools.", dynamicTools: [] }); + await bundle.transport.request("turn/start", { threadId: (opened.thread as { id: string }).id, input: [{ type: "text", text: "Use the tool." }] }); + await vi.waitFor(() => expect(tools()).toHaveLength(2), { timeout: 10_000 }); + expect(tools()).toMatchObject([ + { eventType: "tool.execution.started", executionId: "cloud-native-tool", transport: "builtin", name: "get_mcp_tools", status: "running", output: expect.stringContaining("Discovery failed [redacted] [redacted]") }, + { eventType: "tool.execution.completed", executionId: "cloud-native-tool", transport: "builtin", name: "get_mcp_tools", status: "failed", output: expect.stringContaining("Discovery failed [redacted] [redacted]") }, + ]); + for (const tool of tools()) { + expect(JSON.parse(String(tool.output))).toEqual({ error: { message: "Discovery failed [redacted] [redacted]" } }); + expect(tool).not.toHaveProperty("arguments"); + expect(JSON.stringify(tool)).not.toContain("synthetic-private-argument"); + } + await bundle.transport.close(); + expect(bundle.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + const calls = (await readFile(fetchLog, "utf8")).trim().split("\n").map(line => JSON.parse(line)); + expect(calls.filter(call => call.path === "/v1/agents" && call.method === "POST")).toHaveLength(1); + expect(calls.filter(call => call.path.endsWith("/cancel") && call.method === "POST")).toHaveLength(1); + } finally { + await bundle.transport.close().catch(() => undefined); + await authority?.stop(); + await rm(root, { recursive: true, force: true }); + } +}, 30_000); + +async function cloudQuestionHandoff(terminalDelayMs: number, governed: boolean, planning = false) { + const root = await mkdtemp("/tmp/cc-question-"); + const runtime = join(root, "cloud"); + const configPath = join(runtime, "config.json"); + const socketPath = join(root, "mcp.sock"); + const proxyPath = join(root, "cloud-proxy.cjs"); + const fetchLog = join(root, "controlled-fetches.jsonl"); + buildPrivateCursorCloudProxy(proxyPath); + const providerNodeCommand = await privateCloudNodeCommand(root); + const runId = "run-22222222-2222-4222-8222-222222222222"; + const fixture = Buffer.from(`;(() => { + const assert = require('node:assert/strict'), fs = require('node:fs'); + let agentId = '', status = 'RUNNING'; + const now = '2026-10-28T00:00:00Z', runId = ${JSON.stringify(runId)}; + const json = value => new Response(JSON.stringify(value), { headers: { 'content-type': 'application/json' } }); + const run = () => ({ id: runId, agentId, status, createdAt: now, updatedAt: now }); + globalThis.fetch = async (input, init = {}) => { + const target = new URL(String(input)); assert.equal(target.origin, 'https://api.cursor.com'); + const path = target.pathname, method = init.method ?? 'GET'; + fs.appendFileSync(${JSON.stringify(fetchLog)}, JSON.stringify({ method, path }) + '\\n', { mode: 0o600 }); + if (path === '/v1/agents' && method === 'POST') { + if (${planning}) { + const body = JSON.parse(String(init.body)); + assert.equal(body.mode, 'agent'); + const envelope = JSON.parse(body.prompt.text.split('\\n\\nPaperclip task:\\n').at(-1)); + assert.equal(envelope.executionMode, 'plan'); + assert.equal(envelope.task.workMode, 'planning'); + assert.equal(envelope.planningContext.baseRevisionId, 'plan-revision-3'); + assert.equal(envelope.planningContext.markdown, '# Pinned canonical plan'); + } + agentId = JSON.parse(String(init.body)).agentId; + return json({ agent: { id: agentId, status: 'ACTIVE', env: { type: 'cloud' }, url: 'https://cursor.com/agents/' + agentId, createdAt: now, updatedAt: now, latestRunId: runId }, run: run() }); + } + assert.equal(path.startsWith('/v1/agents/' + agentId + '/runs/' + runId), true); + if (path.endsWith('/stream') && method === 'GET') return new Response(new ReadableStream({ start(controller) { + init.signal?.addEventListener('abort', () => { try { controller.close(); } catch {} }, { once: true }); + } }), { headers: { 'content-type': 'text/event-stream' } }); + if (path.endsWith('/cancel') && method === 'POST') { await new Promise(resolve => setTimeout(resolve, ${terminalDelayMs})); status = 'FINISHED'; return json({ id: runId }); } + if (path.endsWith('/' + runId) && method === 'GET') return json(run()); + throw new Error('Unexpected controlled Cloud request'); + }; + })();\n`); + const builtProxy = await readFile(proxyPath); + const firstLine = builtProxy.indexOf(10) + 1; + await writeFile(proxyPath, Buffer.concat([builtProxy.subarray(0, firstLine), fixture, builtProxy.subarray(firstLine)]), { mode: 0o600 }); + await mkdir(runtime, { mode: 0o700 }); + const normalizedSessionId = "cloud-question-session"; + const cursorCloud = { schema: "paperclip.cursor-cloud.config.v1" as const, repos: [{ url: "https://github.com/example/repo" }] }; + await writeFile(configPath, JSON.stringify({ ...cursorCloud, binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId } }), { mode: 0o600 }); + let authority: DurablePrpControlPlane | undefined; + const bundle = createRunnerdCodexTransport({ + provider: "cursor_cloud", cursorCloud, stateDirectory: join(root, "runner-session"), + runnerBinary: defaultCapabilityRunnerdBinary(), providerNodeCommand, cursorCloudProxyPath: proxyPath, + cursorCloudProxySha256: `sha256:${createHash("sha256").update(await readFile(proxyPath)).digest("hex")}`, + lifecyclePolicy: { mode: "per_turn" }, + prpIdentity: { runnerInstanceId: "runner-cloud-question", environmentLeaseId: "lease-cloud-question", + runId: "00000000-0000-4000-8000-000000000763", normalizedSessionId, turnId: "turn-cloud-question", itemId: "item-cloud-question" }, + environment: { + PATH: process.env.PATH, CURSOR_API_KEY: "synthetic-cloud-launch-key", + PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: join(runtime, "artifacts"), + PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: socketPath, PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "synthetic-cloud-relay-token", + PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp", PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 60_000), + }, + controlPlaneRegistration: async core => { authority = core; await core.start(); return { release: () => undefined }; }, + }); + const questionApplied = vi.fn(async () => ({ success: true, contentItems: [{ type: "inputText", text: JSON.stringify({ status: "applied", questionId: "question-controlled" }) }] })); + bundle.transport.setServerRequestHandler(questionApplied); + const mcp = async (body: Record, sessionId?: string): Promise<{ sessionId?: string; value: any }> => { + const scopeHeader = await currentCloudScopeHeader(runtime, normalizedSessionId); + return new Promise((accept, reject) => { + const req = request({ socketPath, path: "/mcp", method: "POST", headers: { Authorization: "Bearer synthetic-cloud-relay-token", [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: scopeHeader, "content-type": "application/json", ...(sessionId ? { "Mcp-Session-Id": sessionId } : {}) } }, response => { + let text = ""; + response.on("data", chunk => { text += chunk; }); + response.on("end", () => accept({ sessionId: response.headers["mcp-session-id"] as string | undefined, value: JSON.parse(text) })); + }); + req.on("error", reject); + req.end(JSON.stringify({ jsonrpc: "2.0", ...body })); + }); + }; + try { + if (governed) { + await writeFile(join(root, "AGENTS.md"), "Keep assigned instructions."); + const digest = "0".repeat(64); + const context = { + prompt: { revision: PAPERCLIP_EXECUTION_PROMPT_REVISION, text: PAPERCLIP_EXECUTION_PROMPT, digest: nativeRuntimePromptDigest() }, + instructions: { entryPath: "AGENTS.md", bundle: { schema: NATIVE_RUNTIME_ASSET_SCHEMA, digest, manifestDigest: digest, rootPath: root, fileCount: 1, totalBytes: 27 } }, + skills: [], mcp: { assignmentSetId: "none", digest, bindingId: null }, + }; + const input: NativeExecutionInputV5 = { + schema: "paperclip.native-execution-input.v5", executionMode: planning ? "plan" : "default", + planningContext: planning ? { documentId: "plan-document", baseRevisionId: "plan-revision-3", baseRevisionNumber: 3, + markdown: "# Pinned canonical plan", sha256: createHash("sha256").update("# Pinned canonical plan").digest("hex"), reviewContext: { feedback: "Keep the requested scope" } } : null, + binding: { companyId: "company", agentId: "agent", issueId: "issue", runId: "00000000-0000-4000-8000-000000000763", executionWorkspaceId: "workspace" }, + task: { identifier: "CLOUD-QUESTION", title: "Ask the assigned question", description: null, prompt: "Ask before proceeding.", workMode: planning ? "planning" : "standard" }, + workspace: { cwd: root, repoUrl: null, repoRef: null, branchName: null }, + session: { normalizedSessionId, driverKind: "cursor_cloud_api", protocolVersion: 1, lifecyclePolicy: { mode: "per_turn", idleTimeoutMs: null } }, + provider: { kind: "cursor_cloud", model: "explicit-model", cursorCloud }, + runtimeContext: { ...context, aggregateDigest: canonicalNativeRuntimeContextDigest(context) }, + completionContract: { id: "contract", sha256: digest, schemaVersion: "paperclip.completion-contract.v1", contract: { revision: "1", objective: "Ask before proceeding.", criteria: [{ id: "question", requirement: "Request the response." }] } }, + interactionResponses: [], credentialBindings: [], + }; + const yielded: PrpStructuredRunResult = { + schema: "paperclip.run_result.v1", reportedWorkDisposition: "yielded", summary: "Waiting for the requested response.", + completionClaim: { contractRevision: "1", objectiveSatisfied: false, criteria: [{ criterionId: "question", status: "unknown", evidenceRefs: ["interaction:pending"] }], remainingWork: [{ description: "Resume after the response.", blocksCompletion: true }] }, + evidence: [{ ref: "interaction:pending" }], verification: [], attentionRequests: [], artifacts: [{ kind: "issue_thread_interaction", ref: "interaction:pending" }], + continuation: { kind: "response_wake", summary: "Resume from the answer.", idempotencyKey: "interaction-response:pending" }, + }; + const backend = createRunnerdNativeSessionBackend(input, { runnerInstanceId: "runner-cloud-question", transportFactory: () => bundle.transport, + dynamicTools: [{ name: "request_human_input", description: "Ask the user a required question.", inputSchema: { type: "object", properties: {}, additionalProperties: false } }], + dynamicToolHandler: questionApplied, + }); + const history: PrpEvent[] = []; + const completeRun = vi.fn(async () => undefined); + const execution = executeNativeSession({ input, backend, runnerInstanceId: "runner-cloud-question", controlPlaneInstanceId: "control-cloud-question", timeoutMs: 120_000, + controlPlane: { + async openRun() {}, async checkpointSession() {}, completeRun, + async appendEvent(event) { history.push(event); return { cursor: history.length, highestContiguousSourceSeq: event.sourceSeq, disposition: "committed" }; }, + async replayEvents(replay) { return { events: history.filter(event => event.sourceInstanceId === replay.sourceInstanceId && event.sourceSeq > replay.afterSourceSeq), highestContiguousSourceSeq: 0 }; }, + }, + resolveGovernedWait: ({ event }) => event.eventType === "item.completed" && event.payload.kind === "dynamicToolCall" ? yielded : null, + }); + void execution.catch(() => undefined); + await Promise.race([execution, vi.waitFor(() => expect(authority?.store.state.commands.some(command => command.type === "turn.start" && command.status === "completed")).toBe(true), { timeout: 10_000 })]); + const initialized = await mcp({ id: 0, method: "initialize" }); + const response = await mcp({ id: 1, method: "tools/call", params: { name: "request_human_input", arguments: {} } }, initialized.sessionId); + expect(response.value.result.isError).not.toBe(true); + await expect(execution).resolves.toMatchObject({ result: yielded }); + expect(completeRun).toHaveBeenCalledOnce(); + expect(history.some(event => event.eventType === "turn.interrupted")).toBe(true); + } else { + const opened = await bundle.transport.request("thread/start", { cwd: root, model: "explicit-model", baseInstructions: "Ask the assigned question.", dynamicTools: [{ name: "request_human_input", description: "Ask the user a required question.", inputSchema: { type: "object", properties: {}, additionalProperties: false } }] }); + const threadId = (opened.thread as { id: string }).id; + const started = await bundle.transport.request("turn/start", { threadId, input: [{ type: "text", text: "Ask before proceeding." }] }); + const initialized = await mcp({ id: 0, method: "initialize" }); + const response = await mcp({ id: 1, method: "tools/call", params: { name: "request_human_input", arguments: {} } }, initialized.sessionId); + expect(response.value.result.isError).not.toBe(true); + expect(JSON.stringify(response.value)).toContain("question-controlled"); + expect(questionApplied).toHaveBeenCalledOnce(); + await bundle.transport.request("turn/interrupt", { threadId, turnId: (started.turn as { id: string }).id }); + await vi.waitFor(() => expect(authority!.store.state.committedEvents.some(event => event.eventType === "turn.interrupted")).toBe(true), { timeout: 5_000 }); + expect(authority!.store.state.commands.some(command => command.type === "turn.stop")).toBe(false); + expect(authority!.store.state.committedEvents.filter(event => ["turn.interrupted", "turn.completed", "turn.failed"].includes(event.eventType))).toHaveLength(1); + expect(authority!.store.state.commands.filter(command => command.type === "semantic_tool.result")).toHaveLength(1); + } + await bundle.transport.close(); + expect(bundle.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + const calls = (await readFile(fetchLog, "utf8")).trim().split("\n").map(line => JSON.parse(line)); + expect(calls.filter(call => call.path === "/v1/agents" && call.method === "POST")).toHaveLength(1); + expect(calls.filter(call => call.path.endsWith("/cancel") && call.method === "POST")).toHaveLength(1); + } finally { + await bundle.transport.close().catch(() => undefined); + await authority?.stop(); + await rm(root, { recursive: true, force: true }); + } +} + +it.each([0, 18_000])("delivers an applied Cloud question and courtesy-interrupt terminal without Stop (%ims)", async terminalDelayMs => { + await cloudQuestionHandoff(terminalDelayMs, false); +}, 40_000); + +it.each([0, 18_000])("settles a governed Cloud question after its allowed cancellation latency (%ims)", async terminalDelayMs => { + await cloudQuestionHandoff(terminalDelayMs, true); +}, 45_000); + +it("preserves semantic planning and its pinned revision through the real Rust Cloud default harness", async () => { + await cloudQuestionHandoff(0, true, true); +}, 30_000); + +async function cloudColdAuthorityRotation(instructions: string, validShutdown = true) { + const root = await mkdtemp("/tmp/cc-cold-rotation-"); + const runtime = join(root, "cloud"); + const stateDirectory = join(root, "session"); + const configPath = join(runtime, "config.json"); + const socketPath = join(root, "mcp.sock"); + const proxyPath = join(root, "cloud-proxy.cjs"); + const fetchLog = join(root, "fetches.jsonl"); + const remoteStatePath = join(root, "remote.json"); + buildPrivateCursorCloudProxy(proxyPath); + const providerNodeCommand = await privateCloudNodeCommand(root); + const fixture = Buffer.from(`;(() => { + const assert = require('node:assert/strict'), fs = require('node:fs'); + if (!${JSON.stringify(validShutdown)}) { + const write = process.stdout.write; + process.stdout.write = function(chunk, ...args) { + try { const frame = JSON.parse(String(chunk)); if (frame.result?.remoteStopped === true) { frame.result.remoteStopped = false; chunk = JSON.stringify(frame) + '\\n'; } } catch {} + return write.call(this, chunk, ...args); + }; + } + const path = ${JSON.stringify(remoteStatePath)}, now = '2026-10-29T00:00:00Z'; + const read = () => fs.existsSync(path) ? JSON.parse(fs.readFileSync(path, 'utf8')) : { agentId: null, runs: [] }; + const write = state => fs.writeFileSync(path, JSON.stringify(state), { mode: 0o600 }); + const json = value => new Response(JSON.stringify(value), { headers: { 'content-type': 'application/json' } }); + const agent = state => ({ id: state.agentId, status: 'ACTIVE', env: { type: 'cloud' }, url: 'https://cursor.com/agents/' + state.agentId, createdAt: now, updatedAt: now, latestRunId: state.runs.at(-1).id }); + globalThis.fetch = async (input, init = {}) => { + const target = new URL(String(input)); assert.equal(target.origin, 'https://api.cursor.com'); + const method = init.method ?? 'GET', state = read(); + const body = init.body ? JSON.parse(String(init.body)) : null; + fs.appendFileSync(${JSON.stringify(fetchLog)}, JSON.stringify({ method, path: target.pathname, body, pid: process.pid }) + '\\n', { mode: 0o600 }); + if (method === 'POST' && (target.pathname === '/v1/agents' || target.pathname === '/v1/agents/' + state.agentId + '/runs')) { + if (target.pathname === '/v1/agents') { assert.equal(state.agentId, null); state.agentId = body.agentId; } + const run = { id: 'run-' + String(state.runs.length + 1).padStart(8, '0') + '-2222-4222-8222-222222222222', agentId: state.agentId, status: 'RUNNING', createdAt: now, updatedAt: now }; + state.runs.push(run); write(state); return json({ agent: agent(state), run }); + } + if (method === 'GET' && target.pathname === '/v1/agents/' + state.agentId) return json(agent(state)); + const run = state.runs.find(run => target.pathname.startsWith('/v1/agents/' + state.agentId + '/runs/' + run.id)); + assert.ok(run, 'request must bind the retained Agent and an exact Run'); + if (target.pathname.endsWith('/stream') && method === 'GET') return new Response(new ReadableStream({ start(controller) { + init.signal?.addEventListener('abort', () => { try { controller.close(); } catch {} }, { once: true }); + } }), { headers: { 'content-type': 'text/event-stream' } }); + if (target.pathname.endsWith('/cancel') && method === 'POST') { run.status = 'FINISHED'; write(state); return json({ id: run.id }); } + if (target.pathname.endsWith('/' + run.id) && method === 'GET') return json(run); + throw new Error('Unexpected controlled Cloud request'); + }; + })();\n`); + const builtProxy = await readFile(proxyPath); + const firstLine = builtProxy.indexOf(10) + 1; + await writeFile(proxyPath, Buffer.concat([builtProxy.subarray(0, firstLine), fixture, builtProxy.subarray(firstLine)]), { mode: 0o600 }); + await mkdir(runtime, { mode: 0o700 }); + const normalizedSessionId = "cloud-cold-session"; + const cursorCloud = { schema: "paperclip.cursor-cloud.config.v1" as const, repos: [{ url: "https://github.com/example/repo" }] }; + await writeFile(configPath, JSON.stringify({ ...cursorCloud, binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId } }), { mode: 0o600 }); + const identity = { runnerInstanceId: "runner-cloud-cold", environmentLeaseId: "lease-cloud-cold", runId: "00000000-0000-4000-8000-000000000771", normalizedSessionId, turnId: "turn-first", itemId: "item-first" }; + const nextIdentity = { ...identity, runId: "00000000-0000-4000-8000-000000000772", turnId: "turn-second", itemId: "item-second" }; + const tool = (name: string) => ({ name, description: name, inputSchema: { type: "object", properties: {}, additionalProperties: false } }); + const environment = (token: string, runId: string) => ({ PATH: process.env.PATH, CURSOR_API_KEY: "synthetic-key", + PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: join(runtime, "artifacts"), + PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: socketPath, PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: token, + PAPERCLIP_CURSOR_CLOUD_RELAY_URL: `https://relay.example.test/mcp/native-runs/${runId}`, PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 60_000) }); + const options = { provider: "cursor_cloud" as const, cursorCloud, stateDirectory, runnerBinary: defaultCapabilityRunnerdBinary(), providerNodeCommand, + cursorCloudProxyPath: proxyPath, cursorCloudProxySha256: `sha256:${createHash("sha256").update(await readFile(proxyPath)).digest("hex")}`, + lifecyclePolicy: { mode: "per_turn" as const } }; + const mcp = async (token: string, body: Record, sessionId?: string, priorScopeHeader?: string): Promise<{ status: number; sessionId?: string; value: any }> => { + const scopeHeader = priorScopeHeader ?? await currentCloudScopeHeader(runtime, normalizedSessionId); + return new Promise((accept, reject) => { + const req = request({ socketPath, path: "/mcp", method: "POST", headers: { Authorization: `Bearer ${token}`, [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: scopeHeader, "content-type": "application/json", ...(sessionId ? { "Mcp-Session-Id": sessionId } : {}) } }, response => { + let text = ""; response.on("data", chunk => { text += chunk; }); + response.on("end", () => { + try { accept({ status: response.statusCode!, sessionId: response.headers["mcp-session-id"] as string | undefined, value: text ? JSON.parse(text) : null }); } + catch (error) { reject(error); } + }); + }); + req.on("error", reject); req.end(JSON.stringify({ jsonrpc: "2.0", ...body })); + }); + }; + const first = createRunnerdCodexTransport({ ...options, prpIdentity: identity, environment: environment("token-first", identity.runId) }); + const bundles = [first]; + let secondAuthority: DurablePrpControlPlane | undefined; + try { + await first.transport.request("thread/start", { cwd: root, model: "pinned-model", baseInstructions: "FIRST instruction grant", dynamicTools: [tool("first_tool")] }); + await first.transport.request("turn/start", { input: [{ type: "text", text: "Ask before proceeding." }] }); + await vi.waitFor(async () => expect(JSON.parse(await readFile(remoteStatePath, "utf8")).runs).toHaveLength(1)); + const firstScopeHeader = await currentCloudScopeHeader(runtime, normalizedSessionId); + await first.transport.request("turn/interrupt", {}); + for await (const event of first.transport.notifications()) if (event.method === "turn/completed") break; + if (!validShutdown) { + await first.transport.close(); + const unconfirmed = JSON.parse(await readFile(join(stateDirectory, "runner", "codex-provider-state.json"), "utf8")); + expect(unconfirmed.lifecycle).not.toBe("prepared"); + expect(unconfirmed).not.toHaveProperty("providerTerminationReceipt"); + expect(first.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + return; + } + await first.transport.close(); + expect(first.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + const sameAuthority = createRunnerdCodexTransport({ ...options, prpIdentity: identity, + environment: environment("token-first", identity.runId), baseInstructions: "Must not replace same-authority instructions", + resumeProviderSession: { driverSessionId: normalizedSessionId, providerSessionId: normalizedSessionId } }); + bundles.push(sameAuthority); + await expect(sameAuthority.transport.request("thread/read", {})).resolves.toMatchObject({ thread: { id: normalizedSessionId } }); + expect(JSON.parse(await readFile(join(stateDirectory, "runner", "codex-provider-state.json"), "utf8")).config.instructions).toBe("FIRST instruction grant"); + const sameControl = JSON.parse(await readFile(join(stateDirectory, "control-plane", "control-plane-state.json"), "utf8")); + expect(sameControl.runAttachTemplate.provider.instructions).toBe("FIRST instruction grant"); + expect(sameControl.commands.some((command: { type: string }) => command.type === "run.attach")).toBe(false); + expect(JSON.parse(await readFile(remoteStatePath, "utf8")).runs).toHaveLength(1); + await sameAuthority.transport.close(); + expect(sameAuthority.evidence().runnerExited).toBe(true); + const priorRunnerBytes = await readFile(join(stateDirectory, "runner", "runner-state.json")); + const priorCoreBytes = await readFile(join(stateDirectory, "control-plane", "control-plane-state.json")); + const stopped = JSON.parse(await readFile(join(stateDirectory, "runner", "codex-provider-state.json"), "utf8")); + expect(stopped.lifecycle).toBe("prepared"); + expect(stopped.providerTerminationReceipt).toMatchObject({ remoteStopped: true }); + expect(JSON.parse(priorRunnerBytes.toString()).lifecycle).toBe("suspended"); + const checkpointName = (await readdir(runtime)).find(name => /^checkpoint-[a-f0-9]{64}\.json$/u.test(name))!; + const priorCheckpoint = JSON.parse(await readFile(join(runtime, checkpointName), "utf8")); + expect(priorCheckpoint).toMatchObject({ phase: "terminal", ownerRunId: identity.runId, pendingTerminalDelivery: null }); + const baselineRoot = join(root, "baseline"); + await cp(stateDirectory, baselineRoot, { recursive: true }); + const second = createRunnerdCodexTransport({ ...options, prpIdentity: nextIdentity, + environment: environment("token-second", nextIdentity.runId), baseInstructions: instructions, resumeDynamicTools: [tool("second_tool")], + controlPlaneRegistration: async core => { secondAuthority = core; await core.start(); return { release: () => undefined }; } }); + bundles.push(second); + const handler = vi.fn(async () => ({ success: true, contentItems: [{ type: "inputText", text: "current-tool-response" }] })); + second.transport.setServerRequestHandler(handler); + if (instructions === "") { + await expect(second.transport.request("thread/read", {})).rejects.toThrow("Cursor Cloud instructions are empty"); + expect((secondAuthority!.store.state.runAttachTemplate!.provider as Record).instructions).toBe(""); + expect(JSON.parse(await readFile(remoteStatePath, "utf8")).runs).toHaveLength(1); + return; + } + await expect(second.transport.request("thread/read", {})).resolves.toMatchObject({ thread: { id: normalizedSessionId } }); + expect(JSON.parse(await readFile(join(runtime, checkpointName), "utf8"))).toMatchObject({ ownerRunId: nextIdentity.runId, agentId: priorCheckpoint.agentId, runId: priorCheckpoint.runId }); + const archives = await readdir(join(stateDirectory, "authority-epochs")); + expect(archives).toHaveLength(1); + const archive = join(stateDirectory, "authority-epochs", archives[0]!); + expect(await readFile(join(archive, "runner-state.json"))).toEqual(priorRunnerBytes); + expect(await readFile(join(archive, "control-plane", "control-plane-state.json"))).toEqual(priorCoreBytes); + await second.transport.request("turn/start", { input: [{ type: "text", text: "Continue from the answer." }] }); + await vi.waitFor(async () => expect(JSON.parse(await readFile(remoteStatePath, "utf8")).runs).toHaveLength(2)); + const retired = await mcp("token-first", { id: 0, method: "initialize" }); + expect(retired.status).toBe(401); + expect((await mcp("token-second", { id: 0, method: "initialize" }, undefined, firstScopeHeader)).status).toBe(401); + const initialized = await mcp("token-second", { id: 0, method: "initialize" }); + const catalog = await mcp("token-second", { id: 1, method: "tools/list" }, initialized.sessionId); + expect(catalog.value.result.tools.map((entry: { name: string }) => entry.name)).toContain("second_tool"); + expect(catalog.value.result.tools.map((entry: { name: string }) => entry.name)).not.toContain("first_tool"); + const response = await mcp("token-second", { id: 2, method: "tools/call", params: { name: "second_tool", arguments: {} } }, initialized.sessionId); + expect(JSON.stringify(response.value)).toContain("current-tool-response"); + expect(handler).toHaveBeenCalledOnce(); + await second.transport.request("turn/interrupt", {}); + for await (const event of second.transport.notifications()) if (event.method === "turn/completed") break; + await second.transport.close(); + expect(second.evidence().runnerExited).toBe(true); + await expect(stat(socketPath)).rejects.toHaveProperty("code", "ENOENT"); + const calls = (await readFile(fetchLog, "utf8")).trim().split("\n").map(line => JSON.parse(line)); + const creates = calls.filter(call => call.method === "POST" && (call.path === "/v1/agents" || call.path.endsWith("/runs"))); + expect(creates).toHaveLength(2); + expect(creates[0].path).toBe("/v1/agents"); + expect(creates[1].path).toBe(`/v1/agents/${priorCheckpoint.agentId}/runs`); + expect(creates[1].pid).not.toBe(creates[0].pid); + expect(creates.map(call => call.body.model)).toEqual([{ id: "pinned-model" }, { id: "pinned-model" }]); + expect(creates[1].body.prompt.text).toContain(instructions); + expect((secondAuthority!.store.state.runAttachTemplate!.provider as Record).instructions).toBe(instructions); + expect(JSON.parse(await readFile(join(stateDirectory, "runner", "codex-provider-state.json"), "utf8")).config.instructions).toBe(instructions); + expect(creates[1].body.prompt.text).not.toContain("FIRST instruction grant"); + expect(creates[1].body.mcpServers).toEqual([{ name: "paperclip", type: "http", url: `https://relay.example.test/mcp/native-runs/${nextIdentity.runId}`, headers: { Authorization: "Bearer token-second", [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: await currentCloudScopeHeader(runtime, normalizedSessionId) } }]); + const remote = JSON.parse(await readFile(remoteStatePath, "utf8")); + expect(new Set(remote.runs.map((run: { id: string }) => run.id)).size).toBe(2); + expect(remote.runs.every((run: { status: string }) => run.status === "FINISHED")).toBe(true); + for (const mode of ["warm", "unsettled", "cross-binding", "external", "managed", "agentcore"] as const) { + const guardRoot = join(root, `guard-${mode}`); + await cp(baselineRoot, guardRoot, { recursive: true }); + if (mode === "warm") { + const state = JSON.parse(priorCoreBytes.toString()); state.warmTransition = {}; + await writeFile(join(guardRoot, "control-plane", "control-plane-state.json"), JSON.stringify(state)); + } + if (mode === "unsettled") { + const state = JSON.parse(priorRunnerBytes.toString()); state.lifecycle = "ready"; + await writeFile(join(guardRoot, "runner", "runner-state.json"), JSON.stringify(state)); + } + const guard = createRunnerdCodexTransport({ ...options, stateDirectory: guardRoot, + provider: mode === "managed" ? "claude_managed" : mode === "agentcore" ? "aws_agentcore" : "cursor_cloud", + prpIdentity: mode === "cross-binding" ? { ...nextIdentity, normalizedSessionId: "foreign-session" } : nextIdentity, + ...(mode === "external" ? { readRunnerState: async () => JSON.parse(priorRunnerBytes.toString()) } : {}), + environment: environment("token-second", nextIdentity.runId), baseInstructions: instructions }); + bundles.push(guard); + await expect(guard.transport.request("thread/read", {})).rejects.toThrow({ warm: "native_runner_warm_transition_requires_exact_owned_endpoint", unsettled: "native_runner_authority_rotation_requires_settled_state", "cross-binding": "PRP recovery identity does not match the durable session binding", external: "native_runner_prp_run_rotation_unavailable", managed: "native_runner_prp_run_rotation_unavailable", agentcore: "native_runner_prp_run_rotation_unavailable" }[mode]); + await guard.transport.close(); + } + } finally { + for (const bundle of bundles.reverse()) await bundle.transport.close().catch(() => undefined); + await secondAuthority?.stop(); + await rm(root, { recursive: true, force: true }); + } +} + +it.each([{ label: "revised", instructions: "SECOND instruction grant" }, { label: "empty grant rejected", instructions: "" }])("cold-rotates Cloud authority with the same native Agent and current run grants ($label)", async ({ instructions }) => { + await cloudColdAuthorityRotation(instructions); +}, 40_000); + +it("retains an unconfirmed Cloud shutdown without manufacturing cold readiness", async () => { + await cloudColdAuthorityRotation("Current instructions", false); +}, 30_000); diff --git a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.test.ts b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.test.ts index 1de51aca17a..5c4bb9d17ad 100644 --- a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.test.ts +++ b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.test.ts @@ -1600,6 +1600,41 @@ it("preserves an explicit OpenCode permission mode at the runner spawn boundary" expect(launches[0]!.environment.PAPERCLIP_OPENCODE_COMMAND).toBeUndefined(); }); +it.each([undefined, {}, { + CURSOR_API_KEY: "explicit-cloud-key", + PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: "/private/cloud/config.json", + PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT: "/private/cloud/artifacts", + PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: "/private/cloud/mcp.sock", + PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "explicit-cloud-relay", + PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp/native-runs/run", + PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: "2000000000000", + PAPERCLIP_CURSOR_CLOUD_UNRELATED: "must-not-cross", +}])("forwards only explicitly supplied Cloud launch bindings at the runner boundary (%j)", (environment: NodeJS.ProcessEnv | undefined) => { + const names = [ + "CURSOR_API_KEY", "PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH", "PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT", + "PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH", "PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN", + "PAPERCLIP_CURSOR_CLOUD_RELAY_URL", "PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT", + ] as const; + for (const name of names) vi.stubEnv(name, "ambient-must-not-cross"); + const launches: RunnerProcessLaunchSpec[] = []; + try { + spawnRunner({ + connection: { mode: "connect", connectUrl: "ws://127.0.0.1:43127" }, + stateDirectory: "/tmp/paperclip-runner-test", identity, ticket: "bootstrap-ticket", + maxOutboxBytes: 256 * 1024, p0ReserveBytes: 64 * 1024, + runnerVersion: expectedRunnerVersion, runnerDigest: expectedRunnerDigest, environment, + processLauncher: spec => { + launches.push(spec); + return { child: { pid: 42, exitCode: null, signalCode: null, kill: () => true }, + completion: Promise.resolve({ code: 0, signal: null, stdout: "", stderr: "" }) }; + }, + }); + expect(launches).toHaveLength(1); + for (const name of names) expect(launches[0]!.environment[name]).toBe(environment?.[name]); + expect(launches[0]!.environment.PAPERCLIP_CURSOR_CLOUD_UNRELATED).toBeUndefined(); + } finally { vi.unstubAllEnvs(); } +}); + it("preserves only bounded GitHub credential projection at the runner spawn boundary", () => { const launches: RunnerProcessLaunchSpec[] = []; spawnRunner({ diff --git a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts index f78c58fd57d..f0c727bac5b 100644 --- a/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts +++ b/packages/paperclip-runner/src/control-plane/durable-prp-control-plane.ts @@ -4151,6 +4151,12 @@ const runnerExplicitProviderEnvironmentKeys = [ "PAPERCLIP_OPENCODE_PERMISSION_MODE", "PAPERCLIP_OPENCODE_RUNTIME_DIR", "PAPERCLIP_OPENCODE_PERFORMANCE_DIAGNOSTICS", + "PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH", + "PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT", + "PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH", + "PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN", + "PAPERCLIP_CURSOR_CLOUD_RELAY_URL", + "PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT", "PAPERCLIP_RUNNER_INSTANCE_ID", "PAPERCLIP_RUN_ID", "PAPERCLIP_NORMALIZED_SESSION_ID", @@ -4248,6 +4254,9 @@ export function spawnRunner(options: { sidecarScript: string; sidecarScriptSha256: string; }; + cursorCloudLaunchProfile?: { + command: string; commandSha256: string; proxyScript: string; proxyScriptSha256: string; + }; opencodeLaunchProfile?: { command: string; commandSha256: string; @@ -4337,6 +4346,12 @@ export function spawnRunner(options: { ...(options.acpxLaunchProfile.candidateAdmission ? ["--acpx-candidate-admission-json", JSON.stringify(options.acpxLaunchProfile.candidateAdmission)] : []), ] : []), + ...(options.cursorCloudLaunchProfile ? [ + "--cursor-cloud-proxy-command", options.cursorCloudLaunchProfile.command, + "--cursor-cloud-proxy-command-sha256", options.cursorCloudLaunchProfile.commandSha256, + "--cursor-cloud-proxy-script", options.cursorCloudLaunchProfile.proxyScript, + "--cursor-cloud-proxy-script-sha256", options.cursorCloudLaunchProfile.proxyScriptSha256, + ] : []), ...(options.opencodeLaunchProfile ? [ "--opencode-proxy-command", @@ -4407,7 +4422,7 @@ export function spawnRunner(options: { maxOutboxBytes: options.maxOutboxBytes, p0ReserveBytes: options.p0ReserveBytes, maxRuntimeMs, maxLifetimeMs: lifetimeDeadline === undefined ? options.maxLifetimeMs : maxRuntimeMs, reconnectGraceMs: options.reconnectGraceMs, lifecyclePolicy: options.lifecyclePolicy, - acpxLaunchProfile: options.acpxLaunchProfile, opencodeLaunchProfile: options.opencodeLaunchProfile, + acpxLaunchProfile: options.acpxLaunchProfile, opencodeLaunchProfile: options.opencodeLaunchProfile, cursorCloudLaunchProfile: options.cursorCloudLaunchProfile, diagnosticsDirectory: options.diagnosticsDirectory, }, }), diff --git a/packages/paperclip-runner/src/drivers/acpx/antigravity-auth.test.ts b/packages/paperclip-runner/src/drivers/acpx/antigravity-auth.test.ts index af78eef13bb..9cac23eca93 100644 --- a/packages/paperclip-runner/src/drivers/acpx/antigravity-auth.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/antigravity-auth.test.ts @@ -33,6 +33,7 @@ const path = require('node:path'); const readline = require('node:readline'); const home = process.argv[2], mode = process.argv[3]; const requests = []; +let deferredAuthorization = ''; if(mode==='stubborn') { process.on('SIGTERM',()=>{}); const child=require('node:child_process').spawn(process.execPath,['-e',"process.on('SIGTERM',()=>{});setInterval(()=>{},1000)"],{stdio:'ignore'}); @@ -43,11 +44,13 @@ reader.on('line', line => { const request=JSON.parse(line); requests.push(request); fs.writeFileSync(path.join(home,'requests.json'),JSON.stringify(requests)); if(request.method==='initialize') { + if(mode==='early-url') { process.stderr.write('Open the following link to authenticate the ACP server: '+${JSON.stringify(authorizationUrl())}+'\\n'); return; } process.stdout.write(JSON.stringify({jsonrpc:'2.0',id:request.id,result:{protocolVersion:1,agentInfo:{name:'antigravity-acp',version:'1.4.3'},agentCapabilities:{_meta:{antigravity:{paperclipAdmission:1}}},authMethods:[{id:'oauth-personal'}]}})+'\\n'); } else if(request.method==='authenticate') { - const url = mode.startsWith('bad-url') ? 'https://example.invalid/steal' : ${JSON.stringify(authorizationUrl())}; + const url = mode.startsWith('bad-url')||mode==='late-bad-url' ? 'https://example.invalid/steal' : ${JSON.stringify(authorizationUrl())}; const message='Open the following link to authenticate the ACP server: '+url+'\\n'; - if (!mode.endsWith('url-after-result')) {process.stderr.write(message.slice(0,42));process.stderr.write(message.slice(42));} + if(['result-first','late-bad-url','late-duplicate-url'].includes(mode)||mode.endsWith('url-after-result')) deferredAuthorization=message+(mode==='late-duplicate-url'?message:''); + else {process.stderr.write(message.slice(0,42));process.stderr.write(message.slice(42));} if(mode==='blocked' || mode==='bad-url' || mode==='stubborn' || mode==='retained') return; if(mode==='error') {process.stdout.write(JSON.stringify({jsonrpc:'2.0',id:request.id,error:{code:-32000,message:'do not expose fixture-refresh-token'}})+'\\n');return;} fs.mkdirSync(path.join(home,'antigravity-acp'),{mode:0o700}); @@ -56,11 +59,9 @@ reader.on('line', line => { } else {throw new Error('inference/session request forbidden');} }); reader.on('close',()=> { - if (mode.endsWith('url-after-result')) { - const url = mode.startsWith('bad-url') ? 'https://example.invalid/steal' : ${JSON.stringify(authorizationUrl())}; - // EOF proves the client received the authenticate result before this stderr. - process.stderr.write('Open the following link to authenticate the ACP server: '+url+'\\n', () => process.exit(0)); - } else if(mode==='stubborn'||mode==='retained') setInterval(()=>{},1000); + // EOF proves the client received the authenticate result before this stderr. + if(deferredAuthorization) process.stderr.write(deferredAuthorization,()=>process.exit(0)); + else if(mode==='stubborn'||mode==='retained') setInterval(()=>{},1000); else process.exit(0); }); `); @@ -102,10 +103,11 @@ describe("Antigravity setup-only Google authentication", () => { // The login predicate keeps its five-second bound. Allow ten more seconds // for fixture startup and the durable mocked credential checks on a busy CI worker. - it.each(["success", "url-after-result"])("performs native authenticate, retires it, verifies identity, and preserves refresh rotation without repeated status network calls (%s)", async mode => { + it.each(["success", "result-first", "url-after-result"])("performs native authenticate, retires it, verifies identity, and preserves refresh rotation without repeated status network calls (%s)", async mode => { const home = await fixture(mode), fetch = googleIdentity(); vi.stubGlobal("fetch", fetch); const login = startAntigravityBrowserLogin(home); - await vi.waitFor(() => expect(login.outcome).toBe("success"), { timeout: 5_000 }); + await vi.waitFor(() => expect(login.outcome).toBeDefined(), { timeout: 5_000 }); + expect(login.outcome).toBe("success"); expect(login.authorizationUrl).toBe(authorizationUrl()); expect(JSON.parse(await readFile(join(home, "requests.json"), "utf8")).map((request: { method: string }) => request.method)).toEqual(["initialize", "authenticate"]); expect(setup.spawn.mock.calls[0]![1].env).toMatchObject({ GEMINI_HOME: home, AGY_ACP_FORCE_FILE_STORAGE: "1", BROWSER: "/usr/bin/true" }); @@ -125,13 +127,13 @@ describe("Antigravity setup-only Google authentication", () => { expect(fetch).toHaveBeenCalledTimes(6); }, 15_000); - it.each(["error", "bad-url", "bad-url-after-result"])("rejects %s without leaking provider text or calling Google", async mode => { + it.each(["error", "bad-url", "early-url", "late-bad-url", "late-duplicate-url", "bad-url-after-result"])("rejects %s without leaking provider text or calling Google", async mode => { const home = await fixture(mode), fetch = vi.fn(); vi.stubGlobal("fetch", fetch); const login = startAntigravityBrowserLogin(home); await vi.waitFor(() => expect(login.outcome).toBe("failure"), { timeout: 5_000 }); await vi.waitFor(() => expect(setup.close).toHaveBeenCalledOnce(), { timeout: 5_000 }); expect(login.error).not.toContain("fixture"); - if (mode.startsWith("bad-url")) expect(login.authorizationUrl).toBeUndefined(); + if (mode.startsWith("bad-url") || ["early-url", "late-bad-url"].includes(mode)) expect(login.authorizationUrl).toBeUndefined(); expect(fetch).not.toHaveBeenCalled(); }); diff --git a/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts b/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts index 59cc2db416a..16a237b15d3 100644 --- a/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/copilot-installation.test.ts @@ -33,6 +33,652 @@ describe("Copilot build-owned installation", () => { await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, agentProfileVersion: prior } as never)).rejects.toThrow("exact pinned"); } }); + it("preserves profile 89 while binding generated contract fields in profile 90", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("9990fd9cdd23df111a180984160a11db7a2f972a60787e8ddea9793678cc268e"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeRuntimeContextFieldsSourceSha256", "nativeRuntimeContextSourceSha256", "permissionClassifierSourceSha256", "profileCompatibilitySourceSha256", "semanticSidecarSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 89)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 89, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves profile 88 while binding run attachment activity in profile 89", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("6010dc772d914afec7dd31f35f953ce74b65ab3a648ce54aaee559f908b492f9"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "harnessSessionSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "runtimeRequestFacadeSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 88)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 88, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves profile 87 while binding merged operation timing in profile 88", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("ce9912c34ae9126e74061f7bc170b59589af7cb6ab26751e250da9e9dd9553c9"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "semanticSidecarSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 87)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 87, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves profile 86 while binding rejected native completion in profile 87", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v86-cursor-cloud-qualification-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("118a4b0a782b56570e5530cca91255da8932c31f827c319b40a5810bd4d446e9"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeSessionRuntimeSourceSha256", "profileCompatibilitySourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 86)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 86, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves published v65 while binding retained-maintenance waits in v66", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v65-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("ca1d95c21b3f49c99b6d7c6bd3c2bf149715db3263927ad653cc0c6f33fb4462"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v66-sleep-maintenance-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 65)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 65, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves the historical sleep-maintenance v64 identity", async () => { + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v64-sleep-maintenance-historical-identity.json", import.meta.url), "utf8")); + for (const [name, checksum, changed] of [ + ["copilot-profile-v63-identity.json", "4adb05bd642f0222a3bcc85cfefbeb2988de439f58125012e1c575caedd90798", ["agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256"]], + ["copilot-profile-v62-sleep-maintenance-historical-identity.json", "e0c93dd7210fbb0115e09b70887ec4ae40621fc5314bd1625e586caf2163c94e", ["agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "semanticCompletionContractSourceSha256", "semanticContinuationSourceSha256"]], + ] as const) { + const bytes = readFileSync(new URL(`../../../test/fixtures/${name}`, import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe(checksum); + const prior = JSON.parse(bytes.toString("utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(changed); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + const sorted = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(prior.commandDigest); + expect(isSupportedAcpxProfileVersion("copilot", prior.declaration.agentProfileVersion)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: prior.declaration.agentProfileVersion, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + } + }); + + it("preserves profile 78 while binding retained-session waits in profile 79", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v78-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("da2d7d33dbcdb900f3afb0ad0d0d1502c31f7638772a58009a3300f7e442fd1c"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v79-sleep-maintenance-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 78)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 78, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + + it("preserves published profile 79 while binding retained cleanup in profile 80", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v79-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("92fb6b5f1a312933f78d650fdc037ded4876d112c472fcfd5c1116cdbb0dae44"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v80-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 79)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 79, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("retains the published profile 75 fixture while advancing the event contract", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v75-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("4178dad6cf43a6026c85f45a0606f30c72570549d517e49f705dbf8f9f41650b"); + expect(isSupportedAcpxProfileVersion("copilot", 75)).toBe(true); + const prior = JSON.parse(bytes.toString("utf8")); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 75, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v70 while binding historical Grok recovery decoding in v71", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v70-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("7ab63e2832f9d9c3273b5f799b25a02cba18718e956966c3b79052d74b4bd304"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v71-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()) + .toEqual(["agentProfileVersion", "profileCompatibilitySourceSha256"]); + expect(isSupportedAcpxProfileVersion("copilot", 70)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 70, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v69 while binding closed startup diagnostics in v70", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v69-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("a878caa5f40cfad517e852384507b50c1098e219f1dd6822335b1119b03eaea5"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v70-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "admissionDiagnosticsSourceSha256", "agentProfileVersion", "grokAdmissionSourceSha256", + "profileCompatibilitySourceSha256", "runtimeHostSourceSha256", "sidecarErrorSourceSha256", + ]); + for (const [name, field] of [["admission-diagnostics.ts", "admissionDiagnosticsSourceSha256"], ["grok-effort.ts", "grokAdmissionSourceSha256"]]) { + expect(current.declaration[field]).toBe(createHash("sha256").update(readFileSync(new URL(name!, import.meta.url))).digest("hex")); + } + expect(isSupportedAcpxProfileVersion("copilot", 69)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 69, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves published and candidate history while binding native Grok admission in v69", async () => { + const published = readFileSync(new URL("../../../test/fixtures/copilot-profile-v68-identity.json", import.meta.url)); + const candidate = readFileSync(new URL("../../../test/fixtures/copilot-profile-v67-grok-native-effort-candidate-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(published).digest("hex")).toBe("9692e8de4e75682c74f8e635e26b8de1f03f1d3e41966dafbb7314d35b75c3cf"); + expect(createHash("sha256").update(candidate).digest("hex")).toBe("0a20ffe33c92d86f58013582b19c2371f96d93e7e4e0e8096fbf0e7236bd02f4"); + const prior = JSON.parse(published.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v69-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeAdapterSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + for (const history of [prior, JSON.parse(candidate.toString("utf8"))]) { + expect(isSupportedAcpxProfileVersion("copilot", history.declaration.agentProfileVersion)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: history.declaration.agentProfileVersion, commandDigest: history.commandDigest })).rejects.toThrow("exact pinned"); + } + }); + + it("preserves both lineages while binding the merged implementation in v68", async () => { + const published = readFileSync(new URL("../../../test/fixtures/copilot-profile-v66-identity.json", import.meta.url)); + const candidate = readFileSync(new URL("../../../test/fixtures/copilot-profile-v67-identity.json", import.meta.url)); + expect(createHash("sha256").update(published).digest("hex")).toBe("9eb0bfd31334210fd41ddb677a165ef7432a2951922e642dddff087e4db8b6bc"); + expect(createHash("sha256").update(candidate).digest("hex")).toBe("6c818541933b97bea896ca29179ad54c887db9b7d563021da1676a8126f960dd"); + const prior = JSON.parse(published.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v68-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "providerLaunchSourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + for (const history of [prior, JSON.parse(candidate.toString("utf8"))]) { + expect(isSupportedAcpxProfileVersion("copilot", history.declaration.agentProfileVersion)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: history.declaration.agentProfileVersion, commandDigest: history.commandDigest })).rejects.toThrow("exact pinned"); + } + }); + + it("preserves published v65 while binding hot-upgrade adoption in v67", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v65-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("ca1d95c21b3f49c99b6d7c6bd3c2bf149715db3263927ad653cc0c6f33fb4462"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v67-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "providerLaunchSourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 65)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 65, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("retains candidate v66 identity when completion recovery changes in v67", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v66-hot-upgrade-candidate-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("430f7a3bb4f51a22d6f18a515fb32eb4defa5bab60a6a4901f6750e59f2536c6"); + const prior = JSON.parse(bytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v67-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 66)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 66, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("retains the hot-upgrade v59 development identity without replacing published history", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v59-hot-upgrade-candidate-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("b61fe644383acbbaacd209836878243cb96b143807d90c521ef1fbee2a2fcb0c"); + const prior = JSON.parse(bytes.toString("utf8")); + const sorted = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(prior.commandDigest); + expect(isSupportedAcpxProfileVersion("copilot", 59)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 59, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("retains v65 history while binding the shared native Grok effort transport in v66", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v65-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v66-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "harnessSessionContractSourceSha256", "nativeBackendSourceSha256", "nativeExecutionSourceSha256", + "nativeInstructionsSourceSha256", "profileCompatibilitySourceSha256", "providerLaunchSourceSha256", "runtimeAdapterSourceSha256", + "runtimeHostSourceSha256", "runtimeRequestBridgeSourceSha256", "runtimeSandboxSourceSha256", "semanticDirectDriverSourceSha256", "semanticSchemaBundleSourceSha256", + "semanticSidecarProtocolSourceSha256", "semanticSidecarSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 65)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 65, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves published v64 while binding exhausted reconnect cancellation in v65", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v64-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("9ee015b4968d8df8d38364626d413f69f6c0e846de20fe1d5f72c7f1706837a9"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v65-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 64)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 64, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves the published startup cancellation candidate as historical v63 evidence", async () => { + const bytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v63-reconnect-candidate-historical-identity.json", import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe("1ed0ac81863a588f3a2ff997b0e3f3bf0b64440454eb19282bdcd05d35650207"); + const candidate = JSON.parse(bytes.toString("utf8")); + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v62-identity.json", import.meta.url), "utf8")); + expect(Object.keys(candidate.declaration).filter(key => candidate.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + const sorted = Object.fromEntries(Object.entries(candidate.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(candidate.commandDigest); + expect(isSupportedAcpxProfileVersion("copilot", 63)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 63, commandDigest: candidate.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves published v63 while binding delegated connection guidance in v64", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v63-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("4adb05bd642f0222a3bcc85cfefbeb2988de439f58125012e1c575caedd90798"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v64-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:1412842a36a7211d84b6b98a3d1f69e3388bc4814e5825da890a774ae0e3460e"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeRuntimePromptsSourceSha256", "profileCompatibilitySourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 63)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 63, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves both published v62 identities while binding their merged source in v63", async () => { + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v63-identity.json", import.meta.url), "utf8")); + for (const [name, checksum, changed] of [ + ["copilot-profile-v62-identity.json", "faa4d1b35267b54e134a8e0c84586fe1196d8fad5525cb53aa195aae53ca6e83", ["agentProfileVersion", "profileCompatibilitySourceSha256", "semanticCompletionContractSourceSha256", "semanticContinuationSourceSha256"]], + ["copilot-profile-v62-candidate-historical-identity.json", "da3f44a3cfda31cbff558d618e1e9cb1cfb80379b613ff1266e8b866ea666df8", ["agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256"]], + ] as const) { + const bytes = readFileSync(new URL(`../../../test/fixtures/${name}`, import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe(checksum); + const prior = JSON.parse(bytes.toString("utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(changed); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + const sorted = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(prior.commandDigest); + expect(isSupportedAcpxProfileVersion("copilot", 62)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 62, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + } + }); + + it("preserves v61 while binding uncertain process checks and controller retirement in v62", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v61-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("ec3c8561bc123a599a01da356978b73e6d48ab030842af9f0d63d1f30413e1a5"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v62-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:956276ebee59f880249fa6955adc224af9ca7b6a9da59bcc5da4a8667550c5b3"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 61)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 61, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v60 while binding controller journal retirement in v61", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v60-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("e3c45b0311517d05f06ed10f357db713ae157cfa87e4a8becf087c5b6dfa7003"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v61-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 60)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 60, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v59 while binding the Codex-only hosted search restriction in v60", async () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v59-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("a9116d0981cb0feebec31f61cd23d16b3a263fe6a797b1ba1436c6e41198538c"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v60-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeBackendSourceSha256", "nativeExecutionSourceSha256", "profileCompatibilitySourceSha256", "providerLaunchSourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 59)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 59, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v58 while binding the separate remote process reconnect policy in v59", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v58-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v59-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "credentialBindingSourceSha256", "nativeInstructionsSourceSha256", "nativeSessionRuntimeSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "semanticBridgeSourceSha256", "semanticSidecarSourceSha256", "transportContractSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 58)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v57 while binding the shared Pi setup and launch repairs in v58", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v57-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v58-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "guardedInstallationSourceSha256", "nativeBackendSourceSha256", "profileCompatibilitySourceSha256", "profileInstallationSourceSha256", "providerLaunchSourceSha256", "runtimeHostSourceSha256", "runtimeRequestBridgeSourceSha256", "semanticBridgeSourceSha256", "semanticSidecarSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 57)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v56 while binding the extracted core prompts in v57", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v56-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v57-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeRuntimeContextSourceSha256", "nativeRuntimePromptsSourceSha256", "profileCompatibilitySourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 56)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v55 while binding reusable case workflow guidance in v56", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v55-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v56-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeRuntimeContextSourceSha256", "profileCompatibilitySourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 55)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v54 while binding current workspace continuation revalidation in v55", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v54-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v55-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:171d865b9b6ff2eda3926dc957caf2993cd7e1fa1b4359e8b60b83f589bd67fa"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", + "semanticCompletionContractSourceSha256", "semanticContinuationSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 54)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v53 while binding repository setup completion guidance in v54", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v53-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v54-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:6441ff7f3fc664064bff9e7ae80252ddec7a39236f9a4b9d402785eb8b03b2c9"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "semanticCompletionContractSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 53)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v52 while binding the workspace continuation source in v53", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v52-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v53-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:3614db52d3ddcbc0153c79361a0db2c4324249475d3be490f152b64f916bdd53"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "semanticContinuationSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 52)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v51 when the setup transport contract changes", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v51-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:8c1cddce201eb0e3f2792cc5a8c79edf36b0ce823e728255c1897f95c74a3866"); + expect(isSupportedAcpxProfileVersion("copilot", 51)).toBe(true); + expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v49 while binding the extracted provider launch builder", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v49-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v50-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:37a8f6a540a7417bb12becbf283158df8cca925c5136ecc0db14597441fff702"); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "profileCompatibilitySourceSha256", "providerLaunchSourceSha256", "runtimeRequestBridgeSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 49)).toBe(true); + }); + + it("preserves qualified v48 while binding completion-proposal recovery in v49", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v48-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v49-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:49171cb881c43270e101a790a109752642870daedc38cd6e91aef08fd7aab038"); + const sortedPrior = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sortedPrior)).digest("hex")}`).toBe(prior.commandDigest); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeSessionRuntimeSourceSha256", "profileCompatibilitySourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 48)).toBe(true); + vi.mocked(verifyNativeAcpxInstallation).mockClear(); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 48, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled(); + }); + + it("preserves qualified v47 while binding the additive case contracts in v48", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v47-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v48-identity.json", import.meta.url), "utf8")); + expect(prior.commandDigest).toBe("sha256:55044aa235e88b3fe36ec8a556ee1e3382590870aab907e4462ef7d64af49cea"); + const sortedPrior = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sortedPrior)).digest("hex")}`).toBe(prior.commandDigest); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeRuntimeContextSourceSha256", "profileCompatibilitySourceSha256", + "semanticCompletionContractSourceSha256", "semanticSchemaBundleSourceSha256", "semanticValidatorsSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 47)).toBe(true); + vi.mocked(verifyNativeAcpxInstallation).mockClear(); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 47, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled(); + }); + + it("preserves v12 history and changes only the version and four shared source bindings", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v12-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v13-identity.json", import.meta.url), "utf8")); + const changed = Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort(); + expect(changed).toEqual(["agentProfileVersion", "semanticDirectDriverSourceSha256", "semanticSchemaBundleSourceSha256", "semanticSidecarProtocolSourceSha256", "semanticSidecarSourceSha256"]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(prior.declaration.agentProfileVersion).toBe(12); + expect(current.declaration.agentProfileVersion).toBe(13); + const sortedPrior = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sortedPrior)).digest("hex")}`).toBe(prior.commandDigest); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v13 history while binding the shared live request snapshot", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v13-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v14-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(["agentProfileVersion", "semanticSidecarSourceSha256"]); + }); + + it("preserves v14 history while binding the corrected outbound ACPX delivery", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v14-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v15-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(["acpxPatchSha256", "agentProfileVersion"]); + }); + + it("preserves v17 history while binding the shared Grok descriptor schema", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v17-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v18-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(["agentProfileVersion", "semanticSchemaBundleSourceSha256"]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves the historical Muse v18 declaration without granting current launch", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v17-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v18-muse-historical-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "semanticSchemaBundleSourceSha256", "semanticValidatorsSourceSha256", + ]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(prior.declaration.agentProfileVersion).toBe(17); + const sortedPrior = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sortedPrior)).digest("hex")}`).toBe(prior.commandDigest); + expect(current.commandDigest).not.toBe(prior.commandDigest); + vi.mocked(verifyNativeAcpxInstallation).mockClear(); + for (const override of [ + { commandDigest: prior.commandDigest }, + { agentProfileVersion: prior.declaration.agentProfileVersion }, + { commandDigest: prior.commandDigest, agentProfileVersion: prior.declaration.agentProfileVersion }, + ]) { + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, ...override })).rejects.toThrow("exact pinned"); + } + expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled(); + }); + + it("preserves the historical combined external-provider v19 declaration without granting current launch", async () => { + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v19-muse-historical-identity.json", import.meta.url), "utf8")); + expect(current.declaration.agentProfileVersion).toBe(19); + expect(isSupportedAcpxProfileVersion("copilot", 18)).toBe(true); + vi.mocked(verifyNativeAcpxInstallation).mockClear(); + for (const [name, changed] of [ + ["copilot-profile-v18-identity.json", ["agentProfileVersion", "semanticSchemaBundleSourceSha256", "semanticValidatorsSourceSha256"]], + ["copilot-profile-v18-muse-historical-identity.json", ["agentProfileVersion", "semanticSchemaBundleSourceSha256"]], + ] as const) { + const prior = JSON.parse(readFileSync(new URL(`../../../test/fixtures/${name}`, import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(changed); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(current.commandDigest).not.toBe(prior.commandDigest); + for (const override of [ + { commandDigest: prior.commandDigest }, + { agentProfileVersion: prior.declaration.agentProfileVersion }, + { commandDigest: prior.commandDigest, agentProfileVersion: prior.declaration.agentProfileVersion }, + ]) { + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, ...override })).rejects.toThrow("exact pinned"); + } + } + expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled(); + }); + + it("preserves v18 history while binding the credential update protocol sources", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v18-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v19-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()) + .toEqual(["agentProfileVersion", "semanticSchemaBundleSourceSha256", "semanticValidationSourceSha256", "semanticValidatorsSourceSha256"]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + it("binds both immutable v19 histories in a new combined v20 declaration", async () => { + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v20-identity.json", import.meta.url), "utf8")); + expect(current.declaration.agentProfileVersion).toBe(20); + expect(isSupportedAcpxProfileVersion("copilot", 19)).toBe(true); + vi.mocked(verifyNativeAcpxInstallation).mockClear(); + for (const [name, changed] of [ + ["copilot-profile-v19-identity.json", ["agentProfileVersion", "semanticSchemaBundleSourceSha256", "semanticValidatorsSourceSha256"]], + ["copilot-profile-v19-muse-historical-identity.json", ["agentProfileVersion", "semanticSchemaBundleSourceSha256", "semanticValidationSourceSha256", "semanticValidatorsSourceSha256"]], + ] as const) { + const prior = JSON.parse(readFileSync(new URL(`../../../test/fixtures/${name}`, import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual(changed); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + const sortedPrior = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sortedPrior)).digest("hex")}`).toBe(prior.commandDigest); + expect(current.commandDigest).not.toBe(prior.commandDigest); + for (const override of [ + { commandDigest: prior.commandDigest }, + { agentProfileVersion: prior.declaration.agentProfileVersion }, + { commandDigest: prior.commandDigest, agentProfileVersion: prior.declaration.agentProfileVersion }, + ]) { + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, ...override })).rejects.toThrow("exact pinned"); + } + } + expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled(); + }); + + it("preserves v20 history while binding the controller-owned monitor continuation", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v20-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v21-mainline-monitor-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "semanticCompletionContractSourceSha256", "semanticContinuationSourceSha256", "semanticDirectDriverSourceSha256", "semanticSidecarSourceSha256", + ]); + expect(Object.keys(current.declaration).filter(key => !Object.hasOwn(prior.declaration, key))).toEqual(["semanticContinuationSourceSha256"]); + expect(Object.keys(prior.declaration).every(key => Object.hasOwn(current.declaration, key))).toBe(true); + expect(isSupportedAcpxProfileVersion("copilot", 20)).toBe(true); + const sorted = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(prior.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 20, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v22 history while binding the Claude-only preload metadata branch", async () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-mainline-v22-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-mainline-v23-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()) + .toEqual(["agentProfileVersion", "semanticBridgeSourceSha256"]); + expect(Object.keys(current.declaration).sort()).toEqual(Object.keys(prior.declaration).sort()); + expect(isSupportedAcpxProfileVersion("copilot", 22)).toBe(true); + const sorted = Object.fromEntries(Object.entries(prior.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(prior.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: 22, commandDigest: prior.commandDigest })).rejects.toThrow("exact pinned"); + }); + + it("preserves v23 history while binding shared observability diagnostic redaction", () => { + const prior = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-mainline-v23-identity.json", import.meta.url), "utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-mainline-v24-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "semanticSidecarSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 23)).toBe(true); + expect(current.commandDigest).not.toBe(prior.commandDigest); + }); + + it("preserves v85 while binding runtime activity delivery in v86", () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v85-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("15d2790d94d7cc46ac728119ed9b4d07ed2b682be039b3debc716600708d8c1a"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v86-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "nativeSessionRuntimeSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "runtimeRequestFacadeSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 85)).toBe(true); + }); + + it("preserves v86 while binding activity attachment settlement in v87", () => { + const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v86-identity.json", import.meta.url)); + expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("6baeb98adc7132b2afdce8b1d2da1df2f00356677eb4497c49c05aa9def79138"); + const prior = JSON.parse(priorBytes.toString("utf8")); + const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v87-identity.json", import.meta.url), "utf8")); + expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([ + "agentProfileVersion", "harnessSessionSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestFacadeSourceSha256", + ]); + expect(isSupportedAcpxProfileVersion("copilot", 86)).toBe(true); + }); + it("pins the unchanged executable plus complete patched distribution on every target platform", () => { const fixture = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-message-identity-distributions-1.0.88.json", import.meta.url), "utf8")); const script = readFileSync(new URL("../../../scripts/materialize-copilot-binary.mjs", import.meta.url), "utf8"); diff --git a/packages/paperclip-runner/src/drivers/acpx/cursor-cloud-candidate-profiles.test.ts b/packages/paperclip-runner/src/drivers/acpx/cursor-cloud-candidate-profiles.test.ts new file mode 100644 index 00000000000..6dbcb636111 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/acpx/cursor-cloud-candidate-profiles.test.ts @@ -0,0 +1,148 @@ +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; +import { QUALIFIED_ACPX_PROFILES } from "./qualified-profiles.js"; +import { verifyCopilotInstallation } from "./copilot-installation.js"; +import { isSupportedAcpxProfileVersion } from "./profile-compatibility.js"; + +const bytes = (name: string) => readFileSync(new URL(`../../../test/fixtures/${name}`, import.meta.url)); + +describe("published identities after the Cursor Cloud qualification merge", () => { + it.each([ + [ + "copilot-profile-v72-identity.json", + "8d10c689a1707e06a5bfc93b37509b9f0b203586ee58c26cb780ab7057081fe7" + ], + [ + "copilot-profile-v73-identity.json", + "ca8256cf778983db0561a0093879c334ae225cc88b75cc25b42459c69e04223f" + ], + [ + "copilot-profile-v74-identity.json", + "2bfb5dc2f7ddac6dcd9229f155706c0f85da55e946e8c1ab60babced3e94201c" + ], + [ + "copilot-profile-v81-identity.json", + "8b9d6b0e7ba3bb34141275f1a62701c3b69e1e917260d3c9984fbaeba6d413b1" + ], + [ + "grok-profile-v8-identity.json", + "164c4e5bf1cd9696c5935fb0010348e575f05c421b4af5496799a7878735bfd9" + ], + [ + "grok-profile-v12-identity.json", + "f43ac83f80fde04d8f184529502d3efc0df1b870d0ac8f863a183ae48eb6b004" + ] +] as const)("keeps published %s byte-identical", (name, checksum) => { + expect(createHash("sha256").update(bytes(name)).digest("hex")).toBe(checksum); + }); +}); + +describe("branch-only Cursor Cloud identities from 157d4119db48eff9de040d3951755e58dcbd1f0a", () => { + it.each([ + [ + "copilot-profile-v72-cursor-cloud-candidate-historical-identity.json", + "e119e6206f4450e7d6b79b4a1522215f9848419dbc0b46cae877d7a5ae600b69" + ], + [ + "copilot-profile-v73-cursor-cloud-candidate-historical-identity.json", + "7e6d7841267f1cbc4117ab9a3cea7c1fb0ffe043b63ff640e3aa97859bd4ebb6" + ], + [ + "copilot-profile-v74-cursor-cloud-candidate-historical-identity.json", + "d3868e9fc601e3efb85e1c6da651d920e4f08efd572075ed29e4bbfd9c3d223b" + ], + [ + "grok-profile-v8-cursor-cloud-candidate-historical-identity.json", + "be0f07888a618794a2fe42e8894f42e2ac02d2c2c6a361560ae3d2b829b4c706" + ] +] as const)("retains %s as qualification history", async (name, checksum) => { + const retained = bytes(name); + expect(createHash("sha256").update(retained).digest("hex")).toBe(checksum); + const identity = JSON.parse(retained.toString("utf8")); + const agent = name.startsWith("copilot") ? "copilot" : "grok"; + expect(isSupportedAcpxProfileVersion(agent, identity.declaration.agentProfileVersion)).toBe(true); + expect(identity.commandDigest).not.toBe(QUALIFIED_ACPX_PROFILES[agent].commandDigest); + if (agent === "copilot") { + const sorted = Object.fromEntries(Object.entries(identity.declaration).sort(([a], [b]) => a.localeCompare(b))); + expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(identity.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: identity.declaration.agentProfileVersion, commandDigest: identity.commandDigest })).rejects.toThrow("exact pinned"); + } + }); +}); + + +describe("retained Cursor Cloud core profile before semantic planning", () => { + it("keeps version 82 byte-identical and decodable without admitting its old launch identity", async () => { + const retained = bytes("copilot-profile-v82-cursor-cloud-candidate-historical-identity.json"); + expect(createHash("sha256").update(retained).digest("hex")).toBe("350564aceac59083b3009c5915c709549f0a257b0d828314184c28cded33e6a6"); + const identity = JSON.parse(retained.toString("utf8")); + expect(isSupportedAcpxProfileVersion("copilot", 82)).toBe(true); + expect(identity.commandDigest).not.toBe(QUALIFIED_ACPX_PROFILES.copilot.commandDigest); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, agentProfileVersion: 82, commandDigest: identity.commandDigest })).rejects.toThrow("exact pinned"); + }); +}); + + +describe("published identities from pinned master 54cc522e864291564bc37ddc6004bfa558c02644", () => { + it.each([ + [ + "copilot-profile-v82-identity.json", + "fe04407493a608d4204403d04ef06c79904a206f3c57547a11612c068a55b99f" + ], + [ + "copilot-profile-v83-identity.json", + "31d024e3870f8a7278939f6f1186e2ec6d2bc331d7a89213aceae88c04b40654" + ], + [ + "copilot-profile-v84-identity.json", + "6fe83e309911eb83f8b6e817f0b535329b02fab41ef7749d363f4562af19d4fe" + ], + [ + "grok-profile-v13-identity.json", + "374993b170ea181470f6bc606ec568eb347f987e65338d8b980356d97c97b98b" + ] +] as const)("preserves published %s byte-identical", (name, checksum) => { + expect(createHash("sha256").update(bytes(name)).digest("hex")).toBe(checksum); + }); +}); + +describe("qualified branch-only identities from 0d968b005be9063b8c3806ecef5f75239dc5ce5b", () => { + it.each([ + [ + "copilot-profile-v82-cursor-cloud-candidate-historical-identity.json", + "350564aceac59083b3009c5915c709549f0a257b0d828314184c28cded33e6a6" + ], + [ + "copilot-profile-v83-cursor-cloud-candidate-historical-identity.json", + "9b4fa60409fc8e0f85ec61ed6378188ccaeb806684aea3b05ae6cd0c451bb364" + ], + [ + "grok-profile-v13-cursor-cloud-candidate-historical-identity.json", + "2db8e1be2c019e88cf089c2ae344c48d5e67c67b2ff72b2e3a21ff9657306261" + ] +] as const)("retains %s as read-only qualification history", async (name, checksum) => { + const retained = bytes(name); + expect(createHash("sha256").update(retained).digest("hex")).toBe(checksum); + const identity = JSON.parse(retained.toString("utf8")); + const agent = name.startsWith("copilot") ? "copilot" : "grok"; + expect(isSupportedAcpxProfileVersion(agent, identity.declaration.agentProfileVersion)).toBe(true); + expect(identity.commandDigest).not.toBe(QUALIFIED_ACPX_PROFILES[agent].commandDigest); + if (agent === "copilot") { + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, + agentProfileVersion: identity.declaration.agentProfileVersion, commandDigest: identity.commandDigest })).rejects.toThrow("exact pinned"); + } + }); +}); + + +describe("published Core041 profile history", () => { + it("retains v85 bytes without admitting its stale shared bridge", async () => { + const retained = bytes("copilot-profile-v85-cursor-cloud-qualification-historical-identity.json"); + expect(createHash("sha256").update(retained).digest("hex")).toBe("977d68b327f3964e8337ef8ba00230eb1b1697017db21f8010f664fee3d3c70a"); + const identity = JSON.parse(retained.toString("utf8")); + expect(isSupportedAcpxProfileVersion("copilot", 85)).toBe(true); + await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, agentProfileVersion: 85, commandDigest: identity.commandDigest })).rejects.toThrow("exact pinned"); + }); +}); diff --git a/packages/paperclip-runner/src/drivers/acpx/profile-compatibility.test.ts b/packages/paperclip-runner/src/drivers/acpx/profile-compatibility.test.ts index f32056e5e62..b2edd4c6367 100644 --- a/packages/paperclip-runner/src/drivers/acpx/profile-compatibility.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/profile-compatibility.test.ts @@ -1,3 +1,5 @@ +import { readdirSync, readFileSync } from "node:fs"; +import { createHash } from "node:crypto"; import { describe, expect, it } from "vitest"; import { QUALIFIED_ACPX_PROFILE_DATA } from "./generated-profiles.js"; import { isSupportedAcpxProfileVersion } from "./profile-compatibility.js"; @@ -23,6 +25,75 @@ describe("ACPX profile versions", () => { }); describe("historical ACPX profile decoding", () => { + it("keeps both reconciled historical lineages immutable and decode-only", () => { + const lineage = JSON.parse(readFileSync(new URL("../../../test/fixtures/profile-history-lineage.json", import.meta.url), "utf8")) as { + schema: string; historicalDecodeOnly: boolean; executionRequiresExactCurrentProfile: boolean; + records: Array<{ path: string; originRevision: string; sha256: string; agent: keyof typeof QUALIFIED_ACPX_PROFILE_DATA; + version: number; commandDigest: string; launchAuthority: boolean }>; + }; + expect(lineage.schema).toBe("paperclip.acpx-profile-history-lineage.v1"); + expect(lineage.historicalDecodeOnly).toBe(true); + expect(lineage.executionRequiresExactCurrentProfile).toBe(true); + const reconciled = lineage.records.filter(record => [ + "42e9d3d710a2ef5b387f9bb29bf615973b4adba9", "59da15066acd2077b1161b06217acfbd11f8da04", + ].includes(record.originRevision)); + expect(reconciled).toHaveLength(6); + const paths = new Set(); + for (const record of reconciled) { + expect(paths.has(record.path), record.path).toBe(false); + paths.add(record.path); + expect(record.originRevision, record.path).toMatch(/^[a-f0-9]{40}$/u); + expect(record.launchAuthority, record.path).toBe(false); + const bytes = readFileSync(new URL(`../../../../../${record.path}`, import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex"), record.path).toBe(record.sha256); + const identity = JSON.parse(bytes.toString("utf8")); + expect(identity.declaration.agent, record.path).toBe(record.agent); + expect(identity.declaration.agentProfileVersion, record.path).toBe(record.version); + expect(identity.commandDigest, record.path).toBe(record.commandDigest); + expect(isSupportedAcpxProfileVersion(record.agent, record.version), record.path).toBe(true); + expect(identity.commandDigest, record.path).not.toBe(QUALIFIED_ACPX_PROFILE_DATA[record.agent].commandDigest); + } + }); + + it.each([ + ["copilot", "copilot-profile-v88-identity.json", "81e5fbccf057c04e012f638dc7a02c5758bf6ca67f7c4ed0045f3f61525401c2", "published cd5"], + ["copilot", "copilot-profile-v88-cursor-cloud-qualification-historical-identity.json", "6010dc772d914afec7dd31f35f953ce74b65ab3a648ce54aaee559f908b492f9", "private Cloud qualification"], + ["grok", "grok-profile-v15-identity.json", "54f7063c82dc5b135a9b5e2b0d8653b5c839a42bbc3a845dbcfb6cd225fa623f", "published cd5"], + ["grok", "grok-profile-v15-cursor-cloud-qualification-historical-identity.json", "f5d4b41284d60413575f88371e66e940942c256d8b6d9619104deaee181054b2", "private Cloud qualification"], + ["copilot", "copilot-profile-v86-identity.json", "6baeb98adc7132b2afdce8b1d2da1df2f00356677eb4497c49c05aa9def79138", "published a8"], + ["copilot", "copilot-profile-v86-cursor-cloud-qualification-historical-identity.json", "118a4b0a782b56570e5530cca91255da8932c31f827c319b40a5810bd4d446e9", "private Cloud qualification"], + ["copilot", "copilot-profile-v87-identity.json", "505bb72a933d11e3f5aa8a1700d239c06b4d34bb83d5187470483812df996501", "published a8"], + ["copilot", "copilot-profile-v87-cursor-cloud-qualification-historical-identity.json", "ce9912c34ae9126e74061f7bc170b59589af7cb6ab26751e250da9e9dd9553c9", "private Cloud qualification"], + ["copilot", "copilot-profile-v85-identity.json", "15d2790d94d7cc46ac728119ed9b4d07ed2b682be039b3debc716600708d8c1a", "published ed8"], + ["copilot", "copilot-profile-v85-cursor-cloud-qualification-historical-identity.json", "977d68b327f3964e8337ef8ba00230eb1b1697017db21f8010f664fee3d3c70a", "private Cloud qualification"], + ["grok", "grok-profile-v14-identity.json", "08294ec6bdcbdbe46c8c8b711d8b368558a05f0d84d25c9f5fd0c3b67b79cd17", "published ed8"], + ["grok", "grok-profile-v14-cursor-cloud-qualification-historical-identity.json", "fa34ba395ff51affed7e7195dc44f4e33a3c6718ada1c80e8e36852cf7af40ac", "private Cloud qualification"], + ] as const)("keeps %s identity %s immutable and decode-only", (agent, filename, checksum) => { + const bytes = readFileSync(new URL(`../../../test/fixtures/${filename}`, import.meta.url)); + expect(createHash("sha256").update(bytes).digest("hex")).toBe(checksum); + const identity = JSON.parse(bytes.toString("utf8")); + expect(isSupportedAcpxProfileVersion(agent, identity.declaration.agentProfileVersion)).toBe(true); + expect(identity.commandDigest).not.toBe(QUALIFIED_ACPX_PROFILE_DATA[agent].commandDigest); + }); + + it("decodes every retained Copilot identity so saved runs can reach recovery", () => { + const root = new URL("../../../test/fixtures/", import.meta.url); + const files = readdirSync(root).filter(name => /^copilot-profile-v\d+.*-identity\.json$/u.test(name)); + expect(files.length).toBeGreaterThan(30); + for (const file of files) { + const identity = JSON.parse(readFileSync(new URL(file, root), "utf8")); + expect(isSupportedAcpxProfileVersion("copilot", identity.declaration.agentProfileVersion), file).toBe(true); + } + }); + it("decodes every retained Grok identity so saved runs can reach recovery", () => { + const root = new URL("../../../test/fixtures/", import.meta.url); + const files = readdirSync(root).filter(name => /^grok-profile-v\d+.*-identity\.json$/u.test(name)); + expect(files.length).toBeGreaterThan(0); + for (const file of files) { + const identity = JSON.parse(readFileSync(new URL(file, root), "utf8")); + expect(isSupportedAcpxProfileVersion("grok", identity.declaration.agentProfileVersion), file).toBe(true); + } + }); it("decodes every revision from 1 through the current one so saved runs reach recovery", () => { for (const [agent, current] of Object.entries(QUALIFIED_ACPX_PROFILE_DATA)) { for (let version = 1; version <= current.agentProfileVersion; version += 1) { diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/app-server-proxy.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/app-server-proxy.test.ts new file mode 100644 index 00000000000..72fe00b3ec6 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/app-server-proxy.test.ts @@ -0,0 +1,191 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { PassThrough } from "node:stream"; +import { mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { request } from "node:http"; +import { CursorCloudCheckpointStore } from "./checkpoint.js"; +import { RUNNER_TOOL_SCOPE_TOKEN_HEADER } from "../runner-tool-bridge.js"; +import { CursorCloudDriver, type CursorCloudSessionHandle } from "./cursor-cloud-driver.js"; +import { startCursorCloudAppServerProxy } from "../../cli/cursor-cloud-app-server-proxy.js"; + +const roots: string[] = []; +const proxies: Array> = []; +afterEach(async () => { + for (const proxy of proxies.splice(0)) await proxy.shutdown(); + vi.restoreAllMocks(); + for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); +}); +async function peer() { + const root = await mkdtemp("/tmp/cc-proxy-"); roots.push(root); + const configPath = join(root, "config.json"); + await writeFile(configPath, JSON.stringify({ schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo" }], binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId: "session" } }), { mode: 0o600 }); + const input = new PassThrough(); const output = new PassThrough(); const diagnostic = new PassThrough(); + const frames: any[] = []; let buffer = ""; + output.on("data", chunk => { buffer += chunk.toString(); let index; while ((index = buffer.indexOf("\n")) >= 0) { frames.push(JSON.parse(buffer.slice(0, index))); buffer = buffer.slice(index + 1); } }); + const proxy = startCursorCloudAppServerProxy({ input, output, diagnostic, environment: { CURSOR_API_KEY: "private-key", PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH: configPath, PAPERCLIP_NORMALIZED_SESSION_ID: "session", PAPERCLIP_RUN_ID: "run", PAPERCLIP_CURSOR_CLOUD_RELAY_URL: "https://relay.example.test/mcp", PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN: "private-relay-token", PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH: join(root, "mcp.sock"), PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT: String(Date.now() + 600_000) } }); + proxies.push(proxy); + async function rpc(id: number, method: string, params: unknown = {}) { input.write(`${JSON.stringify({ id, method, params })}\n`); await vi.waitFor(() => expect(frames.some(frame => frame.id === id)).toBe(true), { timeout: 5_000 }); return frames.find(frame => frame.id === id); } + return { root, input, output, frames, proxy, rpc, socketPath: join(root, "mcp.sock") }; +} +function mcp(socketPath: string, body: Record, headers: Record, sessionId?: string): Promise<{ headers: Record; value: any }> { + return new Promise((accept, reject) => { + const req = request({ socketPath, path: "/mcp", method: "POST", headers: { ...headers, "content-type": "application/json", ...(sessionId ? { "Mcp-Session-Id": sessionId } : {}) } }, response => { + let text = ""; response.on("data", chunk => { text += chunk; }); response.on("end", () => { try { accept({ headers: response.headers, value: JSON.parse(text) }); } catch (error) { reject(error); } }); + }); + req.on("error", reject); req.end(JSON.stringify({ jsonrpc: "2.0", ...body })); + }); +} +describe("Cursor Cloud bounded stdio proxy", () => { + it("initializes/opens without provider work and returns an explicit empty remote shutdown receipt", async () => { + const nativeFetch = vi.spyOn(globalThis, "fetch").mockRejectedValue(new Error("unexpected paid call")); + const f = await peer(); + try { + expect(await f.rpc(1, "initialize")).toMatchObject({ result: { serverInfo: { name: "cursor-cloud" } } }); + const opened = await f.rpc(2, "thread/start", { model: "explicit-model", cwd: f.root, baseInstructions: "Exact instructions" }); + expect(opened).toMatchObject({ result: { thread: { id: "session" }, submittedModel: "explicit-model", effectiveModelAcknowledged: false, instructionsAcknowledged: false } }); + expect(opened.result).not.toHaveProperty("model"); expect(opened.result.thread).not.toHaveProperty("model"); + expect(await f.rpc(3, "turn/start", { input: [{ type: "image", url: "https://example.com/image.png" }] })).toHaveProperty("error"); + for (const [id, override] of [[4, { collaborationMode: { mode: "plan" } }], [5, { reasoningMode: "high" }]] as const) { + expect(await f.rpc(id, "turn/start", { ...override, input: [{ type: "text", text: "Create the plan." }] })) + .toMatchObject({ error: { message: "Cursor Cloud native plan/reasoning override is unsupported" } }); + } + expect(await f.rpc(6, "collaborationMode/list")).toMatchObject({ result: { data: [{ mode: "default" }] } }); + expect(await f.rpc(7, "paperclip/shutdown", { threadId: "session", turnId: null })).toMatchObject({ result: { remoteStopped: true, threadId: "session", turnId: null, remoteRunId: null } }); + expect(nativeFetch).not.toHaveBeenCalled(); + } finally { f.input.end(); await f.proxy.done; } + }); + it("bounds an unterminated input frame and finishes instead of retaining unbounded input", async () => { + const f = await peer(); f.input.write("x".repeat(2_097_153)); await f.proxy.done; + expect(f.frames).toEqual([]); + }); + it("preserves native tool identity, status and bounded redacted output without assuming MCP transport", async () => { + const remoteRunId = "run-22222222-2222-4222-8222-222222222222"; + const now = "2026-10-28T00:00:00Z"; + let remoteAgentId = ""; + const json = (value: unknown) => new Response(JSON.stringify(value), { headers: { "content-type": "application/json" } }); + const nativeFetch = vi.spyOn(globalThis, "fetch").mockImplementation(async (url, init) => { + const target = new URL(String(url)); + expect(target.origin).toBe("https://api.cursor.com"); + if (target.pathname === "/v1/agents" && init?.method === "POST") { + remoteAgentId = JSON.parse(String(init.body)).agentId; + return json({ agent: { id: remoteAgentId, status: "ACTIVE", env: { type: "cloud" }, url: `https://cursor.com/agents/${remoteAgentId}`, createdAt: now, updatedAt: now, latestRunId: remoteRunId }, run: { id: remoteRunId, agentId: remoteAgentId, status: "RUNNING", createdAt: now, updatedAt: now } }); + } + if (target.pathname.endsWith("/stream")) { + const records = [ + { callId: "native-discovery", name: "get_mcp_tools", status: "running", args: { toolCallId: "synthetic-private-argument" }, result: { error: "native failure private-key private-relay-token" } }, + { callId: "native-discovery", name: "get_mcp_tools", status: "error", args: { toolCallId: "synthetic-private-argument" }, result: { error: "native failure private-key private-relay-token" } }, + { callId: "native-read", name: "read_file", status: "completed", args: { path: "synthetic-private-path" }, result: "x".repeat(65_536) }, + ]; + const body = records.map((data, index) => `id: ${index + 1}\nevent: tool_call\ndata: ${JSON.stringify(data)}\n\n`).join("") + + `id: 4\nevent: result\ndata: ${JSON.stringify({ runId: remoteRunId, status: "FINISHED" })}\n\n`; + return new Response(body, { headers: { "content-type": "text/event-stream" } }); + } + if (target.pathname.endsWith(`/${remoteRunId}`)) return json({ id: remoteRunId, agentId: remoteAgentId, status: "FINISHED", createdAt: now, updatedAt: now }); + throw new Error("Unexpected controlled provider request"); + }); + let releaseTerminalWrites!: () => void; + const terminalGate = new Promise(resolve => { releaseTerminalWrites = resolve; }); + let pausedTerminalWrites = 0; + const write = CursorCloudCheckpointStore.prototype.write; + vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(async function(value) { + if (value.phase === "terminal" && value.pendingTerminalDelivery) { + pausedTerminalWrites += 1; + await terminalGate; + } + await write.call(this, value); + }); + const f = await peer(); + try { + await f.rpc(1, "initialize"); + expect(await f.rpc(2, "thread/start", { model: "explicit-model", cwd: f.root })).toMatchObject({ result: { thread: { id: "session" } } }); + await f.rpc(3, "turn/start", { input: [{ type: "text", text: "Inspect native tool event delivery" }] }); + await vi.waitFor(() => expect(f.frames.filter(frame => frame.params?.item?.name === "get_mcp_tools" || frame.params?.item?.name === "read_file")).toHaveLength(3), { timeout: 1_000 }); + await vi.waitFor(() => expect(pausedTerminalWrites).toBe(1), { timeout: 5_000 }); + const pendingRead = f.rpc(9, "thread/read"); + await new Promise(accept => setImmediate(accept)); + expect(f.frames.some(frame => frame.id === 9)).toBe(false); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + expect(JSON.parse(await readFile(checkpointPath, "utf8")).phase).toBe("running"); + releaseTerminalWrites(); + const committed = await pendingRead; + expect(committed.result.cursorCloudTerminalDelivery).toEqual(JSON.parse(await readFile(checkpointPath, "utf8")).pendingTerminalDelivery); + await vi.waitFor(() => expect(f.frames.some(frame => frame.method === "turn/completed")).toBe(true), { timeout: 5_000 }); + const tools = f.frames.filter(frame => frame.params?.item?.name === "get_mcp_tools" || frame.params?.item?.name === "read_file"); + expect(tools.map(frame => ({ method: frame.method, type: frame.params.item.type, tool: frame.params.item.tool, status: frame.params.item.status }))).toEqual([ + { method: "item/started", type: "builtinToolCall", tool: "get_mcp_tools", status: "running" }, + { method: "item/completed", type: "builtinToolCall", tool: "get_mcp_tools", status: "error" }, + { method: "item/completed", type: "builtinToolCall", tool: "read_file", status: "completed" }, + ]); + expect(JSON.parse(tools[0].params.item.output)).toEqual({ error: "native failure [redacted] [redacted]" }); + expect(JSON.parse(tools[1].params.item.output)).toEqual({ error: "native failure [redacted] [redacted]" }); + expect(JSON.parse(tools[2].params.item.output)).toEqual({ omitted: true, reason: "payload_limit" }); + expect(JSON.stringify(tools)).not.toContain("private-key"); + expect(JSON.stringify(tools)).not.toContain("private-relay-token"); + const retained = await f.rpc(4, "thread/read"); + expect(retained.result.thread.turns).toEqual([]); + expect(retained.result.cursorCloudTerminalDelivery).toMatchObject({ status: "FINISHED", receiptId: expect.any(String) }); + const receipt = retained.result.cursorCloudTerminalDelivery; + expect(await f.rpc(10, "paperclip/shutdown")).toMatchObject({ result: { cursorCloudTerminalDelivery: retained.result.cursorCloudTerminalDelivery } }); + expect(await f.rpc(5, "paperclip/ackTerminal", { turnId: receipt.turnId, receiptId: "wrong" })).toHaveProperty("error"); + expect(await f.rpc(6, "paperclip/ackTerminal", { turnId: receipt.turnId, receiptId: receipt.receiptId })).toMatchObject({ result: { acknowledged: true } }); + expect((await f.rpc(7, "thread/read")).result.cursorCloudTerminalDelivery).toBeNull(); + expect(await f.rpc(8, "paperclip/shutdown", { turnId: null })).toMatchObject({ result: { remoteStopped: true, turnId: null } }); + expect(nativeFetch.mock.calls.filter(([url, init]) => new URL(String(url)).pathname === "/v1/agents" && init?.method === "POST")).toHaveLength(1); + } finally { releaseTerminalWrites(); f.input.end(); await f.proxy.done; } + }); + it("round-trips a semantic completion over stdio and certifies shutdown only after native terminal lookup", async () => { + const remoteRunId = "run-22222222-2222-4222-8222-222222222222"; + let remoteAgentId = ""; let status = "RUNNING"; let stream: ReadableStreamDefaultController | undefined; + let mcpHeaders!: Record; + const now = "2026-10-28T00:00:00Z"; + const json = (value: unknown) => new Response(JSON.stringify(value), { headers: { "content-type": "application/json" } }); + const nativeFetch = vi.spyOn(globalThis, "fetch").mockImplementation(async (url, init) => { + const path = new URL(String(url)).pathname; + if (path === "/v1/agents" && init?.method === "POST") { + const body = JSON.parse(String(init.body)); remoteAgentId = body.agentId; mcpHeaders = body.mcpServers[0].headers; + return json({ agent: { id: remoteAgentId, status: "ACTIVE", env: { type: "cloud" }, url: `https://cursor.com/agents/${remoteAgentId}`, createdAt: now, updatedAt: now, latestRunId: remoteRunId }, run: { id: remoteRunId, agentId: remoteAgentId, status, createdAt: now, updatedAt: now } }); + } + if (path.endsWith("/stream")) return new Response(new ReadableStream({ start(controller) { stream = controller; controller.enqueue(new TextEncoder().encode(`id: 1\nevent: assistant\ndata: {"text":"Working"}\n\n`)); } }), { headers: { "content-type": "text/event-stream" } }); + if (path.endsWith(`/${remoteRunId}`)) return json({ id: remoteRunId, agentId: remoteAgentId, status, createdAt: now, updatedAt: now }); + throw new Error("Unexpected controlled provider request"); + }); + let openedSession!: CursorCloudSessionHandle; + const openSession = CursorCloudDriver.prototype.openSession; + vi.spyOn(CursorCloudDriver.prototype, "openSession").mockImplementation(async function(input) { + openedSession = await openSession.call(this, input); + return openedSession; + }); + const f = await peer(); + try { + await f.rpc(1, "initialize"); await f.rpc(2, "thread/start", { model: "explicit-model", cwd: f.root, baseInstructions: "Use semantic completion." }); + const started = await f.rpc(3, "turn/start", { input: [{ type: "text", text: "Do the task" }] }); + await vi.waitFor(() => expect(stream).toBeDefined(), { timeout: 5_000 }); + expect(mcpHeaders).toMatchObject({ Authorization: "Bearer private-relay-token", [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: expect.stringMatching(/^Bearer [A-Za-z0-9_-]{43}$/) }); + await expect(mcp(f.socketPath, { id: -1, method: "initialize" }, { Authorization: "Bearer private-relay-token" })).rejects.toBeInstanceOf(SyntaxError); + const initialized = await mcp(f.socketPath, { id: 0, method: "initialize" }, mcpHeaders); + const input = { reportedWorkDisposition: "done", summary: "Completed.", evidence: [], verification: [], completionClaim: { contractRevision: "1", objectiveSatisfied: true, criteria: [], remainingWork: [] } }; + const response = mcp(f.socketPath, { id: 1, method: "tools/call", params: { name: "paperclip_finish", arguments: input } }, mcpHeaders, initialized.headers["mcp-session-id"] as string); + await vi.waitFor(() => expect(f.frames.some(frame => frame.method === "item/tool/call")).toBe(true), { timeout: 5_000 }); + const call = f.frames.find(frame => frame.method === "item/tool/call"); + expect(call.params).toMatchObject({ threadId: "session", turnId: started.result.turn.id, tool: "paperclip_finish", arguments: input }); + f.input.write(`${JSON.stringify({ id: call.id, result: { success: true, contentItems: [{ type: "inputText", text: "Exact accepted completion receipt" }] } })}\n`); + expect((await response).value.result.content[0].text).toContain("Exact accepted completion receipt"); + expect(f.frames.some(frame => frame.method === "paperclip/runResult" || frame.method === "turn/completed")).toBe(false); + const snapshot = openedSession.snapshot.bind(openedSession); + let settleDuringRead = true; + vi.spyOn(openedSession, "snapshot").mockImplementation(async () => { + const value = await snapshot(); + if (settleDuringRead) { + settleDuringRead = false; + status = "FINISHED"; stream!.enqueue(new TextEncoder().encode(`id: 2\nevent: result\ndata: ${JSON.stringify({ runId: remoteRunId, status })}\n\n`)); + await vi.waitFor(() => expect(f.frames.some(frame => frame.method === "turn/completed")).toBe(true), { timeout: 5_000 }); + } + return value; + }); + const racing = await f.rpc(5, "thread/read"); + expect(Boolean(racing.result.thread.turns.length && racing.result.cursorCloudTerminalDelivery)).toBe(false); + expect(await f.rpc(4, "paperclip/shutdown", { threadId: "session", turnId: started.result.turn.id })).toMatchObject({ result: { remoteStopped: true, threadId: "session", turnId: started.result.turn.id, remoteAgentId, remoteRunId, status: "FINISHED" } }); + expect(nativeFetch.mock.calls.filter(([url, init]) => new URL(String(url)).pathname === "/v1/agents" && init?.method === "POST")).toHaveLength(1); + } finally { f.input.end(); await f.proxy.done; } + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.test.ts new file mode 100644 index 00000000000..832ea1394df --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.test.ts @@ -0,0 +1,523 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { createHash, randomUUID } from "node:crypto"; +import { spawn, spawnSync } from "node:child_process"; +import { once } from "node:events"; +import { constants } from "node:fs"; +import { link, lstat, mkdir, mkdtemp, open, readFile, readdir, rename, rm, symlink, unlink, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { stageCursorCloudArtifact } from "./artifact-delivery.js"; +import { reserveCursorCloudArtifactStaging } from "./artifact-staging-budget.js"; + +vi.mock("node:fs/promises", async importOriginal => { + const original = await importOriginal(); + return { ...original, open: vi.fn(original.open), link: vi.fn(original.link), unlink: vi.fn(original.unlink) }; +}); + +const roots: string[] = []; +afterEach(async () => { vi.restoreAllMocks(); for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); }); + +function deferred() { + let resolve!: () => void; + const promise = new Promise(done => { resolve = done; }); + return { promise, resolve }; +} + +async function fixture() { + const root = await mkdtemp("/tmp/cc-artifact-"); roots.push(root); + const bytes = Buffer.from("downloaded provider result\n"); const sha256 = createHash("sha256").update(bytes).digest("hex"); + const client = { listArtifacts: vi.fn(async () => ({ items: [{ path: "artifacts/result.txt", sizeBytes: bytes.length, updatedAt: "2026-10-28" }] })), downloadArtifact: vi.fn(async () => bytes) }; + const args = { contentRef: "cursor-artifact:artifacts/result.txt", filename: "result.txt", byteSize: bytes.length, sha256, contentType: "text/plain" }; + const controller = new AbortController(); const artifactRoot = join(root, "artifacts"); const directory = join(artifactRoot, sha256); + const input = { arguments: args, agentId: "agent", runtimeDirectory: root, artifactRoot, client, signal: controller.signal }; + return { root, bytes, args, input, controller, directory, target: join(directory, args.filename), normalized: { ...args, contentRef: join(sha256, args.filename) } }; +} + +async function postLinkWriter(f: Awaited>) { + const script = join(f.root, `postlink-${randomUUID()}.mjs`); + await writeFile(script, ` + import fs from "node:fs/promises"; + import { syncBuiltinESMExports } from "node:module"; + const original = fs.link; + fs.link = async (...args) => { + await original(...args); process.send({ name: "linked", temporary: args[0] }); + await new Promise(resolve => process.once("message", resolve)); + }; + syncBuiltinESMExports(); + const { stageCursorCloudArtifact } = await import(${JSON.stringify(new URL("./artifact-delivery.ts", import.meta.url).href)}); + const bytes = Buffer.from(${JSON.stringify(f.bytes.toString("base64"))}, "base64"); + const result = await stageCursorCloudArtifact({ arguments: ${JSON.stringify(f.args)}, agentId: "agent", runtimeDirectory: ${JSON.stringify(f.root)}, artifactRoot: ${JSON.stringify(f.input.artifactRoot)}, + client: { listArtifacts: async () => ({ items: [{ path: "artifacts/result.txt", sizeBytes: bytes.length }] }), downloadArtifact: async () => bytes }, signal: new AbortController().signal }); + process.send({ name: "completed", result }, () => process.disconnect()); + `, { mode: 0o600 }); + const child = spawn(process.execPath, ["--import", new URL("../../../node_modules/tsx/dist/loader.mjs", import.meta.url).pathname, script], { env: {}, stdio: ["ignore", "ignore", "pipe", "ipc"] }); + let stderr = ""; child.stderr?.on("data", bytes => { stderr = (stderr + bytes).slice(-4_096); }); + const exited = once(child, "exit"); + try { + const message = await Promise.race([once(child, "message"), exited.then(() => { throw new Error(`postlink fixture exited early: ${stderr}`); })]); + expect(message[0]).toMatchObject({ name: "linked" }); + const temporary = String(message[0].temporary); + expect(await readFile(temporary)).toEqual(f.bytes); + return { child, exited, temporary, async stop() { + if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL"); + await exited; + } }; + } catch (error) { + if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL"); + await exited; throw error; + } +} + +function exitedPid() { + const child = spawnSync(process.execPath, ["--input-type=module", "-e", ""], { env: {}, stdio: "ignore" }); + expect(child.status).toBe(0); + expect(() => process.kill(child.pid, 0)).toThrowError(expect.objectContaining({ code: "ESRCH" })); + return child.pid; +} + +function aliasPath(f: Awaited>, pid: number, filename = f.args.filename) { + const targetDigest = createHash("sha256").update(filename).digest("hex"); + return join(f.directory, `.cursor-cloud-${targetDigest}-${pid}-${randomUUID()}-${randomUUID()}.tmp`); +} + +describe("Cursor Cloud artifact registration boundary", () => { + it("recovers an exact published final at capacity without a new allocation", async () => { + const f = await fixture(); const writer = await postLinkWriter(f); + try { + await writer.stop(); + for (let count = 1; count < 256; count++) await reserveCursorCloudArtifactStaging({ ...f.input, byteSize: 0 }); + const budgetPath = join(f.root, ".artifact-staging-budget", "usage.json"); + const before = await readFile(budgetPath, "utf8"); + expect(JSON.parse(before).allocations).toBe(256); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + expect((await lstat(f.target)).nlink).toBe(1); + expect(await readFile(budgetPath, "utf8")).toBe(before); + expect(f.input.client.downloadArtifact).toHaveBeenCalledOnce(); + await expect(stageCursorCloudArtifact({ ...f.input, arguments: { ...f.args, filename: "over-budget.txt" } })).rejects.toThrow(/staging budget/); + expect(f.input.client.downloadArtifact).toHaveBeenCalledOnce(); + } finally { await writer.stop(); } + }, 20_000); + + it("rejects changed current provider bytes despite a matching verified cached final", async () => { + const f = await fixture(); await stageCursorCloudArtifact(f.input); + f.input.client.downloadArtifact.mockResolvedValueOnce(Buffer.alloc(f.bytes.length, "x")); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("do not match"); + expect(await readFile(f.target)).toEqual(f.bytes); + }); + + it("refuses cached bytes that grow after their initial size observation", async () => { + const f = await fixture(); await stageCursorCloudArtifact(f.input); + f.input.client.downloadArtifact.mockClear(); + const original = await vi.importActual("node:fs/promises"); + let injected = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if (!injected && String(path) === f.target) { + const stat = handle.stat.bind(handle); + vi.spyOn(handle, "stat").mockImplementation(async () => { + const before = await stat(); + if (!injected) { injected = true; await writeFile(f.target, Buffer.concat([f.bytes, Buffer.from("extra")])); } + return before; + }); + } + return handle; + }) as typeof open); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("identity conflict"); + expect(f.input.client.downloadArtifact).not.toHaveBeenCalled(); + expect((await lstat(f.target)).size).toBe(f.bytes.length + 5); + }); + + it("refuses a new download after legacy retained bytes reach the 256 MiB budget", async () => { + const f = await fixture(); + const size = 16_777_216, hash = createHash("sha256").update(Buffer.alloc(size)).digest("hex"); + const directory = join(f.input.artifactRoot, hash); await mkdir(directory, { recursive: true, mode: 0o700 }); + for (let index = 0; index < 16; index++) { + const file = await open(join(directory, `legacy-${index}`), "wx", 0o600); + try { await file.truncate(size); } finally { await file.close(); } + } + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(/staging budget/); + expect(f.input.client.downloadArtifact).not.toHaveBeenCalled(); + await expect(lstat(f.target)).rejects.toMatchObject({ code: "ENOENT" }); + expect(await readdir(directory)).toHaveLength(16); + }); + + it("counts zero-byte retained files against the 256-allocation budget", async () => { + const f = await fixture(); const hash = createHash("sha256").update("").digest("hex"); + const directory = join(f.input.artifactRoot, hash); await mkdir(directory, { recursive: true, mode: 0o700 }); + for (let index = 0; index < 256; index++) await writeFile(join(directory, `legacy-${index}`), "", { mode: 0o600 }); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(/staging budget/); + expect(f.input.client.downloadArtifact).not.toHaveBeenCalled(); + expect(await readdir(directory)).toHaveLength(256); + }); + + it("recovers an actual postlink writer crash to one final link", async () => { + const f = await fixture(); const writer = await postLinkWriter(f); + try { + const published = await lstat(f.target); expect(published.nlink).toBe(2); + await writer.stop(); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + const recovered = await lstat(f.target); + expect([recovered.dev, recovered.ino, recovered.nlink]).toEqual([published.dev, published.ino, 1]); + expect(await readFile(f.target)).toEqual(f.bytes); + await expect(lstat(writer.temporary)).rejects.toMatchObject({ code: "ENOENT" }); + expect(await readdir(f.directory)).toEqual([f.args.filename]); + } finally { await writer.stop(); } + }); + + it("lets concurrent retries adopt one dead publisher alias without replacing the final", async () => { + const f = await fixture(); const writer = await postLinkWriter(f); + try { + await writer.stop(); const published = await lstat(f.target); + const foreign = join(f.directory, "unrelated-private-file"); + await writeFile(foreign, "retained foreign bytes", { mode: 0o600 }); const before = await lstat(foreign); + expect(await Promise.all([stageCursorCloudArtifact(f.input), stageCursorCloudArtifact(f.input)])).toEqual([f.normalized, f.normalized]); + const recovered = await lstat(f.target); const retained = await lstat(foreign); + expect([recovered.dev, recovered.ino, recovered.nlink]).toEqual([published.dev, published.ino, 1]); + expect([retained.dev, retained.ino, retained.mode]).toEqual([before.dev, before.ino, before.mode]); + expect(await readFile(f.target)).toEqual(f.bytes); + expect(await readFile(foreign, "utf8")).toBe("retained foreign bytes"); + await expect(lstat(writer.temporary)).rejects.toMatchObject({ code: "ENOENT" }); + expect((await readdir(f.directory)).sort()).toEqual([f.args.filename, "unrelated-private-file"].sort()); + } finally { await writer.stop(); } + }); + + it("never removes another live process's published alias", async () => { + const f = await fixture(); const writer = await postLinkWriter(f); + try { + const before = await lstat(writer.temporary); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(); + const retained = await lstat(writer.temporary); + expect([retained.dev, retained.ino, retained.nlink]).toEqual([before.dev, before.ino, 2]); + expect(await readFile(writer.temporary)).toEqual(f.bytes); + const completed = once(writer.child, "message"); writer.child.send("continue"); + expect((await completed)[0]).toMatchObject({ name: "completed", result: f.normalized }); + expect(await writer.exited).toEqual([0, null]); + expect((await lstat(f.target)).nlink).toBe(1); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + } finally { await writer.stop(); } + }); + + it("never removes an active same-module publisher alias", async () => { + const f = await fixture(); const original = await vi.importActual("node:fs/promises"); + const linked = deferred(); const resume = deferred(); let alias = ""; + vi.mocked(link).mockImplementation(async (source, destination) => { + await original.link(source, destination); + if (!alias && String(destination) === f.target) { alias = String(source); linked.resolve(); await resume.promise; } + }); + const active = stageCursorCloudArtifact(f.input); + try { + await linked.promise; + const before = await lstat(alias); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(); + const retained = await lstat(alias); + expect([retained.dev, retained.ino, retained.nlink]).toEqual([before.dev, before.ino, 2]); + expect(await readFile(alias)).toEqual(f.bytes); + resume.resolve(); expect(await active).toEqual(f.normalized); + expect((await lstat(f.target)).nlink).toBe(1); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + } finally { resume.resolve(); await active.catch(() => {}); } + }); + + it("recovers only the alias of a finished own attempt after cleanup failure", async () => { + const f = await fixture(); const original = await vi.importActual("node:fs/promises"); + let alias = ""; + vi.mocked(unlink).mockImplementation(async path => { + if (!alias && String(path).startsWith(`${f.directory}/`) && String(path).endsWith(".tmp")) { + alias = String(path); throw Object.assign(new Error("fixture completed-attempt cleanup failed"), { code: "EIO" }); + } + await original.unlink(path); + }); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("fixture completed-attempt cleanup failed"); + expect((await lstat(f.target)).nlink).toBe(2); + expect(await readFile(alias)).toEqual(f.bytes); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + await expect(lstat(alias)).rejects.toMatchObject({ code: "ENOENT" }); + expect((await lstat(f.target)).nlink).toBe(1); + expect(await readdir(f.directory)).toEqual([f.args.filename]); + }); + + it.each(["foreign", "unknown", "wrong-target", "live-reused-pid", "malformed", "unrelated-inode", "symlink", "unknown-liveness"])("retains %s aliases and refuses to certify multiple links", async mode => { + const f = await fixture(); let ownSuccessfulAlias = ""; + if (mode === "foreign") { + const original = await vi.importActual("node:fs/promises"); + vi.mocked(link).mockImplementation(async (source, destination) => { + await original.link(source, destination); + if (!ownSuccessfulAlias && String(destination) === f.target) ownSuccessfulAlias = String(source); + }); + } + await stageCursorCloudArtifact(f.input); + const deadPid = exitedPid(); const originalKill = process.kill.bind(process); + let alias = mode === "foreign" ? ownSuccessfulAlias + : mode === "unknown" ? join(f.directory, `.cursor-cloud-${randomUUID()}.tmp`) + : aliasPath(f, mode === "live-reused-pid" ? process.pid : deadPid, mode === "wrong-target" ? "other-result.txt" : f.args.filename); + if (mode === "malformed") alias = alias.replace(/-[a-f0-9-]{36}\.tmp$/, "-not-an-attempt.tmp"); + if (mode === "unrelated-inode" || mode === "symlink") { + await link(f.target, join(f.directory, "unknown-final-alias")); + if (mode === "unrelated-inode") await writeFile(alias, f.bytes, { mode: 0o600 }); + else await symlink(f.target, alias); + } else await link(f.target, alias); + if (mode === "unknown-liveness") vi.spyOn(process, "kill").mockImplementation((pid, signal) => { + if (pid === deadPid) throw Object.assign(new Error("fixture owner liveness unknown"), { code: "EPERM" }); + return originalKill(pid, signal); + }); + const before = await lstat(alias); const final = await lstat(f.target); const names = (await readdir(f.directory)).sort(); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(); + const after = await lstat(alias); const retained = await lstat(f.target); + expect([after.dev, after.ino, after.mode]).toEqual([before.dev, before.ino, before.mode]); + expect([retained.dev, retained.ino, retained.nlink]).toEqual([final.dev, final.ino, 2]); + expect(await readFile(alias)).toEqual(f.bytes); + expect(await readFile(f.target)).toEqual(f.bytes); + expect((await readdir(f.directory)).sort()).toEqual(names); + }); + + it.each(["entries", "aliases"])("refuses an over-bound %s recovery without deleting aliases", async mode => { + const f = await fixture(); await stageCursorCloudArtifact(f.input); const deadPid = exitedPid(); + const aliases = Array.from({ length: mode === "aliases" ? 33 : 1 }, () => aliasPath(f, deadPid)); + for (const alias of aliases) await link(f.target, alias); + if (mode === "entries") for (let index = 0; index < 256; index += 16) { + await Promise.all(Array.from({ length: 16 }, (_, offset) => writeFile(join(f.directory, `unrelated-${index + offset}`), "retained", { mode: 0o600 }))); + } + const before = await lstat(f.target); const names = (await readdir(f.directory)).sort(); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(); + const after = await lstat(f.target); + expect([after.dev, after.ino, after.nlink]).toEqual([before.dev, before.ino, before.nlink]); + expect((await readdir(f.directory)).sort()).toEqual(names); + for (const alias of aliases) expect(await readFile(alias)).toEqual(f.bytes); + }); + + it("does not clean a dead publisher alias after recovery cancellation", async () => { + const f = await fixture(); const writer = await postLinkWriter(f); await writer.stop(); + const original = await vi.importActual("node:fs/promises"); + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if (String(path) === f.target) { + const read = handle.read.bind(handle) as (...args: unknown[]) => Promise>>; + vi.spyOn(handle, "read").mockImplementation((async (...args: unknown[]) => { + const bytes = await read(...args); f.controller.abort(new Error("fixture artifact recovery cancelled")); return bytes; + }) as typeof handle.read); + } + return handle; + }) as typeof open); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("fixture artifact recovery cancelled"); + expect(await readFile(writer.temporary)).toEqual(f.bytes); + expect((await lstat(f.target)).nlink).toBe(2); + vi.mocked(open).mockImplementation(original.open); + expect(await stageCursorCloudArtifact({ ...f.input, signal: new AbortController().signal })).toEqual(f.normalized); + expect((await lstat(f.target)).nlink).toBe(1); + }); + + it("never exposes a partial final file and allows retry after a failed write", async () => { + const f = await fixture(); + const original = await vi.importActual("node:fs/promises"); + const partial = deferred(); const resume = deferred(); let injected = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if (!injected && String(path).startsWith(`${f.directory}/`) && (flags === "wx" || (typeof flags === "number" && (flags & constants.O_EXCL) !== 0))) { + injected = true; + vi.spyOn(handle, "writeFile").mockImplementation(async () => { + await handle.write(f.bytes.subarray(0, 4), 0, 4, 0); + partial.resolve(); await resume.promise; throw new Error("fixture partial artifact write failed"); + }); + } + return handle; + }) as typeof open); + const staging = stageCursorCloudArtifact(f.input); + try { + await partial.promise; + const visible = await readFile(f.target).catch(error => { if (error.code === "ENOENT") return null; throw error; }); + resume.resolve(); + await expect(staging).rejects.toThrow("fixture partial artifact write failed"); + expect(visible).toBeNull(); + await expect(lstat(f.target)).rejects.toMatchObject({ code: "ENOENT" }); + expect(await readdir(f.directory)).toEqual([]); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + expect(await readFile(f.target)).toEqual(f.bytes); + } finally { resume.resolve(); await staging.catch(() => {}); } + }); + + it("does not publish an artifact cancelled while its private write is pending", async () => { + const f = await fixture(); + const original = await vi.importActual("node:fs/promises"); + const written = deferred(); const resume = deferred(); let injected = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if (!injected && String(path).startsWith(`${f.directory}/`) && (flags === "wx" || (typeof flags === "number" && (flags & constants.O_EXCL) !== 0))) { + injected = true; const write = handle.writeFile.bind(handle); + vi.spyOn(handle, "writeFile").mockImplementation(async (...args) => { await write(...args); written.resolve(); await resume.promise; }); + } + return handle; + }) as typeof open); + const staging = stageCursorCloudArtifact(f.input); + try { + await written.promise; f.controller.abort(new Error("fixture artifact cancellation")); resume.resolve(); + await expect(staging).rejects.toThrow("fixture artifact cancellation"); + await expect(lstat(f.target)).rejects.toMatchObject({ code: "ENOENT" }); + expect(await readdir(f.directory)).toEqual([]); + expect(JSON.parse(await readFile(join(f.root, ".artifact-staging-budget", "usage.json"), "utf8")).allocations).toBe(1); + } finally { resume.resolve(); await staging.catch(() => {}); } + }); + + it("keeps the final absent through an actual writer crash and retries without reaping the orphan", async () => { + const f = await fixture(); + const script = join(f.root, "crash-writer.mjs"); + await writeFile(script, ` + import fs from "node:fs/promises"; + import { constants } from "node:fs"; + import { syncBuiltinESMExports } from "node:module"; + const original = fs.open; + fs.open = async (...args) => { + const handle = await original(...args); + const flags = args[1]; + if (String(args[0]).startsWith(${JSON.stringify(`${f.directory}/`)}) && (flags === "wx" || (typeof flags === "number" && (flags & constants.O_EXCL) !== 0))) { + handle.writeFile = async bytes => { + await handle.write(bytes.subarray(0, 4), 0, 4, 0); await handle.sync(); + process.send("partial-written"); + await new Promise(resolve => process.once("message", resolve)); + }; + } + return handle; + }; + syncBuiltinESMExports(); + const { stageCursorCloudArtifact } = await import(${JSON.stringify(new URL("./artifact-delivery.ts", import.meta.url).href)}); + const bytes = Buffer.from(${JSON.stringify(f.bytes.toString("base64"))}, "base64"); + await stageCursorCloudArtifact({ arguments: ${JSON.stringify(f.args)}, agentId: "agent", runtimeDirectory: ${JSON.stringify(f.root)}, artifactRoot: ${JSON.stringify(f.input.artifactRoot)}, + client: { listArtifacts: async () => ({ items: [{ path: "artifacts/result.txt", sizeBytes: bytes.length }] }), downloadArtifact: async () => bytes }, signal: new AbortController().signal }); + process.send("unexpected-completed"); + `, { mode: 0o600 }); + const child = spawn(process.execPath, ["--import", new URL("../../../node_modules/tsx/dist/loader.mjs", import.meta.url).pathname, script], { env: {}, stdio: ["ignore", "ignore", "pipe", "ipc"] }); + let stderr = ""; child.stderr?.on("data", bytes => { stderr = (stderr + bytes).slice(-4_096); }); + const exited = once(child, "exit"); + try { + const message = await Promise.race([once(child, "message"), exited.then(() => { throw new Error(`artifact crash fixture exited early: ${stderr}`); })]); + expect(message[0]).toBe("partial-written"); + await expect(lstat(f.target)).rejects.toMatchObject({ code: "ENOENT" }); + child.kill("SIGKILL"); expect(await exited).toEqual([null, "SIGKILL"]); + const orphans = await readdir(f.directory); + expect(orphans).toHaveLength(1); + const orphan = join(f.directory, orphans[0]!); + expect(await readFile(orphan)).toEqual(f.bytes.subarray(0, 4)); + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + expect(await readFile(f.target)).toEqual(f.bytes); + expect(await readFile(orphan)).toEqual(f.bytes.subarray(0, 4)); + expect((await readdir(f.directory)).sort()).toEqual([...orphans, f.args.filename].sort()); + } finally { + if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL"); + await exited; + } + }); + + it("concurrently stages identical bytes without replacing the first verified final", async () => { + const f = await fixture(); + const original = await vi.importActual("node:fs/promises"); + const written = deferred(); const resume = deferred(); let held = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if (!held && String(path).startsWith(`${f.directory}/`) && (flags === "wx" || (typeof flags === "number" && (flags & constants.O_EXCL) !== 0))) { + held = true; const write = handle.writeFile.bind(handle); + vi.spyOn(handle, "writeFile").mockImplementation(async (...args) => { await write(...args); written.resolve(); await resume.promise; }); + } + return handle; + }) as typeof open); + const first = stageCursorCloudArtifact(f.input); + try { + await written.promise; + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + const published = await lstat(f.target); + resume.resolve(); expect(await first).toEqual(f.normalized); + const retained = await lstat(f.target); + expect([retained.dev, retained.ino]).toEqual([published.dev, published.ino]); + expect(await readFile(f.target)).toEqual(f.bytes); + expect(await readdir(f.directory)).toEqual([f.args.filename]); + } finally { resume.resolve(); await first.catch(() => {}); } + }); + + it("requires directory sync again when retry verifies an already-published final", async () => { + const f = await fixture(); + const original = await vi.importActual("node:fs/promises"); + const synced: string[] = []; let failures = 2; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + if ([f.directory, f.input.artifactRoot, f.root].includes(String(path))) { + const sync = handle.sync.bind(handle); + vi.spyOn(handle, "sync").mockImplementation(async () => { + synced.push(String(path)); + if (String(path) === f.directory && failures-- > 0) throw new Error("fixture artifact directory sync failed"); + await sync(); + }); + } + return handle; + }) as typeof open); + for (let attempt = 0; attempt < 2; attempt += 1) { + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("fixture artifact directory sync failed"); + expect(await readFile(f.target)).toEqual(f.bytes); + expect(await readdir(f.directory)).toEqual([f.args.filename]); + } + expect(await stageCursorCloudArtifact(f.input)).toEqual(f.normalized); + expect(synced).toEqual([f.root, f.directory, f.directory, f.directory, f.input.artifactRoot, f.root]); + }); + + it.each(["partial", "wrong-hash", "public-mode", "symlink", "directory"])("refuses an existing %s final unchanged", async mode => { + const f = await fixture(); await mkdir(f.directory, { recursive: true, mode: 0o700 }); + const bytes = mode === "partial" ? f.bytes.subarray(0, 4) : mode === "wrong-hash" ? Buffer.alloc(f.bytes.length, "x") : f.bytes; + if (mode === "directory") await mkdir(f.target, { mode: 0o700 }); + else if (mode === "symlink") { + const target = join(f.root, "unrelated-result"); + await writeFile(target, bytes, { mode: 0o600 }); await symlink(target, f.target); + } else await writeFile(f.target, bytes, { mode: mode === "public-mode" ? 0o644 : 0o600 }); + const before = await lstat(f.target); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow(); + const after = await lstat(f.target); + expect([after.dev, after.ino, after.mode]).toEqual([before.dev, before.ino, before.mode]); + if (mode !== "directory") expect(await readFile(f.target)).toEqual(bytes); + expect(await readdir(f.directory)).toEqual([f.args.filename]); + }); + + it.each(["replace", "symlink"])("retains a foreign %s temporary file without publishing or deleting it", async mode => { + const f = await fixture(); + const original = await vi.importActual("node:fs/promises"); + let temporary = ""; + vi.mocked(open).mockImplementation((async (path, flags, fileMode) => { + const handle = await original.open(path, flags, fileMode); + if (String(path).startsWith(`${f.directory}/`) && typeof flags === "number" && (flags & constants.O_EXCL) !== 0) { + temporary = String(path); const sync = handle.sync.bind(handle); + vi.spyOn(handle, "sync").mockImplementation(async () => { + await sync(); await rename(temporary, join(f.root, "retained-own-temporary")); + if (mode === "replace") await writeFile(temporary, "foreign temporary", { mode: 0o600 }); + else { + const target = join(f.root, "foreign-temporary"); + await writeFile(target, "foreign temporary", { mode: 0o600 }); await symlink(target, temporary); + } + }); + } + return handle; + }) as typeof open); + await expect(stageCursorCloudArtifact(f.input)).rejects.toThrow("temporary ownership changed"); + expect(await readFile(temporary, "utf8")).toBe("foreign temporary"); + expect(await readFile(join(f.root, "retained-own-temporary"))).toEqual(f.bytes); + await expect(lstat(f.target)).rejects.toMatchObject({ code: "ENOENT" }); + if (mode === "symlink") expect((await lstat(temporary)).isSymbolicLink()).toBe(true); + }); + + it.each(["fresh", "existing"])("stages %s verified bytes with a contentRef relative to the artifact root", async state => { + const root = await mkdtemp("/tmp/cc-artifact-"); roots.push(root); + const bytes = Buffer.from("downloaded provider result\n"); const sha256 = createHash("sha256").update(bytes).digest("hex"); + const client = { listArtifacts: vi.fn(async () => ({ items: [{ path: "artifacts/result.txt", sizeBytes: bytes.length, updatedAt: "2026-10-28" }] })), downloadArtifact: vi.fn(async () => bytes) }; + const args = { contentRef: "cursor-artifact:artifacts/result.txt", filename: "result.txt", byteSize: bytes.length, sha256, contentType: "text/plain" }; + const artifactRoot = join(root, "artifacts"); + const input = { arguments: args, agentId: "agent", runtimeDirectory: root, artifactRoot, client, signal: new AbortController().signal }; + if (state === "existing") await stageCursorCloudArtifact(input); + const normalized = await stageCursorCloudArtifact(input); + expect(normalized).toEqual({ ...args, contentRef: join(sha256, "result.txt") }); + expect(await readFile(join(artifactRoot, normalized.contentRef as string))).toEqual(bytes); + await expect(stageCursorCloudArtifact({ arguments: { ...args, sha256: "a".repeat(64) }, agentId: "agent", runtimeDirectory: root, artifactRoot: join(root, "artifacts"), client, signal: new AbortController().signal })).rejects.toThrow("do not match"); + }); + it("rejects host paths, traversal, unlisted paths, size mismatches and an unadmitted root", async () => { + const root = await mkdtemp("/tmp/cc-artifact-"); roots.push(root); + const client = { listArtifacts: vi.fn(async () => ({ items: [] })), downloadArtifact: vi.fn(async () => Buffer.from("not read")) }; + const input = { agentId: "agent", runtimeDirectory: root, artifactRoot: join(root, "artifacts"), client, signal: new AbortController().signal }; + for (const contentRef of ["/etc/passwd", "cursor-artifact:../outside", "cursor-artifact:artifacts/missing"]) { + await expect(stageCursorCloudArtifact({ ...input, arguments: { contentRef, filename: "file", byteSize: 1, sha256: "a".repeat(64) } })).rejects.toThrow(); + } + await expect(stageCursorCloudArtifact({ ...input, artifactRoot: root, arguments: { contentRef: "cursor-artifact:artifacts/file", filename: "file", byteSize: 1, sha256: "a".repeat(64) } })).rejects.toThrow("outside"); + expect(client.downloadArtifact).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.ts new file mode 100644 index 00000000000..973b7bdb7c9 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-delivery.ts @@ -0,0 +1,196 @@ +import { constants, type Stats } from "node:fs"; +import { link, lstat, mkdir, open, opendir, unlink, type FileHandle } from "node:fs/promises"; +import { isAbsolute, join, resolve } from "node:path"; +import type { CursorCloudClient } from "./cloud-client.js"; +import { createHash, randomUUID } from "node:crypto"; +import { reserveCursorCloudArtifactStaging } from "./artifact-staging-budget.js"; + +const artifactPublisherNonce = randomUUID(); +const activeArtifactAliases = new Set(); +const retainedOwnArtifactAliases = new Map(); +const uuidPattern = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"; +const artifactAliasPattern = new RegExp(`^\\.cursor-cloud-([a-f0-9]{64})-([1-9][0-9]*)-(${uuidPattern})-(${uuidPattern})\\.tmp$`); +const sameArtifactIdentity = (a: { dev: number; ino: number }, b: { dev: number; ino: number }) => a.dev === b.dev && a.ino === b.ino; +const privateArtifact = (stat: Stats) => stat.isFile() && (stat.mode & 0o077) === 0 && (!process.getuid || stat.uid === process.getuid()); + +function artifactPublisherIsDead(pid: number): boolean { + if (!Number.isSafeInteger(pid) || pid <= 0) return false; + try { process.kill(pid, 0); return false; } + catch (error) { return (error as NodeJS.ErrnoException).code === "ESRCH"; } +} + +async function readExactArtifact(handle: FileHandle, size: number): Promise { + const bytes = Buffer.allocUnsafe(size); + let offset = 0; + while (offset < size) { + const result = await handle.read(bytes, offset, size - offset, offset); + if (!result.bytesRead) throw new Error("Cursor Cloud artifact staging identity conflict"); + offset += result.bytesRead; + } + if ((await handle.read(Buffer.alloc(1), 0, 1, size)).bytesRead) throw new Error("Cursor Cloud artifact staging identity conflict"); + return bytes; +} + +async function verifyPublishedArtifact(target: string, bytes: Buffer, sha256: string): Promise { + const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + try { + const before = await handle.stat(); const pathBefore = await lstat(target); + if (!privateArtifact(before) || before.size !== bytes.length || !privateArtifact(pathBefore) || !sameArtifactIdentity(before, pathBefore) + || createHash("sha256").update(await readExactArtifact(handle, bytes.length)).digest("hex") !== sha256) throw new Error("Cursor Cloud artifact staging identity conflict"); + const after = await handle.stat(); const pathAfter = await lstat(target); + if (!privateArtifact(after) || after.size !== bytes.length || !privateArtifact(pathAfter) || !sameArtifactIdentity(before, after) + || !sameArtifactIdentity(after, pathAfter)) throw new Error("Cursor Cloud artifact staging identity conflict"); + return after; + } finally { await handle.close(); } +} + +async function recoverPublishedArtifactAliases(input: { + directory: string; target: string; filenameDigest: string; bytes: Buffer; sha256: string; signal: AbortSignal; +}): Promise { + input.signal.throwIfAborted(); + const final = await verifyPublishedArtifact(input.target, input.bytes, input.sha256); + if (final.nlink > 1) { + const names: string[] = []; + for await (const entry of await opendir(input.directory)) { + input.signal.throwIfAborted(); + if (names.length === 256) throw new Error("Cursor Cloud artifact publication recovery exceeds its directory bound"); + names.push(entry.name); + } + const aliases = names.map(name => ({ name, match: artifactAliasPattern.exec(name) })) + .filter(value => value.match?.[1] === input.filenameDigest); + if (aliases.length > 32) throw new Error("Cursor Cloud artifact publication recovery exceeds its alias bound"); + for (const { name, match } of aliases) { + input.signal.throwIfAborted(); + const alias = join(input.directory, name); const pid = Number(match![2]); + const own = retainedOwnArtifactAliases.get(alias); + const finishedOwn = pid === process.pid && match![3] === artifactPublisherNonce && own !== undefined; + if (activeArtifactAliases.has(alias) || (!finishedOwn && !artifactPublisherIsDead(pid))) continue; + const handle = await open(alias, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)).catch(error => { + if (["ENOENT", "ELOOP"].includes((error as NodeJS.ErrnoException).code ?? "")) return null; + throw error; + }); + if (!handle) continue; + try { + const held = await handle.stat(); const current = await lstat(alias).catch(error => { + if ((error as NodeJS.ErrnoException).code === "ENOENT") return null; + throw error; + }); + if (!current || !privateArtifact(held) || !privateArtifact(current) || held.size !== input.bytes.length + || !sameArtifactIdentity(held, final) || !sameArtifactIdentity(held, current) || (finishedOwn && !sameArtifactIdentity(held, own!))) continue; + input.signal.throwIfAborted(); + const target = await lstat(input.target); const aliasBefore = await lstat(alias).catch(error => { + if ((error as NodeJS.ErrnoException).code === "ENOENT") return null; + throw error; + }); + if (!aliasBefore) continue; + if (!privateArtifact(target) || !sameArtifactIdentity(target, final) || !privateArtifact(aliasBefore) + || !sameArtifactIdentity(aliasBefore, held)) throw new Error("Cursor Cloud artifact publication ownership changed"); + await unlink(alias).catch(error => { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; }); + if (finishedOwn) retainedOwnArtifactAliases.delete(alias); + } finally { await handle.close(); } + } + } + const verified = await verifyPublishedArtifact(input.target, input.bytes, input.sha256); + if (!sameArtifactIdentity(final, verified) || verified.nlink !== 1) throw new Error("Cursor Cloud artifact has unresolved publication aliases"); + return verified; +} + +export async function stageCursorCloudArtifact(input: { + arguments: unknown; + agentId: string; + runtimeDirectory: string; + artifactRoot: string; + client: Pick; + signal: AbortSignal; +}): Promise> { + if (!input.arguments || typeof input.arguments !== "object" || Array.isArray(input.arguments)) throw new Error("Cursor Cloud deliverable input must be an object"); + const args = input.arguments as Record; + if (typeof args.contentRef !== "string" || !args.contentRef.startsWith("cursor-artifact:")) throw new Error("Cursor Cloud deliverables require contentRef cursor-artifact:"); + const path = args.contentRef.slice("cursor-artifact:".length); + if (!path || path.startsWith("/") || /[\\\0\r\n]/.test(path) || path.split("/").some(part => !part || part === "." || part === "..")) throw new Error("Cursor Cloud artifact path must be a listed relative path"); + if (!Number.isSafeInteger(args.byteSize) || Number(args.byteSize) < 0 || Number(args.byteSize) > 16_777_216 || typeof args.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(args.sha256)) throw new Error("Cursor Cloud deliverables require exact byteSize and lowercase SHA-256"); + if (typeof args.filename !== "string" || !args.filename || args.filename.length > 255 || /[\x00-\x1f\x7f/\\]/.test(args.filename) || [".", ".."].includes(args.filename)) throw new Error("Cursor Cloud deliverable filename must be a single safe filename"); + if (!isAbsolute(input.artifactRoot) || resolve(input.artifactRoot) !== resolve(input.runtimeDirectory, "artifacts")) throw new Error("Cursor Cloud artifact root is outside its admitted session directory"); + const listed = await input.client.listArtifacts(input.agentId, { signal: input.signal }); + const artifact = listed.items.find(file => file.path === path); + if (!artifact || artifact.sizeBytes !== args.byteSize) throw new Error("Cursor Cloud artifact is absent or its reported byte size does not match the claim"); + input.signal.throwIfAborted(); + const directory = join(input.artifactRoot, args.sha256); + const contentRef = join(args.sha256, args.filename); + const target = join(directory, args.filename); + let cached: Buffer | null = null; + try { + for (const path of [input.artifactRoot, directory]) { + const stat = await lstat(path); + if (!stat.isDirectory() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0 || (process.getuid && stat.uid !== process.getuid())) throw new Error("Cursor Cloud artifact staging directory must be owned and private"); + } + const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + try { + const stat = await handle.stat(); + if (!privateArtifact(stat) || stat.size !== args.byteSize) throw new Error("Cursor Cloud artifact staging identity conflict"); + cached = await readExactArtifact(handle, Number(args.byteSize)); + const after = await handle.stat(), pathAfter = await lstat(target); + if (!privateArtifact(after) || !privateArtifact(pathAfter) || !sameArtifactIdentity(stat, after) + || !sameArtifactIdentity(after, pathAfter) || after.size !== args.byteSize || pathAfter.size !== args.byteSize + || cached.length !== args.byteSize) throw new Error("Cursor Cloud artifact staging identity conflict"); + await verifyPublishedArtifact(target, cached, args.sha256); + } finally { await handle.close(); } + } catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; } + if (!cached) await reserveCursorCloudArtifactStaging({ runtimeDirectory: input.runtimeDirectory, artifactRoot: input.artifactRoot, byteSize: Number(args.byteSize), signal: input.signal }); + const bytes = await input.client.downloadArtifact(input.agentId, path, { signal: input.signal, maxBytes: Math.max(1, Number(args.byteSize)) }); + if (bytes.length !== args.byteSize || createHash("sha256").update(bytes).digest("hex") !== args.sha256) throw new Error("Cursor Cloud artifact bytes do not match the claimed size/SHA-256"); + input.signal.throwIfAborted(); + if (!cached) { + for (const root of [input.artifactRoot, directory]) { + await mkdir(root, { recursive: true, mode: 0o700 }); + const stat = await lstat(root); + if (!stat.isDirectory() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0 || (process.getuid && stat.uid !== process.getuid())) throw new Error("Cursor Cloud artifact staging directory must be owned and private"); + } + } + const filenameDigest = createHash("sha256").update(args.filename).digest("hex"); + if (!cached) { + const temporary = join(directory, `.cursor-cloud-${filenameDigest}-${process.pid}-${artifactPublisherNonce}-${randomUUID()}.tmp`); + input.signal.throwIfAborted(); + const handle = await open(temporary, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600); + activeArtifactAliases.add(temporary); + try { + const held = await handle.stat(); + let published = false; + try { + await handle.writeFile(bytes); await handle.sync(); + const current = await lstat(temporary); + if (!current.isFile() || current.isSymbolicLink() || current.dev !== held.dev || current.ino !== held.ino || current.size !== bytes.length + || (current.mode & 0o077) !== 0 || (process.getuid && current.uid !== process.getuid())) throw new Error("Cursor Cloud artifact temporary ownership changed"); + input.signal.throwIfAborted(); + // A hard link publishes complete bytes without overwriting a concurrent final. + try { await link(temporary, target); published = true; } + catch (error) { + if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error; + await verifyPublishedArtifact(target, bytes, args.sha256); + } + } finally { + const current = await lstat(temporary); + if (!current.isFile() || current.isSymbolicLink() || current.dev !== held.dev || current.ino !== held.ino) throw new Error("Cursor Cloud artifact temporary ownership changed"); + await unlink(temporary).catch(async error => { + const retained = await lstat(temporary).catch(() => null); + if (published && retained && privateArtifact(retained) && sameArtifactIdentity(retained, held) && retained.nlink > 1) { + retainedOwnArtifactAliases.set(temporary, { dev: held.dev, ino: held.ino }); + } + throw error; + }); + } + } finally { + try { await handle.close(); } finally { activeArtifactAliases.delete(temporary); } + } + } + const published = await recoverPublishedArtifactAliases({ directory, target, filenameDigest, bytes, sha256: args.sha256, signal: input.signal }); + // EEXIST retries also finish durability after a prior post-publication failure. + for (const root of [directory, input.artifactRoot, input.runtimeDirectory]) { + const handle = await open(root, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0)); + try { await handle.sync(); } finally { await handle.close(); } + } + input.signal.throwIfAborted(); + const verified = await verifyPublishedArtifact(target, bytes, args.sha256); + if (!sameArtifactIdentity(published, verified) || verified.nlink !== 1) throw new Error("Cursor Cloud artifact publication ownership changed"); + return { ...args, contentRef }; +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.test.ts new file mode 100644 index 00000000000..81146e5a1d7 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.test.ts @@ -0,0 +1,227 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { spawn, type ChildProcess } from "node:child_process"; +import { chmod, link, lstat, mkdir, mkdtemp, open, readFile, readdir, rename, rm, symlink, writeFile } from "node:fs/promises"; +import { createRequire } from "node:module"; +import { dirname, join } from "node:path"; +import { fileURLToPath, pathToFileURL } from "node:url"; +import { CursorCloudCheckpointStore } from "./checkpoint.js"; +import { CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS, CURSOR_CLOUD_STAGING_MAX_BYTES, reserveCursorCloudArtifactStaging } from "./artifact-staging-budget.js"; + +vi.mock("node:fs/promises", async importOriginal => { + const original = await importOriginal(); + return { ...original, open: vi.fn(original.open) }; +}); + +const roots: string[] = []; +const children = new Set(); +afterEach(async () => { + vi.restoreAllMocks(); + await Promise.all([...children].map(child => child.exitCode !== null || child.signalCode !== null ? Promise.resolve() : new Promise(resolve => { + child.once("exit", () => resolve()); child.kill("SIGKILL"); + }))); + children.clear(); + for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); +}); +const MiB = 1_048_576; +const schema = "paperclip.cursor-cloud.artifact-budget.v1"; + +function deferred() { + let resolve!: () => void; + const promise = new Promise(done => { resolve = done; }); + return { promise, resolve }; +} + +async function fixture() { + const root = await mkdtemp("/tmp/cc-budget-"); roots.push(root); + const runtimeDirectory = join(root, "runtime"); await mkdir(runtimeDirectory, { mode: 0o700 }); + const artifactRoot = join(root, "artifacts"); + const directory = join(runtimeDirectory, ".artifact-staging-budget"); + const usage = join(directory, "usage.json"); + const store = new CursorCloudCheckpointStore(directory, "budget"); + const reserve = (byteSize: number, signal = new AbortController().signal) => reserveCursorCloudArtifactStaging({ runtimeDirectory, artifactRoot, byteSize, signal }); + const budget = async () => JSON.parse(await readFile(usage, "utf8")); + const seed = async (allocations: number, reservedBytes: number) => { + await reserve(0); await writeFile(usage, JSON.stringify({ schema, allocations, reservedBytes }), { mode: 0o600 }); + }; + return { root, runtimeDirectory, artifactRoot, directory, usage, store, reserve, budget, seed }; +} + +async function worker(f: Awaited>, byteSize: number) { + const workerRoot = await mkdtemp(join(f.root, "worker-")); + const script = join(workerRoot, "reserve.mjs"); + const source = pathToFileURL(join(dirname(fileURLToPath(import.meta.url)), "artifact-staging-budget.ts")).href; + const input = JSON.stringify({ runtimeDirectory: f.runtimeDirectory, artifactRoot: f.artifactRoot, byteSize }); + await writeFile(script, `import { reserveCursorCloudArtifactStaging } from ${JSON.stringify(source)}; +process.once('message', async () => { + try { await reserveCursorCloudArtifactStaging({ ...${input}, signal: new AbortController().signal }); process.send({ ok: true }); } + catch (error) { process.send({ ok: false, error: String(error) }); } + finally { process.disconnect(); } +}); +process.send({ ready: true }); +`, { mode: 0o600 }); + const loader = createRequire(import.meta.url).resolve("tsx"); + const child = spawn(process.execPath, ["--import", loader, script], { env: { PATH: process.env.PATH }, stdio: ["ignore", "pipe", "pipe", "ipc"] }); + children.add(child); let stderr = ""; child.stderr!.on("data", value => { stderr += value; }); + const ready = new Promise((resolve, reject) => { + child.once("error", reject); + child.on("message", value => { if ((value as { ready?: boolean }).ready) resolve(); }); + child.once("exit", code => { if (code !== 0) reject(new Error(`Worker exited ${code}: ${stderr}`)); }); + }); + const result = new Promise<{ ok: boolean; error?: string }>((resolve, reject) => { + child.on("message", value => { if (typeof (value as { ok?: boolean }).ok === "boolean") resolve(value as { ok: boolean; error?: string }); }); + child.once("error", reject); + child.once("exit", code => { if (code !== 0) reject(new Error(`Worker exited ${code}: ${stderr}`)); }); + }); + const exited = new Promise((resolve, reject) => child.once("exit", (code, signal) => { + children.delete(child); + if (code === 0 && signal === null) resolve(); else reject(new Error(`Worker exited ${code}/${signal}: ${stderr}`)); + })); + void result.catch(() => {}); void exited.catch(() => {}); + await ready; + return { run: async () => { child.send("reserve"); const value = await result; await exited; return value; } }; +} + +describe("Cursor Cloud persistent artifact staging budget", () => { + it("charges each allocation including zero bytes and releases ownership before returning", async () => { + expect(CURSOR_CLOUD_STAGING_MAX_BYTES).toBe(256 * MiB); + expect(CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS).toBe(256); + const f = await fixture(); await f.reserve(0); await f.reserve(7); + expect(await f.budget()).toEqual({ schema, allocations: 2, reservedBytes: 7 }); + expect((await lstat(f.usage)).mode & 0o077).toBe(0); + await expect(lstat(`${f.store.path}.lock`)).rejects.toMatchObject({ code: "ENOENT" }); + await expect(lstat(`${f.store.path}.lock.acquire`)).rejects.toMatchObject({ code: "ENOENT" }); + await f.store.acquire(); await f.store.release(); + }); + + it("serializes concurrent byte reservations at the exact aggregate limit", async () => { + const f = await fixture(); + const results = await Promise.allSettled(Array.from({ length: 19 }, () => f.reserve(16 * MiB))); + expect(results.filter(result => result.status === "fulfilled")).toHaveLength(16); + expect(await f.budget()).toEqual({ schema, allocations: 16, reservedBytes: 256 * MiB }); + await expect(f.reserve(1)).rejects.toThrow(); + await f.reserve(0); + expect(await f.budget()).toEqual({ schema, allocations: 17, reservedBytes: 256 * MiB }); + }); + + it("bounds concurrent zero-byte import attempts by allocation count", async () => { + const f = await fixture(); await f.seed(254, 9); + const results = await Promise.allSettled(Array.from({ length: 7 }, () => f.reserve(0))); + expect(results.filter(result => result.status === "fulfilled")).toHaveLength(2); + expect(await f.budget()).toEqual({ schema, allocations: 256, reservedBytes: 9 }); + const before = await readFile(f.usage, "utf8"); await expect(f.reserve(0)).rejects.toThrow(); + expect(await readFile(f.usage, "utf8")).toBe(before); + }); + + it.each(["allocation", "byte"])("prevents independent processes from reserving the last %s twice", async limit => { + const f = await fixture(); await f.seed(limit === "allocation" ? 255 : 0, limit === "allocation" ? 4 : 256 * MiB - 1); + const workers = await Promise.all(Array.from({ length: 4 }, () => worker(f, 1))); + const results = await Promise.all(workers.map(value => value.run())); + expect(results.filter(result => result.ok)).toHaveLength(1); + expect(await f.budget()).toEqual({ schema, allocations: limit === "allocation" ? 256 : 1, reservedBytes: limit === "allocation" ? 5 : 256 * MiB }); + await expect(f.reserve(limit === "allocation" ? 0 : 1)).rejects.toThrow(); + }, 10_000); + + it("retains charged reservations across independent process restarts", async () => { + const f = await fixture(); await f.reserve(3); + expect(await (await worker(f, 5)).run()).toEqual({ ok: true }); + expect(await (await worker(f, 7)).run()).toEqual({ ok: true }); + expect(await f.budget()).toEqual({ schema, allocations: 3, reservedBytes: 15 }); + }, 10_000); + + it("seeds existing private files and empty digest directories exactly once", async () => { + const f = await fixture(); await mkdir(f.artifactRoot, { mode: 0o700 }); + const populated = join(f.artifactRoot, "a".repeat(64)); const empty = join(f.artifactRoot, "b".repeat(64)); + await mkdir(populated, { mode: 0o700 }); await mkdir(empty, { mode: 0o700 }); + await writeFile(join(populated, "one.txt"), "123", { mode: 0o600 }); + await writeFile(join(populated, "empty.txt"), "", { mode: 0o600 }); + await f.reserve(4); expect(await f.budget()).toEqual({ schema, allocations: 4, reservedBytes: 7 }); + await f.reserve(2); expect(await f.budget()).toEqual({ schema, allocations: 5, reservedBytes: 9 }); + }); + + it("retains an abandoned staging reservation and refuses further imports", async () => { + const f = await fixture(); await f.reserve(0); const before = await readFile(f.usage, "utf8"); + const path = join(f.directory, "usage.pending.tmp"); const bytes = "ambiguous reservation"; + await writeFile(path, bytes, { mode: 0o600 }); const identity = await lstat(path); + await expect(f.reserve(1)).rejects.toThrow(); + expect(await readFile(path, "utf8")).toBe(bytes); expect(await readFile(f.usage, "utf8")).toBe(before); + const after = await lstat(path); expect([after.dev, after.ino, after.mode]).toEqual([identity.dev, identity.ino, identity.mode]); + }); + + it.each([-1, 0.5, NaN, Infinity, 16 * MiB + 1])("rejects invalid reservation size %s without changing the ledger", async byteSize => { + const f = await fixture(); await f.reserve(0); const before = await readFile(f.usage, "utf8"); + await expect(f.reserve(byteSize)).rejects.toThrow(); expect(await readFile(f.usage, "utf8")).toBe(before); + }); + + it.each(["{", JSON.stringify({ schema, allocations: -1, reservedBytes: 0 }), JSON.stringify({ schema, allocations: 257, reservedBytes: 0 }), JSON.stringify({ schema, allocations: 1, reservedBytes: 256 * MiB + 1 }), JSON.stringify({ schema, allocations: 0.5, reservedBytes: 0 }), JSON.stringify({ schema, allocations: 1, reservedBytes: 0, extra: true }), JSON.stringify({ schema: "foreign", allocations: 1, reservedBytes: 0 })])("preserves an unverifiable ledger (%s)", async bytes => { + const f = await fixture(); await f.reserve(0); await writeFile(f.usage, bytes); const before = await lstat(f.usage); + await expect(f.reserve(1)).rejects.toThrow(); expect(await readFile(f.usage, "utf8")).toBe(bytes); + const after = await lstat(f.usage); expect([after.dev, after.ino]).toEqual([before.dev, before.ino]); + }); + + it.each(["public", "symlink", "hardlink"])("preserves a %s ledger and its target", async mode => { + const f = await fixture(); await f.reserve(0); const before = await readFile(f.usage, "utf8"); const target = join(f.root, "foreign-ledger"); + if (mode === "public") await chmod(f.usage, 0o644); + if (mode === "symlink") { await rename(f.usage, target); await symlink(target, f.usage); } + if (mode === "hardlink") await link(f.usage, target); + const identity = await lstat(f.usage); await expect(f.reserve(1)).rejects.toThrow(); + expect(await readFile(f.usage, "utf8")).toBe(before); + const after = await lstat(f.usage); expect([after.dev, after.ino, after.mode, after.nlink]).toEqual([identity.dev, identity.ino, identity.mode, identity.nlink]); + if (mode !== "public") expect(await readFile(target, "utf8")).toBe(before); + }); + + it.each(["live-lock", "ambiguous-guard", "symlink-guard"])("refuses and preserves a foreign %s", async mode => { + const f = await fixture(); await f.reserve(0); const before = await readFile(f.usage, "utf8"); + const path = `${f.store.path}.lock${mode === "live-lock" ? "" : ".acquire"}`; + const bytes = mode === "ambiguous-guard" ? "{" : JSON.stringify({ pid: process.pid, token: "foreign-owner" }); + if (mode === "symlink-guard") { const target = join(f.root, "foreign-guard"); await writeFile(target, bytes, { mode: 0o600 }); await symlink(target, path); } + else await writeFile(path, bytes, { mode: 0o600 }); + const identity = await lstat(path); await expect(f.reserve(1)).rejects.toThrow(); + expect(await readFile(path, "utf8")).toBe(bytes); expect(await readFile(f.usage, "utf8")).toBe(before); + const after = await lstat(path); expect([after.dev, after.ino, after.mode]).toEqual([identity.dev, identity.ino, identity.mode]); + }); + + it.each(["write", "file-sync", "directory-sync", "parent-sync"])("cannot escape quota after a %s failure", async failure => { + const f = await fixture(); await f.seed(255, 256 * MiB - 1); const before = await readFile(f.usage, "utf8"); + const original = await vi.importActual("node:fs/promises"); let openedTemporary = false; let injected = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); const temporary = String(path) === join(f.directory, "usage.pending.tmp"); + if (temporary) openedTemporary = true; + const targetDirectory = failure === "directory-sync" ? f.directory : f.runtimeDirectory; + return new Proxy(handle, { get(target, key) { + if (!injected && temporary && key === (failure === "write" ? "writeFile" : failure === "file-sync" ? "sync" : "unused")) return async () => { + injected = true; if (failure === "write") await target.writeFile("{"); throw new Error(`fixture ${failure} failure`); + }; + if (!injected && openedTemporary && String(path) === targetDirectory && key === "sync" && ["directory-sync", "parent-sync"].includes(failure)) return async () => { injected = true; throw new Error(`fixture ${failure} failure`); }; + const value = Reflect.get(target, key, target); return typeof value === "function" ? value.bind(target) : value; + } }); + }) as typeof open); + await expect(f.reserve(1)).rejects.toThrow(`fixture ${failure} failure`); expect(injected).toBe(true); + vi.mocked(open).mockImplementation(original.open); + if (["write", "file-sync"].includes(failure)) { + expect(await readFile(f.usage, "utf8")).toBe(before); await f.reserve(1); + } + expect(await f.budget()).toEqual({ schema, allocations: 256, reservedBytes: 256 * MiB }); + await expect(f.reserve(0)).rejects.toThrow(); + expect((await readdir(f.directory)).filter(name => name.endsWith(".tmp"))).toEqual([]); + }); + + it("cancels a queued reservation without admitting it or releasing the active owner's quota", async () => { + const f = await fixture(); const entered = deferred(); const resume = deferred(); + const original = await vi.importActual("node:fs/promises"); let held = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + const handle = await original.open(path, flags, mode); + return new Proxy(handle, { get(target, key) { + if (!held && String(path) === join(f.directory, "usage.pending.tmp") && key === "writeFile") return async (...args: Parameters) => { + held = true; entered.resolve(); await resume.promise; return target.writeFile(...args); + }; + const value = Reflect.get(target, key, target); return typeof value === "function" ? value.bind(target) : value; + } }); + }) as typeof open); + const active = f.reserve(1); const abort = new AbortController(); + try { + await entered.promise; const cancelled = f.reserve(2, abort.signal); abort.abort(new Error("fixture queued cancellation")); + await expect(cancelled).rejects.toThrow("fixture queued cancellation"); resume.resolve(); await active; + await f.reserve(3); expect(await f.budget()).toEqual({ schema, allocations: 2, reservedBytes: 4 }); + } finally { resume.resolve(); await active.catch(() => {}); } + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.ts new file mode 100644 index 00000000000..4faf070ac59 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/artifact-staging-budget.ts @@ -0,0 +1,121 @@ +import { constants, type Stats } from "node:fs"; +import { lstat, open, opendir, rename, unlink } from "node:fs/promises"; +import { join } from "node:path"; +import { CursorCloudCheckpointStore } from "./checkpoint.js"; + +export const CURSOR_CLOUD_STAGING_MAX_BYTES = 268_435_456; +export const CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS = 256; +const queues = new Map>(); +type Budget = { schema: "paperclip.cursor-cloud.artifact-budget.v1"; allocations: number; reservedBytes: number }; +const denied = () => new Error("Cursor Cloud artifact staging budget is exhausted or cannot be verified"); +const same = (a: Stats, b: Stats) => a.dev === b.dev && a.ino === b.ino; +const privateEntry = (value: Stats) => (value.mode & 0o077) === 0 && (!process.getuid || value.uid === process.getuid()); +async function present(path: string): Promise { + try { return await lstat(path); } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return null; throw error; } +} +async function privateDirectory(path: string): Promise { + const value = await lstat(path); + if (!value.isDirectory() || value.isSymbolicLink() || !privateEntry(value)) throw denied(); + return value; +} +async function seedBudget(artifactRoot: string): Promise { + const result: Budget = { schema: "paperclip.cursor-cloud.artifact-budget.v1", allocations: 0, reservedBytes: 0 }; + const root = await present(artifactRoot); + if (!root) return result; + await privateDirectory(artifactRoot); + let directories = 0; + for await (const entry of await opendir(artifactRoot)) { + if (++directories > CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS || !/^[a-f0-9]{64}$/.test(entry.name)) throw denied(); + const path = join(artifactRoot, entry.name), before = await privateDirectory(path); + let count = 0; + for await (const file of await opendir(path)) { + if (++result.allocations > CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS) throw denied(); + const value = await lstat(join(path, file.name)); + if (!value.isFile() || value.isSymbolicLink() || !privateEntry(value) || value.size > 16_777_216) throw denied(); + result.reservedBytes += value.size; count++; + if (result.reservedBytes > CURSOR_CLOUD_STAGING_MAX_BYTES) throw denied(); + } + if (!count && ++result.allocations > CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS) throw denied(); + if (!same(before, await privateDirectory(path))) throw denied(); + } + if (!same(root, await privateDirectory(artifactRoot))) throw denied(); + return result; +} +async function readBudget(path: string, artifactRoot: string): Promise<{ budget: Budget; identity: Stats | null }> { + let handle; + try { handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW); } + catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return { budget: await seedBudget(artifactRoot), identity: null }; throw error; } + try { + const before = await handle.stat(); + if (!before.isFile() || before.nlink !== 1 || !privateEntry(before) || before.size > 1_024) throw denied(); + const value = JSON.parse(await handle.readFile("utf8")) as Budget; + const after = await lstat(path); + if (!same(before, after) || !after.isFile() || !privateEntry(after) || after.nlink !== 1 + || value?.schema !== "paperclip.cursor-cloud.artifact-budget.v1" + || Object.keys(value).sort().join(",") !== "allocations,reservedBytes,schema" + || !Number.isSafeInteger(value.allocations) || value.allocations < 0 || value.allocations > CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS + || !Number.isSafeInteger(value.reservedBytes) || value.reservedBytes < 0 || value.reservedBytes > CURSOR_CLOUD_STAGING_MAX_BYTES) throw denied(); + return { budget: value, identity: before }; + } finally { await handle.close(); } +} +async function saveBudget(directory: string, path: string, before: Stats | null, value: Budget): Promise { + const temporary = join(directory, "usage.pending.tmp"); + const handle = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600); + let owned: Stats | undefined; + try { + owned = await handle.stat(); + await handle.writeFile(JSON.stringify(value)); await handle.sync(); + const current = await present(path), temp = await lstat(temporary); + if ((before ? !current || !same(before, current) || !current.isFile() || !privateEntry(current) || current.nlink !== 1 : current !== null) + || !same(owned, temp) || !temp.isFile() || !privateEntry(temp) || temp.nlink !== 1) throw denied(); + await rename(temporary, path); + const directoryHandle = await open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW); + try { await directoryHandle.sync(); } finally { await directoryHandle.close(); } + } finally { + await handle.close(); + const current = await present(temporary); + if (current) { + if (!owned || !same(owned, current) || !current.isFile() || !privateEntry(current) || current.nlink !== 1) throw denied(); + await unlink(temporary); + } + } +} + +export async function reserveCursorCloudArtifactStaging(input: { + runtimeDirectory: string; artifactRoot: string; byteSize: number; signal: AbortSignal; +}): Promise { + input.signal.throwIfAborted(); + if (!Number.isSafeInteger(input.byteSize) || input.byteSize < 0 || input.byteSize > 16_777_216) throw denied(); + const preceding = queues.get(input.runtimeDirectory) ?? Promise.resolve(); + let release!: () => void; + const held = new Promise(resolve => { release = resolve; }); + const queued = preceding.then(() => held); + queues.set(input.runtimeDirectory, queued); + let abort!: () => void; + const cancelled = new Promise((_resolve, reject) => { + abort = () => reject(input.signal.reason ?? new Error("Cursor Cloud artifact staging cancelled")); + input.signal.addEventListener("abort", abort, { once: true }); + }); + try { + await Promise.race([preceding, cancelled]); input.signal.throwIfAborted(); + await privateDirectory(input.runtimeDirectory); + const directory = join(input.runtimeDirectory, ".artifact-staging-budget"); + const lock = new CursorCloudCheckpointStore(directory, "budget"); + await lock.acquire(); + try { + input.signal.throwIfAborted(); + const path = join(directory, "usage.json"), prior = await readBudget(path, input.artifactRoot); + if (prior.budget.allocations >= CURSOR_CLOUD_STAGING_MAX_ALLOCATIONS + || prior.budget.reservedBytes + input.byteSize > CURSOR_CLOUD_STAGING_MAX_BYTES) throw denied(); + const next = { ...prior.budget, allocations: prior.budget.allocations + 1, reservedBytes: prior.budget.reservedBytes + input.byteSize }; + input.signal.throwIfAborted(); + await saveBudget(directory, path, prior.identity, next); + const root = await open(input.runtimeDirectory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW); + try { await root.sync(); } finally { await root.close(); } + input.signal.throwIfAborted(); + } finally { await lock.release(); } + } finally { + input.signal.removeEventListener("abort", abort); release(); + void queued.then(() => { if (queues.get(input.runtimeDirectory) === queued) queues.delete(input.runtimeDirectory); }); + } +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint-archive.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint-archive.test.ts new file mode 100644 index 00000000000..ff8ec393449 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint-archive.test.ts @@ -0,0 +1,290 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { spawnSync } from "node:child_process"; +import { lstat, mkdtemp, mkdir, open, readFile, readdir, rename, rm, symlink, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { semanticCanonicalJson } from "../semantic-tool-receipt.js"; +import { archiveCursorCloudSessionCheckpoint, CursorCloudCheckpointStore, cursorCloudDigest, type CursorCloudCheckpoint } from "./checkpoint.js"; + +vi.mock("node:fs/promises", async importOriginal => { + const original = await importOriginal(); + return { ...original, lstat: vi.fn(original.lstat), open: vi.fn(original.open) }; +}); + +const roots: string[] = []; +afterEach(async () => { vi.restoreAllMocks(); for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); }); +const binding = { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId: "session" }; + +function deferred() { + let resolve!: () => void; + const promise = new Promise(done => { resolve = done; }); + return { promise, resolve }; +} + +function deadOwner() { + const child = spawnSync(process.execPath, ["--input-type=module", "-e", ""], { env: {}, stdio: "ignore" }); + expect(child.status).toBe(0); + expect(() => process.kill(child.pid, 0)).toThrowError(expect.objectContaining({ code: "ESRCH" })); + return { pid: child.pid, token: "dead-owner" }; +} + +async function fixture(phase: "idle" | "terminal" = "terminal") { + const root = await mkdtemp("/tmp/cc-archive-"); roots.push(root); + const runtimeDirectory = join(root, "cursor-cloud"); + const store = new CursorCloudCheckpointStore(runtimeDirectory, "session"); + await store.acquire(); + const checkpoint: CursorCloudCheckpoint = { schema: "paperclip.cursor-cloud.checkpoint.v1", driverSessionId: "session", normalizedSessionId: "session", + bindingDigest: cursorCloudDigest(semanticCanonicalJson(binding)), configDigest: "a".repeat(64), modelDigest: "b".repeat(64), instructionsDigest: "c".repeat(64), + instructionsRevisionPending: false, relayTurnToken: null, ownerRunId: "owner", agentId: phase === "terminal" ? "bc-provider" : null, + runId: phase === "terminal" ? "run-provider" : null, turnId: phase === "terminal" ? "turn-provider" : null, + phase, pendingOperation: null, idempotencyKey: null, requestedAgentId: null, requestDigest: null, lastEventId: phase === "terminal" ? "opaque" : null, lastEventFingerprints: [], + sourceSequence: phase === "terminal" ? 1 : 0, terminalStatus: phase === "terminal" ? "ERROR" : null, deadlineAt: null, pendingTerminalDelivery: null, acceptedCompletion: null }; + await store.write(checkpoint); await store.release(); + const input = { runtimeDirectory, driverSessionId: "session", ownerRunId: "owner", binding, socketPath: join(root, "mcp.sock"), archiveDirectory: join(root, "continuity-break", "cursor-cloud") }; + return { root, store, checkpoint, input }; +} + +describe("Cursor Cloud checkpoint ownership", () => { + it.each(["", 123, "a".repeat(42), "a".repeat(44), "!".repeat(43)])("rejects malformed persisted turn capabilities (%s)", async token => { + const f = await fixture(); + await f.store.acquire(); + try { + await writeFile(f.store.path, JSON.stringify({ ...f.checkpoint, relayTurnToken: token }), { mode: 0o600 }); + await expect(f.store.read()).rejects.toThrow("Invalid Cursor Cloud checkpoint"); + } finally { await f.store.release(); } + }); + + + it("does not let a delayed dead-owner contender unlink its successor's lock", async () => { + const f = await fixture(); + const lockPath = `${f.store.path}.lock`; + await writeFile(lockPath, JSON.stringify(deadOwner()), { mode: 0o600 }); + const original = await vi.importActual("node:fs/promises"); + const firstChecked = deferred(); const secondChecked = deferred(); + const resumeFirst = deferred(); const resumeSecond = deferred(); + let lockReads = 0; + vi.mocked(lstat).mockImplementation((async (path: Parameters[0], options: Parameters[1]) => { + const stat = await original.lstat(path, options); + if (String(path) === lockPath) { + const read = ++lockReads; + if (read === 2) { firstChecked.resolve(); await resumeFirst.promise; } + if (read === 4) { secondChecked.resolve(); await resumeSecond.promise; } + } + return stat; + }) as typeof lstat); + const first = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + const second = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + const firstResult = first.acquire(); + let secondResult: Promise<{ acquired: boolean; error?: unknown }> | undefined; + try { + await firstChecked.promise; + secondResult = second.acquire().then(() => ({ acquired: true }), error => ({ acquired: false, error })); + await Promise.race([secondChecked.promise, secondResult]); + resumeFirst.resolve(); await firstResult; + const firstLock = await readFile(lockPath, "utf8"); + resumeSecond.resolve(); + expect(await secondResult).toMatchObject({ acquired: false, error: expect.objectContaining({ message: "Cursor Cloud checkpoint acquisition is in progress or ambiguous" }) }); + expect(await readFile(lockPath, "utf8")).toBe(firstLock); + await first.write({ ...f.checkpoint, sourceSequence: 2 }); + expect((await first.read())?.sourceSequence).toBe(2); + } finally { + resumeFirst.resolve(); resumeSecond.resolve(); + await firstResult.catch(() => {}); await secondResult; + await first.release().catch(() => {}); await second.release().catch(() => {}); + } + }); + + it.each(["live", "dead", "corrupt", "symlink"])("preserves a %s acquisition guard and refuses takeover and archival", async mode => { + const f = await fixture(); + const lockPath = `${f.store.path}.lock`; + const guardPath = `${lockPath}.acquire`; + const lockBytes = JSON.stringify(deadOwner()); + await writeFile(lockPath, lockBytes, { mode: 0o600 }); + const guardBytes = mode === "corrupt" ? "{" : JSON.stringify(mode === "dead" ? deadOwner() : { pid: process.pid, token: "other-acquirer" }); + if (mode === "symlink") { + const target = join(f.root, "retained-acquirer"); + await writeFile(target, guardBytes, { mode: 0o600 }); await symlink(target, guardPath); + } else await writeFile(guardPath, guardBytes, { mode: 0o600 }); + const checkpointBytes = await readFile(f.store.path, "utf8"); + const contender = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + try { + await expect(contender.acquire()).rejects.toThrow("acquisition"); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("acquisition"); + expect(await readFile(lockPath, "utf8")).toBe(lockBytes); + expect(await readFile(guardPath, "utf8")).toBe(guardBytes); + expect(await readFile(f.store.path, "utf8")).toBe(checkpointBytes); + await expect(readdir(f.input.archiveDirectory)).rejects.toMatchObject({ code: "ENOENT" }); + if (mode === "symlink") expect((await lstat(guardPath)).isSymbolicLink()).toBe(true); + } finally { await contender.release().catch(() => {}); } + }); + + it("automatically recovers a dead main owner and retains exclusive checkpoint and archive ownership", async () => { + const f = await fixture(); const lockPath = `${f.store.path}.lock`; + await writeFile(lockPath, JSON.stringify(deadOwner()), { mode: 0o600 }); + const recovered = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + await recovered.acquire(); + try { + expect(recovered.recoveredDeadOwner).toBe(true); + expect(await recovered.read()).toEqual(f.checkpoint); + const lockBytes = await readFile(lockPath, "utf8"); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("live owner"); + expect(await readFile(lockPath, "utf8")).toBe(lockBytes); + await expect(lstat(`${lockPath}.acquire`)).rejects.toMatchObject({ code: "ENOENT" }); + } finally { await recovered.release(); } + await writeFile(lockPath, JSON.stringify(deadOwner()), { mode: 0o600 }); + await archiveCursorCloudSessionCheckpoint(f.input); + expect(JSON.parse(await readFile(join(f.input.archiveDirectory, f.store.path.split("/").at(-1)!), "utf8"))).toEqual(f.checkpoint); + await expect(lstat(lockPath)).rejects.toMatchObject({ code: "ENOENT" }); + await expect(lstat(`${lockPath}.acquire`)).rejects.toMatchObject({ code: "ENOENT" }); + }); + + it("cleans its own acquisition guard when main-lock acquisition fails", async () => { + const f = await fixture(); const lockPath = `${f.store.path}.lock`; + const original = await vi.importActual("node:fs/promises"); + let failed = false; + vi.mocked(open).mockImplementation((async (path, flags, mode) => { + if (String(path) === lockPath && flags === "wx" && !failed) { + failed = true; throw Object.assign(new Error("fixture main-lock failure"), { code: "EACCES" }); + } + return original.open(path, flags, mode); + }) as typeof open); + const contender = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + await expect(contender.acquire()).rejects.toThrow(); + await expect(lstat(`${lockPath}.acquire`)).rejects.toMatchObject({ code: "ENOENT" }); + expect(await contender.read()).toEqual(f.checkpoint); + await contender.acquire(); await contender.release(); + await expect(lstat(lockPath)).rejects.toMatchObject({ code: "ENOENT" }); + }); + + it.each(["replace", "rewrite", "symlink"])("does not delete an acquisition guard after %s tampering", async mode => { + const f = await fixture(); const lockPath = `${f.store.path}.lock`; const guardPath = `${lockPath}.acquire`; + const original = await vi.importActual("node:fs/promises"); + const guardBytes = JSON.stringify({ pid: process.pid, token: "replacement-acquirer" }); + vi.mocked(open).mockImplementation((async (path, flags, fileMode) => { + if (String(path) === lockPath && flags === "wx") { + if (mode !== "rewrite") await rm(guardPath); + if (mode === "symlink") { + const target = join(f.root, "replacement-acquirer"); + await writeFile(target, guardBytes, { mode: 0o600 }); await symlink(target, guardPath); + } else await writeFile(guardPath, guardBytes, { mode: 0o600 }); + } + return original.open(path, flags, fileMode); + }) as typeof open); + const contender = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + await expect(contender.acquire()).rejects.toThrow("acquisition ownership changed"); + expect(await readFile(guardPath, "utf8")).toBe(guardBytes); + expect(await contender.read()).toEqual(f.checkpoint); + await contender.release(); + expect(await readFile(guardPath, "utf8")).toBe(guardBytes); + if (mode === "symlink") expect((await lstat(guardPath)).isSymbolicLink()).toBe(true); + }); + + it.each(["replace", "rewrite", "symlink"])("does not delete the main lock after %s tampering during release", async mode => { + const f = await fixture(); const lockPath = `${f.store.path}.lock`; + const contender = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); + await contender.acquire(); + const originalBytes = await readFile(lockPath, "utf8"); + const replacementBytes = mode === "rewrite" ? JSON.stringify({ pid: process.pid, token: "replacement-owner" }) : originalBytes; + if (mode === "replace") { + const replacementPath = `${lockPath}.replacement`; + await writeFile(replacementPath, replacementBytes, { flag: "wx", mode: 0o600 }); + const original = await lstat(lockPath), replacement = await lstat(replacementPath); + expect([replacement.dev, replacement.ino]).not.toEqual([original.dev, original.ino]); + await rename(replacementPath, lockPath); + } else { + if (mode !== "rewrite") await rm(lockPath); + if (mode === "symlink") { + const target = join(f.root, "replacement-owner"); + await writeFile(target, replacementBytes, { mode: 0o600 }); await symlink(target, lockPath); + } else await writeFile(lockPath, replacementBytes, { mode: 0o600 }); + } + await expect(contender.release()).rejects.toThrow(); + expect(await readFile(lockPath, "utf8")).toBe(replacementBytes); + expect(await contender.read()).toEqual(f.checkpoint); + await expect(lstat(`${lockPath}.acquire`)).rejects.toMatchObject({ code: "ENOENT" }); + if (mode === "symlink") expect((await lstat(lockPath)).isSymbolicLink()).toBe(true); + }); +}); + +describe("Cursor Cloud replacement checkpoint archive", () => { + it.each(["idle", "terminal"] as const)("archives only the exact %s checkpoint and preserves launch and artifact state", async phase => { + const f = await fixture(phase); + for (const name of ["config.json", "relay-capability.json"]) await writeFile(join(f.input.runtimeDirectory, name), name, { mode: 0o600 }); + await mkdir(join(f.input.runtimeDirectory, "artifacts"), { mode: 0o700 }); + await writeFile(join(f.input.runtimeDirectory, "artifacts", "result.txt"), "retained"); + const bytes = await readFile(f.store.path, "utf8"); + await archiveCursorCloudSessionCheckpoint(f.input); + expect(await readFile(join(f.input.archiveDirectory, f.store.path.split("/").at(-1)!), "utf8")).toBe(bytes); + expect((await readdir(f.input.runtimeDirectory)).sort()).toEqual(["artifacts", "config.json", "relay-capability.json"]); + for (const name of ["config.json", "relay-capability.json"]) expect(await readFile(join(f.input.runtimeDirectory, name), "utf8")).toBe(name); + expect(await readFile(join(f.input.runtimeDirectory, "artifacts", "result.txt"), "utf8")).toBe("retained"); + const next = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); await next.acquire(); + try { expect(await next.read()).toBeNull(); } finally { await next.release(); } + }); + + it.each(["requestedAgentId", "idempotencyKey", "requestDigest", "acceptedCompletion"] as const)("does not archive pristine-looking idle state with retained %s evidence", async field => { + const f = await fixture("idle"); + const checkpoint = { ...f.checkpoint, [field]: field === "acceptedCompletion" + ? { turnId: "turn", callIdDigest: "a".repeat(64), inputDigest: "b".repeat(64), resultDigest: "c".repeat(64) } : "retained" }; + const bytes = JSON.stringify(checkpoint); await writeFile(f.store.path, bytes); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("active, ambiguous or outside"); + expect(await readFile(f.store.path, "utf8")).toBe(bytes); + }); + + it.each(["outside", "inside", "dot-child"])("rejects an archive with %s containment", async mode => { + const f = await fixture(); + const bytes = await readFile(f.store.path, "utf8"); + const archiveDirectory = mode === "outside" ? `${f.root}-other` : join(f.input.runtimeDirectory, mode === "inside" ? "archive" : "..archive"); + await expect(archiveCursorCloudSessionCheckpoint({ ...f.input, archiveDirectory })).rejects.toThrow("inside the admitted session root"); + expect(await readFile(f.store.path, "utf8")).toBe(bytes); + }); + + it("preserves both files when the archive destination already exists", async () => { + const f = await fixture(); + await mkdir(f.input.archiveDirectory, { recursive: true, mode: 0o700 }); + const destination = join(f.input.archiveDirectory, f.store.path.split("/").at(-1)!); + await writeFile(destination, "Existing archive", { mode: 0o600 }); + const bytes = await readFile(f.store.path, "utf8"); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("archive already exists"); + expect(await readFile(f.store.path, "utf8")).toBe(bytes); + expect(await readFile(destination, "utf8")).toBe("Existing archive"); + }); + + it("preserves an unknown socket path without archiving its checkpoint", async () => { + const f = await fixture(); + await writeFile(f.input.socketPath, "Unknown owner", { mode: 0o600 }); + const bytes = await readFile(f.store.path, "utf8"); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("safe dead-owner recovery proof"); + expect(await readFile(f.store.path, "utf8")).toBe(bytes); + expect(await readFile(f.input.socketPath, "utf8")).toBe("Unknown owner"); + await expect(readdir(f.input.archiveDirectory)).rejects.toMatchObject({ code: "ENOENT" }); + }); + + it("does not grant replacement from a missing checkpoint", async () => { + const f = await fixture(); await rm(f.store.path); + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow("checkpoint is missing"); + await expect(readdir(f.input.archiveDirectory)).rejects.toMatchObject({ code: "ENOENT" }); + }); + + it.each(["creating", "running", "stopping", "pending-create", "terminal-debt", "deadline", "foreign-owner", "foreign-binding", "foreign-session", "nonpristine-idle", "corrupt", "live-owner", "symlink"])("retains the exact checkpoint on %s refusal", async mode => { + const f = await fixture(); + const checkpoint = { ...f.checkpoint }; + if (["creating", "running", "stopping"].includes(mode)) checkpoint.phase = mode as CursorCloudCheckpoint["phase"]; + if (mode === "pending-create") checkpoint.pendingOperation = "create_run"; + if (mode === "terminal-debt") checkpoint.pendingTerminalDelivery = { schema: "paperclip.cursor-cloud.terminal-delivery.v1", threadId: "session", turnId: "turn-provider", providerRunId: "run-provider", receiptId: "11111111-1111-4111-8111-111111111111", status: "ERROR", interrupted: false, result: null }; + if (mode === "nonpristine-idle") Object.assign(checkpoint, { phase: "idle", agentId: null, runId: null, turnId: null, terminalStatus: null }); + if (mode === "deadline") checkpoint.deadlineAt = Date.now() + 60_000; + if (mode === "foreign-owner") checkpoint.ownerRunId = "other-owner"; + if (mode === "foreign-binding") checkpoint.bindingDigest = "f".repeat(64); + if (mode === "foreign-session") checkpoint.normalizedSessionId = "other-session"; + await writeFile(f.store.path, mode === "corrupt" ? "{" : JSON.stringify(checkpoint), { mode: 0o600 }); + let held: CursorCloudCheckpointStore | undefined; + if (mode === "live-owner") { held = new CursorCloudCheckpointStore(f.input.runtimeDirectory, "session"); await held.acquire(); } + if (mode === "symlink") { const moved = join(f.root, "retained.json"); await writeFile(moved, JSON.stringify(checkpoint)); await rm(f.store.path); await symlink(moved, f.store.path); } + const bytes = await readFile(f.store.path, "utf8"); + try { + await expect(archiveCursorCloudSessionCheckpoint(f.input)).rejects.toThrow(); + expect(await readFile(f.store.path, "utf8")).toBe(bytes); + await expect(readdir(f.input.archiveDirectory)).rejects.toMatchObject({ code: "ENOENT" }); + } finally { await held?.release(); } + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint.ts new file mode 100644 index 00000000000..607b91042ed --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/checkpoint.ts @@ -0,0 +1,249 @@ +import { createHash, randomUUID } from "node:crypto"; +import { constants } from "node:fs"; +import { lstat, mkdir, open, readFile, rename, unlink } from "node:fs/promises"; +import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path"; +import { semanticCanonicalJson } from "../semantic-tool-receipt.js"; +import { parseCursorCloudBinding, type CursorCloudBinding } from "./config.js"; +import { releaseCursorCloudStaleSocket } from "./stale-socket.js"; + +export const cursorCloudDigest = (value: string) => createHash("sha256").update(value).digest("hex"); + +export interface CursorCloudTerminalDelivery { + schema: "paperclip.cursor-cloud.terminal-delivery.v1"; + threadId: string; + turnId: string; + providerRunId: string; + receiptId: string; + status: "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED"; + interrupted: boolean; + result: string | null; +} + +export interface CursorCloudCheckpoint { + schema: "paperclip.cursor-cloud.checkpoint.v1"; + driverSessionId: string; + normalizedSessionId: string; + bindingDigest: string; + configDigest: string; + modelDigest: string; + instructionsDigest: string; + instructionsRevisionPending: boolean; + ownerRunId: string; + agentId: string | null; + runId: string | null; + turnId: string | null; + relayTurnToken?: string | null; + phase: "idle" | "creating" | "running" | "stopping" | "terminal"; + pendingOperation: "create_agent" | "create_run" | null; + idempotencyKey: string | null; + requestedAgentId: string | null; + requestDigest: string | null; + lastEventId: string | null; + lastEventFingerprints: string[]; + sourceSequence: number; + terminalStatus: string | null; + deadlineAt: number | null; + pendingTerminalDelivery: CursorCloudTerminalDelivery | null; + acceptedCompletion: { callIdDigest: string; inputDigest: string; resultDigest: string; turnId: string } | null; +} + +export class CursorCloudCheckpointStore { + readonly path: string; + readonly #lockPath: string; + readonly #root: string; + #lockToken: string | null = null; + #lockIdentity: { dev: number; ino: number } | null = null; + recoveredDeadOwner = false; + #writes: Promise = Promise.resolve(); + + constructor(root: string, sessionId: string) { + if (!isAbsolute(root) || !sessionId || sessionId.length > 1_024) throw new Error("Cursor Cloud checkpoint requires a private absolute directory and session identity"); + this.#root = root; + this.path = join(root, `checkpoint-${cursorCloudDigest(sessionId)}.json`); + this.#lockPath = `${this.path}.lock`; + } + + async acquire(): Promise { + await mkdir(this.#root, { recursive: true, mode: 0o700 }); + const root = await lstat(this.#root); + if (!root.isDirectory() || root.isSymbolicLink() || (root.mode & 0o077) !== 0 || (process.getuid && root.uid !== process.getuid())) throw new Error("Cursor Cloud runtime directory must be owned and private (0700)"); + const token = randomUUID(); + const guardPath = `${this.#lockPath}.acquire`; + let guard; + try { guard = await open(guardPath, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600); } + catch (error) { + if ((error as NodeJS.ErrnoException).code === "EEXIST" || (error as NodeJS.ErrnoException).code === "ELOOP") throw new Error("Cursor Cloud checkpoint acquisition is in progress or ambiguous"); + throw error; + } + try { + const held = await guard.stat(); + await guard.writeFile(JSON.stringify({ pid: process.pid, token })); await guard.sync(); + try { + // Serialize the complete stale-lock decision and replacement, not just unlink. + // An abandoned guard is uncertainty: never recursively take over another guard. + for (let attempt = 0; attempt < 2; attempt += 1) { + try { + const handle = await open(this.#lockPath, "wx", 0o600); + let identity; + try { identity = await handle.stat(); await handle.writeFile(JSON.stringify({ pid: process.pid, token })); await handle.sync(); } + finally { await handle.close(); } + this.#lockIdentity = { dev: identity.dev, ino: identity.ino }; + this.#lockToken = token; + return; + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== "EEXIST" || attempt !== 0) throw new Error("Cursor Cloud session already has an owner"); + const before = await lstat(this.#lockPath); + if (!before.isFile() || before.isSymbolicLink() || (before.mode & 0o077) !== 0) throw new Error("Cursor Cloud checkpoint ownership is unsafe"); + let owner: { pid?: unknown }; + try { owner = JSON.parse(await readFile(this.#lockPath, "utf8")); } + catch { throw new Error("Cursor Cloud checkpoint owner is unknown"); } + if (!Number.isSafeInteger(owner.pid) || Number(owner.pid) <= 0) throw new Error("Cursor Cloud checkpoint owner is unknown"); + try { process.kill(Number(owner.pid), 0); throw new Error("Cursor Cloud session already has a live owner"); } + catch (cause) { if ((cause as NodeJS.ErrnoException).code !== "ESRCH") throw cause; } + const current = await lstat(this.#lockPath); + if (current.ino !== before.ino || current.dev !== before.dev) throw new Error("Cursor Cloud checkpoint owner changed"); + await unlink(this.#lockPath); + this.recoveredDeadOwner = true; + } + } + } finally { + let current; + try { + current = await open(guardPath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + const stat = await current.stat(); + if (!stat.isFile() || stat.dev !== held.dev || stat.ino !== held.ino || (stat.mode & 0o077) !== 0 + || (process.getuid && stat.uid !== process.getuid()) || stat.size > 1_024) throw new Error("Cursor Cloud checkpoint acquisition ownership changed"); + const owner = JSON.parse(await current.readFile("utf8")); + if (owner.pid !== process.pid || owner.token !== token) throw new Error("Cursor Cloud checkpoint acquisition ownership changed"); + } catch { throw new Error("Cursor Cloud checkpoint acquisition ownership changed"); } + finally { await current?.close(); } + await unlink(guardPath); + } + } finally { await guard.close(); } + } + + async read(): Promise { + let handle; + try { handle = await open(this.path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); } + catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return null; throw error; } + try { + const stat = await handle.stat(); + if (!stat.isFile() || (stat.mode & 0o077) !== 0 || stat.size > 524_288) throw new Error("Cursor Cloud checkpoint is unsafe or exceeds its bound"); + const value: unknown = JSON.parse(await handle.readFile("utf8")); + if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid Cursor Cloud checkpoint"); + const cp = value as CursorCloudCheckpoint; + if (cp.deadlineAt === undefined) cp.deadlineAt = ["creating", "running", "stopping"].includes(cp.phase) ? 0 : null; + if (cp.pendingTerminalDelivery === undefined) cp.pendingTerminalDelivery = null; + if (cp.instructionsRevisionPending === undefined) cp.instructionsRevisionPending = false; + if (cp.relayTurnToken === undefined) cp.relayTurnToken = null; + const digestFields = [cp.bindingDigest, cp.configDigest, cp.modelDigest, cp.instructionsDigest]; + if (cp.schema !== "paperclip.cursor-cloud.checkpoint.v1" || !digestFields.every(v => typeof v === "string" && /^[a-f0-9]{64}$/.test(v)) + || !["idle", "creating", "running", "stopping", "terminal"].includes(cp.phase) + || !Number.isSafeInteger(cp.sourceSequence) || cp.sourceSequence < 0 + || typeof cp.instructionsRevisionPending !== "boolean" + || (cp.relayTurnToken !== null && (typeof cp.relayTurnToken !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(cp.relayTurnToken))) + || (cp.deadlineAt !== null && (!Number.isSafeInteger(cp.deadlineAt) || cp.deadlineAt < 0)) + || !Array.isArray(cp.lastEventFingerprints) || cp.lastEventFingerprints.length > 32 + || !cp.lastEventFingerprints.every(v => typeof v === "string" && /^[a-f0-9]{64}$/.test(v)) + || ![cp.driverSessionId, cp.normalizedSessionId, cp.ownerRunId].every(v => typeof v === "string" && v.length > 0 && v.length <= 1_024) + || ![cp.agentId, cp.runId, cp.turnId, cp.idempotencyKey, cp.requestedAgentId, cp.requestDigest, cp.lastEventId, cp.terminalStatus].every(v => v === null || (typeof v === "string" && v.length <= 1_024)) + || ![null, "create_agent", "create_run"].includes(cp.pendingOperation)) throw new Error("Invalid Cursor Cloud checkpoint"); + const pending = cp.pendingTerminalDelivery; + if (pending !== null && (typeof pending !== "object" || Array.isArray(pending) + || pending.schema !== "paperclip.cursor-cloud.terminal-delivery.v1" || pending.threadId !== cp.driverSessionId + || pending.turnId !== cp.turnId || pending.providerRunId !== cp.runId + || typeof pending.receiptId !== "string" || !/^[a-f0-9-]{36}$/.test(pending.receiptId) + || !["FINISHED", "ERROR", "CANCELLED", "EXPIRED"].includes(pending.status) + || typeof pending.interrupted !== "boolean" || (pending.result !== null && (typeof pending.result !== "string" || pending.result.length > 65_536)))) throw new Error("Invalid Cursor Cloud terminal delivery"); + return cp; + } finally { await handle.close(); } + } + + write(value: CursorCloudCheckpoint): Promise { + if (!this.#lockToken) return Promise.reject(new Error("Cursor Cloud checkpoint has no owner")); + const bytes = JSON.stringify(value); + if (Buffer.byteLength(bytes) > 524_288) return Promise.reject(new Error("Cursor Cloud checkpoint exceeds its bound")); + const operation = this.#writes.then(async () => { + const temporary = `${this.path}.${randomUUID()}.tmp`; + const handle = await open(temporary, "wx", 0o600); + try { await handle.writeFile(bytes); await handle.sync(); } + finally { await handle.close(); } + try { + await rename(temporary, this.path); + const directory = await open(this.#root, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0)); + try { await directory.sync(); } finally { await directory.close(); } + } finally { await unlink(temporary).catch(() => {}); } + }); + this.#writes = operation.catch(() => {}); + return operation; + } + + async release(): Promise { + await this.#writes; + if (!this.#lockToken || !this.#lockIdentity) return; + const handle = await open(this.#lockPath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + try { + const stat = await handle.stat(); + if (!stat.isFile() || stat.dev !== this.#lockIdentity.dev || stat.ino !== this.#lockIdentity.ino || (stat.mode & 0o077) !== 0 + || (process.getuid && stat.uid !== process.getuid()) || stat.size > 1_024) throw new Error("Cursor Cloud checkpoint ownership changed"); + const current = JSON.parse(await handle.readFile("utf8")); + if (current.token !== this.#lockToken || current.pid !== process.pid) throw new Error("Cursor Cloud checkpoint ownership changed"); + } finally { await handle.close(); } + await unlink(this.#lockPath); + this.#lockToken = null; + this.#lockIdentity = null; + } +} + +export async function archiveCursorCloudSessionCheckpoint(input: { + runtimeDirectory: string; + driverSessionId: string; + ownerRunId: string; + binding: CursorCloudBinding; + socketPath: string; + archiveDirectory: string; +}): Promise { + const binding = parseCursorCloudBinding(input.binding); + if (!input.ownerRunId || !isAbsolute(input.archiveDirectory) || !isAbsolute(input.socketPath)) throw new Error("Cursor Cloud replacement requires exact private bindings"); + const archiveDirectory = resolve(input.archiveDirectory); + const sessionRoot = dirname(resolve(input.runtimeDirectory)); + const archiveRelative = relative(sessionRoot, archiveDirectory); + const escapes = (path: string) => path === ".." || path.startsWith(`..${sep}`) || isAbsolute(path); + if (!archiveRelative || escapes(archiveRelative) || !escapes(relative(resolve(input.runtimeDirectory), archiveDirectory))) { + throw new Error("Cursor Cloud checkpoint archive must be separate state inside the admitted session root"); + } + const store = new CursorCloudCheckpointStore(input.runtimeDirectory, input.driverSessionId); + await store.acquire(); + try { + const checkpoint = await store.read(); + if (!checkpoint) throw new Error("Cursor Cloud replacement checkpoint is missing"); + const bound = checkpoint.driverSessionId === input.driverSessionId && checkpoint.normalizedSessionId === binding.normalizedSessionId + && checkpoint.ownerRunId === input.ownerRunId && checkpoint.bindingDigest === cursorCloudDigest(semanticCanonicalJson(binding)); + const pristine = checkpoint.phase === "idle" && checkpoint.agentId === null && checkpoint.runId === null && checkpoint.turnId === null && checkpoint.terminalStatus === null + && checkpoint.sourceSequence === 0 && checkpoint.lastEventId === null && checkpoint.lastEventFingerprints.length === 0 + && checkpoint.requestedAgentId === null && checkpoint.idempotencyKey === null && checkpoint.requestDigest === null && checkpoint.acceptedCompletion === null; + const terminal = checkpoint.phase === "terminal" && typeof checkpoint.agentId === "string" && checkpoint.agentId.length > 0 + && typeof checkpoint.runId === "string" && checkpoint.runId.length > 0 && typeof checkpoint.turnId === "string" && checkpoint.turnId.length > 0 + && ["FINISHED", "ERROR", "CANCELLED", "EXPIRED"].includes(checkpoint.terminalStatus ?? ""); + if (!bound || (!pristine && !terminal) || checkpoint.pendingOperation !== null || checkpoint.pendingTerminalDelivery !== null || checkpoint.deadlineAt !== null) { + throw new Error("Cursor Cloud replacement checkpoint is active, ambiguous or outside the admitted session"); + } + await releaseCursorCloudStaleSocket(input.socketPath, store.recoveredDeadOwner); + await mkdir(archiveDirectory, { recursive: true, mode: 0o700 }); + for (let directory = archiveDirectory; ; directory = dirname(directory)) { + const stat = await lstat(directory); + if (!stat.isDirectory() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0 || (process.getuid && stat.uid !== process.getuid())) throw new Error("Cursor Cloud checkpoint archive must be owned and private (0700)"); + const handle = await open(directory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0)); + try { await handle.sync(); } finally { await handle.close(); } + if (directory === sessionRoot) break; + } + const destination = join(archiveDirectory, basename(store.path)); + try { await lstat(destination); throw new Error("Cursor Cloud checkpoint archive already exists"); } + catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; } + await rename(store.path, destination); + for (const directory of [archiveDirectory, input.runtimeDirectory]) { + const handle = await open(directory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0)); + try { await handle.sync(); } finally { await handle.close(); } + } + } finally { await store.release(); } +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.test.ts new file mode 100644 index 00000000000..404986ecec0 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.test.ts @@ -0,0 +1,309 @@ +import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; +import { afterEach, describe, expect, it } from "vitest"; +import { + CursorCloudClient, + CursorCloudClientError, + isCursorCloudUnsentRequestError, + isCursorCloudRunActive, +} from "./cloud-client.js"; + +const AGENT = "bc-00000000-0000-0000-0000-000000000001"; +const RUN = "run-00000000-0000-0000-0000-000000000001"; +const OTHER_RUN = "run-00000000-0000-0000-0000-000000000002"; +const API_KEY = "cursor-provider-secret-canary"; +const TIME = "2026-10-28T16:00:00.000Z"; +const agent = { id: AGENT, status: "ACTIVE", env: { type: "cloud" }, url: `https://cursor.com/agents/${AGENT}`, createdAt: TIME, updatedAt: TIME }; +const run = { id: RUN, agentId: AGENT, status: "CREATING", createdAt: TIME, updatedAt: TIME }; +const cleanup: Array<() => Promise> = []; + +afterEach(async () => { await Promise.all(cleanup.splice(0).map(close => close())); }); + +async function serve(handler: (request: IncomingMessage, response: ServerResponse) => void | Promise) { + const server = createServer((request, response) => { + Promise.resolve(handler(request, response)).catch(() => { + if (!response.headersSent) response.writeHead(500); + response.end(); + }); + }); + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(0, "127.0.0.1", resolve); + }); + cleanup.push(async () => { + server.closeAllConnections(); + await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); + }); + const address = server.address(); + if (!address || typeof address === "string") throw new Error("No test server address"); + return `http://127.0.0.1:${address.port}`; +} + +function json(response: ServerResponse, value: unknown, status = 200) { + response.writeHead(status, { "Content-Type": "application/json" }); + response.end(JSON.stringify(value)); +} + +async function body(request: IncomingMessage): Promise { + const chunks: Buffer[] = []; + for await (const chunk of request) chunks.push(Buffer.from(chunk)); + return JSON.parse(Buffer.concat(chunks).toString("utf8")); +} + +async function collect(source: AsyncIterable): Promise { + const result: T[] = []; + for await (const item of source) result.push(item); + return result; +} + +describe("Cursor Cloud v1 HTTP client", () => { + it("uses authenticated native paths and preserves exact model, MCP, and run-scoped environment payloads", async () => { + const requests: Array<{ path: string; method: string; authorization: string | undefined; key: string | undefined; body?: unknown }> = []; + const baseUrl = await serve(async (request, response) => { + const entry = { + path: request.url!, method: request.method!, authorization: request.headers.authorization, + key: request.headers["idempotency-key"] as string | undefined, + ...(["POST"].includes(request.method!) && !request.url?.endsWith("/cancel") ? { body: await body(request) } : {}), + }; + requests.push(entry); + if (entry.path === "/v1/agents" && entry.method === "POST") return json(response, { agent, run }, 201); + if (entry.path === `/v1/agents/${AGENT}/runs` && entry.method === "POST") return json(response, { run: { ...run, id: OTHER_RUN } }, 201); + if (entry.path.endsWith("/cancel")) return json(response, { id: RUN }); + if (entry.path === `/v1/agents/${AGENT}` && entry.method === "DELETE") return json(response, { id: AGENT }); + if (entry.path === `/v1/agents/${AGENT}`) return json(response, agent); + if (entry.path === `/v1/agents/${AGENT}/runs/${RUN}`) return json(response, { ...run, status: "WAITING_FOR_BACKGROUND_WORK" }); + if (entry.path === "/v1/models") return json(response, { items: [{ id: "future-model/exact", displayName: "Future model" }] }); + if (entry.path.endsWith("/artifacts")) return json(response, { items: [{ path: "proof.json", sizeBytes: 32, updatedAt: TIME }] }); + json(response, {}, 404); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + const model = { id: "future-model/exact", params: [{ id: "thinking", value: "high" }] }; + const mcpServers = [{ name: "paperclip", type: "http" as const, url: "https://tools.example.test/mcp", headers: { Authorization: "Bearer run-secret" } }]; + expect(await client.createAgent({ prompt: { text: "Create the proof" }, model, repos: [], mcpServers }, { idempotencyKey: "initial-receipt" })).toEqual({ agent, run }); + await client.createRun(AGENT, { prompt: { text: "Continue" }, model, envVars: { PAPERCLIP_RUN_ID: "new-run" }, mcpServers }, { idempotencyKey: "followup-receipt" }); + expect((await client.getRun(AGENT, RUN)).status).toBe("WAITING_FOR_BACKGROUND_WORK"); + expect(await client.getAgent(AGENT)).toEqual(agent); + expect(await client.cancelRun(AGENT, RUN)).toEqual({ id: RUN }); + expect(await client.listModels()).toEqual({ items: [{ id: "future-model/exact", displayName: "Future model" }] }); + expect(await client.listArtifacts(AGENT)).toEqual({ items: [{ path: "proof.json", sizeBytes: 32, updatedAt: TIME }] }); + expect(await client.deleteAgent(AGENT)).toEqual({ id: AGENT }); + expect(requests.every(entry => entry.authorization === `Bearer ${API_KEY}`)).toBe(true); + expect(requests[0]).toMatchObject({ path: "/v1/agents", method: "POST", key: "initial-receipt", body: { prompt: { text: "Create the proof" }, model, repos: [], mcpServers } }); + expect(requests[1]).toMatchObject({ path: `/v1/agents/${AGENT}/runs`, key: "followup-receipt", body: { envVars: { PAPERCLIP_RUN_ID: "new-run" }, model, mcpServers } }); + expect(isCursorCloudRunActive("WAITING_FOR_BACKGROUND_WORK")).toBe(true); + expect(isCursorCloudRunActive("EXPIRED")).toBe(false); + }); + + it("retains safe HTTP metadata without echoing provider messages or retrying mutations", async () => { + let calls = 0; + const baseUrl = await serve((_request, response) => { + calls += 1; + response.setHeader("Retry-After", "2"); + json(response, { error: { code: "feature_unavailable", message: `Failure with ${API_KEY}`, token: API_KEY } }, 503); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + const error = await client.createAgent({ prompt: { text: "Do work" } }).catch(error => error); + expect(error).toBeInstanceOf(CursorCloudClientError); + expect(error).toMatchObject({ code: "http_error", status: 503, providerCode: "feature_unavailable", retryAfterMs: 2_000, retryable: true }); + expect(String(error)).not.toContain(API_KEY); + expect(JSON.stringify(error)).not.toContain(API_KEY); + expect(error.cause).toBeUndefined(); + expect(calls).toBe(1); + }); + + it("scopes token usage to the exact run and obtains an artifact URL without forwarding credentials to it", async () => { + const paths: string[] = []; + const usage = { inputTokens: 3, outputTokens: 2, cacheWriteTokens: 0, cacheReadTokens: 1, totalTokens: 6 }; + const baseUrl = await serve((request, response) => { + paths.push(request.url!); + if (request.url?.includes("/usage?")) return json(response, { totalUsage: usage, runs: [{ id: RUN, usage }] }); + if (request.url?.includes("/artifacts/download?")) return json(response, { url: "https://artifacts.example.test/proof?signature=private", expiresAt: TIME }); + json(response, { ...agent, status: "IDLE" }); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + expect(await client.getUsage(AGENT, { runId: RUN })).toEqual({ totalUsage: usage, runs: [{ id: RUN, usage }] }); + expect(await client.getArtifactDownloadUrl(AGENT, "artifacts/proof file.json")).toEqual({ url: "https://artifacts.example.test/proof?signature=private", expiresAt: TIME }); + expect((await client.getAgent(AGENT)).status).toBe("IDLE"); + expect(paths).toEqual([ + `/v1/agents/${AGENT}/usage?runId=${RUN}`, + `/v1/agents/${AGENT}/artifacts/download?path=artifacts%2Fproof+file.json`, + `/v1/agents/${AGENT}`, + ]); + }); + + it("downloads only the qualified artifact host with no provider credentials and bounded binary bytes", async () => { + const calls: Array<{ path: string; authorization?: string }> = []; + const bytes = Buffer.from([0, 255, 0, 8, 127]); + let host = "agent-stores.s3.us-east-1.amazonaws.com"; + const baseUrl = await serve((request, response) => { + calls.push({ path: request.url!, authorization: request.headers.authorization }); + if (request.url?.includes("/artifacts/download?")) return json(response, { url: `https://${host}/proof?private-signature`, expiresAt: TIME }); + response.end(bytes); + }); + const externalHeaders: HeadersInit[] = []; + let unexpectedTargets = 0; + const transport: typeof fetch = (input, init) => { + const url = String(input); + if (url.startsWith("https://agent-stores.s3.us-east-1.amazonaws.com/")) { + externalHeaders.push(init?.headers ?? {}); + expect(init?.redirect).toBe("error"); + return fetch(`${baseUrl}/download`, init); + } + if (url.startsWith("https://")) { unexpectedTargets += 1; return Promise.reject(new TypeError("Unqualified test target")); } + return fetch(input, init); + }; + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl, fetch: transport }); + expect(await client.downloadArtifact(AGENT, "proof.bin", { maxBytes: 5 })).toEqual(bytes); + expect(externalHeaders).toEqual([{}]); + expect(calls[0]?.authorization).toBe(`Bearer ${API_KEY}`); + expect(calls[1]?.authorization).toBeUndefined(); + const downloadError = await client.downloadArtifact(AGENT, "proof.bin", { maxBytes: 4 }).catch(error => error); + expect(downloadError).toMatchObject({ code: "payload_too_large" }); + expect(isCursorCloudUnsentRequestError(downloadError)).toBe(false); + const downloads = calls.filter(call => call.path === "/download").length; + host = "cloud-agent-artifacts.s3.us-east-1.amazonaws.com"; + await expect(client.downloadArtifact(AGENT, "proof.bin")).rejects.toMatchObject({ code: "invalid_response" }); + host = "127.0.0.1"; + await expect(client.downloadArtifact(AGENT, "proof.bin")).rejects.toMatchObject({ code: "invalid_response" }); + expect(calls.filter(call => call.path === "/download")).toHaveLength(downloads); + expect(unexpectedTargets).toBe(0); + await expect(client.downloadArtifact(AGENT, "../../escape")).rejects.toMatchObject({ code: "invalid_request" }); + }); + + it("rejects conflicting identities, unknown statuses, and secret-shaped error codes", async () => { + let attempt = 0; + const baseUrl = await serve((_request, response) => { + attempt += 1; + if (attempt === 1) return json(response, { ...run, id: OTHER_RUN }); + if (attempt === 2) return json(response, { ...run, status: "UNRECOGNIZED" }); + json(response, { code: API_KEY, message: API_KEY }, 400); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + await expect(client.getRun(AGENT, RUN)).rejects.toMatchObject({ code: "invalid_response" }); + await expect(client.getRun(AGENT, RUN)).rejects.toMatchObject({ code: "invalid_response" }); + const error = await client.getAgent(AGENT).catch(error => error); + expect(error.providerCode).toBeUndefined(); + expect(JSON.stringify(error)).not.toContain(API_KEY); + }); + + it("bounds request and JSON response bytes before preserving their contents", async () => { + let calls = 0; + const baseUrl = await serve((_request, response) => { calls += 1; json(response, { items: ["x".repeat(1_024)] }); }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl, maxRequestBytes: 100, maxResponseBytes: 100 }); + const requestError = await client.createAgent({ prompt: { text: "x".repeat(200) } }).catch(error => error); + expect(requestError).toMatchObject({ code: "payload_too_large" }); + expect(isCursorCloudUnsentRequestError(requestError)).toBe(true); + expect(calls).toBe(0); + const responseError = await client.listModels().catch(error => error); + expect(responseError).toMatchObject({ code: "payload_too_large" }); + expect(isCursorCloudUnsentRequestError(responseError)).toBe(false); + expect(isCursorCloudUnsentRequestError(new CursorCloudClientError("payload_too_large"))).toBe(false); + expect(calls).toBe(1); + }); + + it("aborts actual HTTP work for deadlines and operator cancellation", async () => { + let calls = 0; + let signalReady: (() => void) | undefined; + const ready = new Promise(resolve => { signalReady = resolve; }); + let signalClosed: (() => void) | undefined; + const closed = new Promise(resolve => { signalClosed = resolve; }); + const baseUrl = await serve((request, _response) => { + calls += 1; + if (calls === 2) { + request.on("close", () => signalClosed?.()); + signalReady?.(); + } + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl, requestTimeoutMs: 35 }); + await expect(client.getAgent(AGENT)).rejects.toMatchObject({ code: "timeout" }); + const controller = new AbortController(); + const pending = client.getAgent(AGENT, { signal: controller.signal, timeoutMs: 5_000 }); + await ready; + controller.abort(new Error(`Do not retain ${API_KEY}`)); + const error = await pending.catch(error => error); + expect(error).toMatchObject({ code: "cancelled" }); + expect(String(error)).not.toContain(API_KEY); + await closed; + expect(calls).toBe(2); + }); + + it("rejects malformed IDs, credential URLs, header injection, and redirects before credential forwarding", async () => { + let calls = 0; + const baseUrl = await serve((_request, response) => { calls += 1; response.writeHead(307, { Location: "https://example.test/steal" }); response.end(); }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + await expect(client.getAgent("bc-../../escape")).rejects.toMatchObject({ code: "invalid_request" }); + await expect(client.createAgent({ prompt: { text: "task" } }, { idempotencyKey: "unsafe\r\nAuthorization: other" })).rejects.toMatchObject({ code: "invalid_request" }); + expect(calls).toBe(0); + await expect(client.getAgent(AGENT)).rejects.toBeInstanceOf(CursorCloudClientError); + expect(calls).toBe(1); + expect(() => new CursorCloudClient({ apiKey: API_KEY, baseUrl: "https://user:secret@example.test" })).toThrow(CursorCloudClientError); + expect(() => new CursorCloudClient({ apiKey: API_KEY, baseUrl: "http://example.test" })).toThrow(CursorCloudClientError); + }); +}); + +describe("Cursor Cloud SSE wire protocol", () => { + it("replays the opaque cursor and decodes fragmented UTF-8, CRLF, multiline data, and shared IDs", async () => { + let replay: string | undefined; + const baseUrl = await serve((request, response) => { + replay = request.headers["last-event-id"] as string | undefined; + response.writeHead(200, { "Content-Type": "text/event-stream" }); + const bytes = Buffer.from(': heartbeat\r\nid: opaque/cursor-7\r\nevent: assistant\r\ndata: {"text":\r\ndata: "héllo 🌍"}\r\n\r\nid: opaque/cursor-7\nevent: interaction_update\ndata: {"type":"text-delta"}\n\nevent: done\ndata: {}\n\n'); + const split = bytes.indexOf(Buffer.from("🌍")) + 2; + response.write(bytes.subarray(0, split)); + setImmediate(() => { response.write(bytes.subarray(split, split + 1)); setImmediate(() => response.end(bytes.subarray(split + 1))); }); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + expect(await collect(client.streamRun(AGENT, RUN, { lastEventId: "previous-opaque" }))).toEqual([ + { event: "assistant", id: "opaque/cursor-7", data: { text: "héllo 🌍" } }, + { event: "interaction_update", id: "opaque/cursor-7", data: { type: "text-delta" } }, + { event: "done", data: {} }, + ]); + expect(replay).toBe("previous-opaque"); + }); + + it("cancels the wire reader when the consumer stops", async () => { + let connectionClosed: (() => void) | undefined; + const closed = new Promise(resolve => { connectionClosed = resolve; }); + const baseUrl = await serve((request, response) => { + request.once("close", () => connectionClosed?.()); + response.writeHead(200, { "Content-Type": "text/event-stream" }); + response.write('event: status\ndata: {"status":"RUNNING"}\n\n'); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + for await (const event of client.streamRun(AGENT, RUN)) { expect(event.event).toBe("status"); break; } + await closed; + }); + + it("bounds an unterminated frame and settles an idle connection", async () => { + let calls = 0; + const baseUrl = await serve((_request, response) => { + calls += 1; + response.writeHead(200, { "Content-Type": "text/event-stream" }); + if (calls === 1) response.end(`event: assistant\ndata: ${"x".repeat(200)}`); + else response.flushHeaders(); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl, maxSseFrameBytes: 100 }); + const streamError = await collect(client.streamRun(AGENT, RUN)).catch(error => error); + expect(streamError).toMatchObject({ code: "payload_too_large" }); + expect(isCursorCloudUnsentRequestError(streamError)).toBe(false); + const idleClient = new CursorCloudClient({ apiKey: API_KEY, baseUrl, streamIdleTimeoutMs: 35 }); + await expect(collect(idleClient.streamRun(AGENT, RUN))).rejects.toMatchObject({ code: "timeout" }); + }); + + it("rejects malformed JSON and preserves stream-expiry metadata without logging the body", async () => { + let calls = 0; + const baseUrl = await serve((_request, response) => { + calls += 1; + if (calls === 1) { + response.writeHead(200, { "Content-Type": "text/event-stream" }); + response.end(`event: assistant\ndata: {${API_KEY}}\n\n`); + return; + } + json(response, { error: { code: "stream_expired", message: API_KEY } }, 410); + }); + const client = new CursorCloudClient({ apiKey: API_KEY, baseUrl }); + await expect(collect(client.streamRun(AGENT, RUN))).rejects.toMatchObject({ code: "invalid_response" }); + const error = await collect(client.streamRun(AGENT, RUN)).catch(error => error); + expect(error).toMatchObject({ status: 410, providerCode: "stream_expired", retryable: false }); + expect(JSON.stringify(error)).not.toContain(API_KEY); + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.ts new file mode 100644 index 00000000000..3a60933db0b --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/cloud-client.ts @@ -0,0 +1,563 @@ +export type CursorCloudRunStatus = + | "CREATING" | "RUNNING" | "WAITING_FOR_BACKGROUND_WORK" + | "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED"; + +export interface CursorCloudModelRef { + id: string; + params?: Array<{ id: string; value: string }>; +} + +export interface CursorCloudRepo { + url: string; + startingRef?: string; + prUrl?: string; +} + +export type CursorCloudMcpServer = { + name: string; + type?: "http" | "sse"; + url: string; + headers?: Record; + auth?: { CLIENT_ID: string; CLIENT_SECRET?: string; scopes?: string[] }; +} | { + name: string; + type?: "stdio"; + command: string; + args?: string[]; + env?: Record; +}; + +export interface CursorCloudFollowupInput { + prompt: { text: string }; + model?: CursorCloudModelRef; + mcpServers?: CursorCloudMcpServer[]; + envVars?: Record; + mode?: "agent" | "plan"; +} + +export interface CursorCloudCreateInput extends CursorCloudFollowupInput { + agentId?: string; + name?: string; + env?: { type: "cloud" | "pool" | "machine"; name?: string }; + repos?: CursorCloudRepo[]; + workOnCurrentBranch?: boolean; + autoCreatePR?: boolean; + skipReviewerRequest?: boolean; + customSubagents?: Array<{ + name: string; + description: string; + prompt: string; + model?: "inherit" | string | CursorCloudModelRef; + }>; +} + +export interface CursorCloudAgent { + id: string; + status: "ACTIVE" | "IDLE" | "ARCHIVED"; + env: { type: "cloud" | "pool" | "machine"; name?: string }; + url: string; + createdAt: string; + updatedAt: string; + name?: string; + latestRunId?: string; + repos?: CursorCloudRepo[]; +} + +export interface CursorCloudRun { + id: string; + agentId: string; + status: CursorCloudRunStatus; + createdAt: string; + updatedAt: string; + durationMs?: number; + result?: string; + git?: { branches: Array<{ repoUrl: string; branch?: string; prUrl?: string }> }; +} + +export interface CursorCloudModel { + id: string; + displayName: string; + description?: string; + aliases?: string[]; + parameters?: Array<{ id: string; displayName?: string; values: Array<{ value: string; displayName?: string }> }>; + variants?: Array<{ params: Array<{ id: string; value: string }>; displayName: string; description?: string; isDefault?: boolean }>; +} + +export interface CursorCloudArtifact { + path: string; + sizeBytes: number; + updatedAt: string; +} + +export interface CursorCloudTokenUsage { + inputTokens: number; + outputTokens: number; + cacheWriteTokens: number; + cacheReadTokens: number; + totalTokens: number; +} + +export interface CursorCloudUsage { + totalUsage: CursorCloudTokenUsage; + runs: Array<{ id: string; usageUuid?: string; usage: CursorCloudTokenUsage }>; +} + +export interface CursorCloudSseEvent { + event: string; + id?: string; + data: unknown; +} + +export interface CursorCloudRequestOptions { + signal?: AbortSignal; + timeoutMs?: number; +} + +export interface CursorCloudMutationOptions extends CursorCloudRequestOptions { + idempotencyKey?: string; +} + +export interface CursorCloudStreamOptions extends CursorCloudRequestOptions { + lastEventId?: string; +} + +export interface CursorCloudClientOptions { + apiKey: string; + baseUrl?: string; + fetch?: typeof globalThis.fetch; + requestTimeoutMs?: number; + streamIdleTimeoutMs?: number; + streamTimeoutMs?: number; + maxRequestBytes?: number; + maxResponseBytes?: number; + maxSseFrameBytes?: number; +} + +type ClientErrorCode = "configuration" | "invalid_request" | "http_error" | "network_error" + | "invalid_response" | "payload_too_large" | "cancelled" | "timeout"; + +export class CursorCloudClientError extends Error { + readonly code: ClientErrorCode; + readonly status?: number; + readonly providerCode?: string; + readonly retryAfterMs?: number; + readonly retryable: boolean; + + constructor(code: ClientErrorCode, details: { + status?: number; providerCode?: string; retryAfterMs?: number; + } = {}) { + super(`Cursor Cloud request failed (${code}${details.status ? `, HTTP ${details.status}` : ""}).`); + this.name = "CursorCloudClientError"; + this.code = code; + this.status = details.status; + this.providerCode = details.providerCode; + this.retryAfterMs = details.retryAfterMs; + this.retryable = code === "network_error" || code === "timeout" + || (details.status !== undefined && (details.status === 408 || details.status === 429 || details.status >= 500)); + } +} + +// This private brand is minted only before fetch. The shared error code also +// describes oversized responses, downloads and SSE frames after dispatch. +class CursorCloudUnsentRequestError extends CursorCloudClientError { + constructor() { super("payload_too_large"); } +} + +export function isCursorCloudUnsentRequestError(error: unknown): boolean { + return error instanceof CursorCloudUnsentRequestError; +} + +const RUN_STATUSES = new Set([ + "CREATING", "RUNNING", "WAITING_FOR_BACKGROUND_WORK", "FINISHED", "ERROR", "CANCELLED", "EXPIRED", +]); +const SAFE_PROVIDER_CODES = new Set([ + "validation_error", "unauthorized", "unauthenticated", "forbidden", "feature_unavailable", + "not_found", "agent_not_found", "run_not_found", "agent_busy", "agent_archived", "agent_id_conflict", + "run_not_cancellable", "invalid_model", "invalid_last_event_id", "stream_expired", "rate_limited", + "rate_limit_exceeded", "internal_error", "repository_access", "key_not_supported", "integration_not_connected", +]); +const UUID_BODY = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"; +const AGENT_ID = new RegExp(`^bc-${UUID_BODY}$`); +const RUN_ID = new RegExp(`^run-${UUID_BODY}$`); + +export function isCursorCloudRunActive(status: CursorCloudRunStatus): boolean { + return status === "CREATING" || status === "RUNNING" || status === "WAITING_FOR_BACKGROUND_WORK"; +} + +function record(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function invalidResponse(): never { throw new CursorCloudClientError("invalid_response"); } +function invalidRequest(): never { throw new CursorCloudClientError("invalid_request"); } +function nonempty(value: unknown): value is string { return typeof value === "string" && value.trim().length > 0; } +function agentId(value: unknown): asserts value is string { if (typeof value !== "string" || !AGENT_ID.test(value)) invalidRequest(); } +function runId(value: unknown): asserts value is string { if (typeof value !== "string" || !RUN_ID.test(value)) invalidRequest(); } +function headerValue(value: string): string { + if (!value || value.length > 1_024 || /[\r\n\0]/.test(value)) invalidRequest(); + return value; +} + +function parseAgent(value: unknown, expectedId?: string): CursorCloudAgent { + if (!record(value) || typeof value.id !== "string" || !AGENT_ID.test(value.id) + || (expectedId !== undefined && value.id !== expectedId) + || !["ACTIVE", "IDLE", "ARCHIVED"].includes(String(value.status)) + || !record(value.env) || !["cloud", "pool", "machine"].includes(String(value.env.type)) + || !nonempty(value.url) || !nonempty(value.createdAt) || !nonempty(value.updatedAt) + || (value.latestRunId !== undefined && (typeof value.latestRunId !== "string" || !RUN_ID.test(value.latestRunId)))) invalidResponse(); + return value as unknown as CursorCloudAgent; +} + +function parseRun(value: unknown, expectedAgentId?: string, expectedRunId?: string): CursorCloudRun { + if (!record(value) || typeof value.id !== "string" || !RUN_ID.test(value.id) + || typeof value.agentId !== "string" || !AGENT_ID.test(value.agentId) + || (expectedAgentId !== undefined && value.agentId !== expectedAgentId) + || (expectedRunId !== undefined && value.id !== expectedRunId) + || !RUN_STATUSES.has(value.status as CursorCloudRunStatus) + || !nonempty(value.createdAt) || !nonempty(value.updatedAt) + || (value.durationMs !== undefined && (!Number.isSafeInteger(value.durationMs) || Number(value.durationMs) < 0)) + || (value.result !== undefined && typeof value.result !== "string")) invalidResponse(); + return value as unknown as CursorCloudRun; +} + +function validatePrompt(input: CursorCloudFollowupInput): void { + if (!record(input) || !record(input.prompt) || !nonempty(input.prompt.text)) invalidRequest(); + if (input.model !== undefined && (!record(input.model) || !nonempty(input.model.id))) invalidRequest(); +} + +function positiveLimit(value: number | undefined, fallback: number): number { + const limit = value ?? fallback; + if (!Number.isSafeInteger(limit) || limit <= 0) throw new CursorCloudClientError("configuration"); + return limit; +} + +function requestScope(signal: AbortSignal | undefined, timeoutMs: number) { + const controller = new AbortController(); + let timedOut = false; + const cancel = () => controller.abort(); + if (signal?.aborted) cancel(); + else signal?.addEventListener("abort", cancel, { once: true }); + const timer = setTimeout(() => { timedOut = true; controller.abort(); }, timeoutMs); + timer.unref?.(); + return { + signal: controller.signal, + abort: () => { timedOut = true; controller.abort(); }, + error: () => new CursorCloudClientError(timedOut ? "timeout" : "cancelled"), + dispose: () => { clearTimeout(timer); signal?.removeEventListener("abort", cancel); }, + }; +} + +async function readBoundedBytes(response: Response, maxBytes: number): Promise { + const declared = response.headers.get("content-length"); + if (declared && /^\d+$/.test(declared) && Number(declared) > maxBytes) { + await response.body?.cancel().catch(() => {}); + throw new CursorCloudClientError("payload_too_large"); + } + if (!response.body) invalidResponse(); + const reader = response.body.getReader(); + const chunks: Uint8Array[] = []; + let bytes = 0; + try { + while (true) { + const chunk = await reader.read(); + if (chunk.done) break; + bytes += chunk.value.byteLength; + if (bytes > maxBytes) throw new CursorCloudClientError("payload_too_large"); + chunks.push(chunk.value); + } + return Buffer.concat(chunks, bytes); + } finally { + await reader.cancel().catch(() => {}); + reader.releaseLock(); + } +} + +async function readBoundedBody(response: Response, maxBytes: number): Promise { + const bytes = await readBoundedBytes(response, maxBytes); + try { return new TextDecoder("utf-8", { fatal: true }).decode(bytes); } + catch { invalidResponse(); } +} + +export class CursorCloudClient { + readonly #apiKey: string; + readonly #baseUrl: string; + readonly #fetch: typeof globalThis.fetch; + readonly #requestTimeoutMs: number; + readonly #streamIdleTimeoutMs: number; + readonly #streamTimeoutMs: number; + readonly #maxRequestBytes: number; + readonly #maxResponseBytes: number; + readonly #maxSseFrameBytes: number; + + constructor(options: CursorCloudClientOptions) { + if (!nonempty(options.apiKey) || /[\r\n\0]/.test(options.apiKey)) throw new CursorCloudClientError("configuration"); + let base: URL; + try { base = new URL(options.baseUrl ?? "https://api.cursor.com"); } + catch { throw new CursorCloudClientError("configuration"); } + if ((base.protocol !== "https:" && !(base.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(base.hostname))) + || base.username || base.password || base.search || base.hash || base.pathname !== "/") throw new CursorCloudClientError("configuration"); + this.#apiKey = options.apiKey; + this.#baseUrl = base.origin; + this.#fetch = options.fetch ?? globalThis.fetch; + this.#requestTimeoutMs = positiveLimit(options.requestTimeoutMs, 30_000); + this.#streamIdleTimeoutMs = positiveLimit(options.streamIdleTimeoutMs, 60_000); + this.#streamTimeoutMs = positiveLimit(options.streamTimeoutMs, 7_200_000); + this.#maxRequestBytes = positiveLimit(options.maxRequestBytes, 2_097_152); + this.#maxResponseBytes = positiveLimit(options.maxResponseBytes, 4_194_304); + this.#maxSseFrameBytes = positiveLimit(options.maxSseFrameBytes, 1_048_576); + } + + async createAgent(input: CursorCloudCreateInput, options: CursorCloudMutationOptions = {}): Promise<{ agent: CursorCloudAgent; run: CursorCloudRun }> { + validatePrompt(input); + if (input.agentId !== undefined) agentId(input.agentId); + if (input.agentId !== undefined && input.envVars !== undefined) invalidRequest(); + const response = await this.#json("POST", "/v1/agents", input, options); + if (!record(response)) invalidResponse(); + const agent = parseAgent(response.agent, input.agentId); + const run = parseRun(response.run, agent.id); + return { agent, run }; + } + + async createRun(id: string, input: CursorCloudFollowupInput, options: CursorCloudMutationOptions = {}): Promise<{ run: CursorCloudRun }> { + agentId(id); + validatePrompt(input); + const response = await this.#json("POST", `/v1/agents/${id}/runs`, input, options); + if (!record(response)) invalidResponse(); + return { run: parseRun(response.run, id) }; + } + + async getAgent(id: string, options: CursorCloudRequestOptions = {}): Promise { + agentId(id); + return parseAgent(await this.#json("GET", `/v1/agents/${id}`, undefined, options), id); + } + + async getRun(id: string, run: string, options: CursorCloudRequestOptions = {}): Promise { + agentId(id); runId(run); + return parseRun(await this.#json("GET", `/v1/agents/${id}/runs/${run}`, undefined, options), id, run); + } + + async cancelRun(id: string, run: string, options: CursorCloudRequestOptions = {}): Promise<{ id: string }> { + agentId(id); runId(run); + return this.#idResponse(await this.#json("POST", `/v1/agents/${id}/runs/${run}/cancel`, undefined, options), run); + } + + async deleteAgent(id: string, options: CursorCloudRequestOptions = {}): Promise<{ id: string }> { + agentId(id); + return this.#idResponse(await this.#json("DELETE", `/v1/agents/${id}`, undefined, options), id); + } + + async listModels(options: CursorCloudRequestOptions = {}): Promise<{ items: CursorCloudModel[] }> { + const response = await this.#json("GET", "/v1/models", undefined, options); + if (!record(response) || !Array.isArray(response.items) + || !response.items.every(item => record(item) && nonempty(item.id) && nonempty(item.displayName))) invalidResponse(); + return { items: response.items as CursorCloudModel[] }; + } + + async listArtifacts(id: string, options: CursorCloudRequestOptions = {}): Promise<{ items: CursorCloudArtifact[] }> { + agentId(id); + const response = await this.#json("GET", `/v1/agents/${id}/artifacts`, undefined, options); + if (!record(response) || !Array.isArray(response.items) || response.items.length > 100 + || !response.items.every(item => record(item) && nonempty(item.path) && Number.isSafeInteger(item.sizeBytes) + && Number(item.sizeBytes) >= 0 && nonempty(item.updatedAt))) invalidResponse(); + return { items: response.items as CursorCloudArtifact[] }; + } + + async getArtifactDownloadUrl(id: string, path: string, options: CursorCloudRequestOptions = {}): Promise<{ url: string; expiresAt: string }> { + agentId(id); + if (!nonempty(path) || path.startsWith("/") || /[\\\0]/.test(path) || path.split("/").some(segment => segment === "..")) invalidRequest(); + const response = await this.#json("GET", `/v1/agents/${id}/artifacts/download?${new URLSearchParams({ path })}`, undefined, options); + if (!record(response) || !nonempty(response.url) || !nonempty(response.expiresAt)) invalidResponse(); + let url: URL; + try { url = new URL(response.url); } catch { invalidResponse(); } + if (url.protocol !== "https:" || url.username || url.password) invalidResponse(); + return { url: response.url, expiresAt: response.expiresAt }; + } + + async getUsage(id: string, query: { runId?: string } = {}, options: CursorCloudRequestOptions = {}): Promise { + agentId(id); + if (query.runId !== undefined) runId(query.runId); + const suffix = query.runId ? `?${new URLSearchParams({ runId: query.runId })}` : ""; + const response = await this.#json("GET", `/v1/agents/${id}/usage${suffix}`, undefined, options); + const validUsage = (value: unknown): boolean => record(value) + && ["inputTokens", "outputTokens", "cacheWriteTokens", "cacheReadTokens", "totalTokens"] + .every(key => Number.isSafeInteger(value[key]) && Number(value[key]) >= 0); + if (!record(response) || !validUsage(response.totalUsage) || !Array.isArray(response.runs) + || !response.runs.every(item => record(item) && typeof item.id === "string" && RUN_ID.test(item.id) + && (query.runId === undefined || item.id === query.runId) && validUsage(item.usage) + && (item.usageUuid === undefined || nonempty(item.usageUuid)))) invalidResponse(); + return response as unknown as CursorCloudUsage; + } + + async downloadArtifact(id: string, path: string, options: CursorCloudRequestOptions & { maxBytes?: number } = {}): Promise { + const maxBytes = positiveLimit(options.maxBytes, 16_777_216); + if (maxBytes > 16_777_216) invalidRequest(); + const scope = requestScope(options.signal, positiveLimit(options.timeoutMs, this.#requestTimeoutMs)); + try { + const { url } = await this.getArtifactDownloadUrl(id, path, { ...options, signal: scope.signal }); + const target = new URL(url); + if (target.hostname !== "agent-stores.s3.us-east-1.amazonaws.com" || target.port || target.protocol !== "https:") invalidResponse(); + if (scope.signal.aborted) throw scope.error(); + const response = await this.#fetch(url, { method: "GET", signal: scope.signal, redirect: "error" }); + if (!response.ok) { + await response.body?.cancel().catch(() => {}); + throw new CursorCloudClientError("http_error", { status: response.status }); + } + return await readBoundedBytes(response, maxBytes); + } catch (error) { throw this.#safeError(error, scope); } + finally { scope.dispose(); } + } + + async *streamRun(id: string, run: string, options: CursorCloudStreamOptions = {}): AsyncGenerator { + agentId(id); runId(run); + const headers = this.#headers("text/event-stream"); + if (options.lastEventId !== undefined) headers["Last-Event-ID"] = headerValue(options.lastEventId); + const scope = requestScope(options.signal, positiveLimit(options.timeoutMs, this.#streamTimeoutMs)); + let idleTimer: ReturnType | undefined; + let reader: ReadableStreamDefaultReader | undefined; + const resetIdle = () => { + clearTimeout(idleTimer); + idleTimer = setTimeout(scope.abort, this.#streamIdleTimeoutMs); + idleTimer.unref?.(); + }; + resetIdle(); + try { + if (scope.signal.aborted) throw scope.error(); + const response = await this.#fetch(`${this.#baseUrl}/v1/agents/${id}/runs/${run}/stream`, { + method: "GET", headers, signal: scope.signal, redirect: "error", + }); + if (!response.ok) throw await this.#httpError(response); + if (!response.headers.get("content-type")?.toLowerCase().startsWith("text/event-stream") || !response.body) { + await response.body?.cancel().catch(() => {}); + invalidResponse(); + } + reader = response.body.getReader(); + clearTimeout(idleTimer); + const decoder = new TextDecoder("utf-8", { fatal: true }); + const parser = new CursorCloudSseParser(this.#maxSseFrameBytes); + while (true) { + resetIdle(); + const chunk = await reader.read(); + clearTimeout(idleTimer); + if (scope.signal.aborted) throw scope.error(); + if (chunk.done) { yield* parser.push(decoder.decode(), true); break; } + for (const event of parser.push(decoder.decode(chunk.value, { stream: true }))) { + yield event; + if (event.event === "done") return; + } + } + } catch (error) { throw this.#safeError(error, scope); } + finally { + clearTimeout(idleTimer); + await reader?.cancel().catch(() => {}); + reader?.releaseLock(); + scope.dispose(); + } + } + + #idResponse(response: unknown, expected: string): { id: string } { + if (!record(response) || response.id !== expected) invalidResponse(); + return { id: expected }; + } + + #headers(accept = "application/json"): Record { + return { Authorization: `Bearer ${this.#apiKey}`, Accept: accept }; + } + + async #json(method: string, path: string, input: unknown, options: CursorCloudMutationOptions): Promise { + const headers = this.#headers(); + let body: string | undefined; + if (input !== undefined) { + try { body = JSON.stringify(input); } catch { invalidRequest(); } + if (Buffer.byteLength(body) > this.#maxRequestBytes) throw new CursorCloudUnsentRequestError(); + headers["Content-Type"] = "application/json"; + } + if (options.idempotencyKey !== undefined) headers["Idempotency-Key"] = headerValue(options.idempotencyKey); + const scope = requestScope(options.signal, positiveLimit(options.timeoutMs, this.#requestTimeoutMs)); + try { + if (scope.signal.aborted) throw scope.error(); + const response = await this.#fetch(`${this.#baseUrl}${path}`, { method, headers, body, signal: scope.signal, redirect: "error" }); + if (!response.ok) throw await this.#httpError(response); + if (!response.headers.get("content-type")?.toLowerCase().startsWith("application/json")) { + await response.body?.cancel().catch(() => {}); + invalidResponse(); + } + const text = await readBoundedBody(response, this.#maxResponseBytes); + try { return JSON.parse(text); } catch { invalidResponse(); } + } catch (error) { throw this.#safeError(error, scope); } + finally { scope.dispose(); } + } + + #safeError(error: unknown, scope: ReturnType): CursorCloudClientError { + if (scope.signal.aborted) return scope.error(); + if (error instanceof CursorCloudClientError) return error; + return new CursorCloudClientError(error instanceof TypeError ? "network_error" : "invalid_response"); + } + + async #httpError(response: Response): Promise { + let providerCode: string | undefined; + try { + const value: unknown = JSON.parse(await readBoundedBody(response, Math.min(this.#maxResponseBytes, 65_536))); + const code = record(value) ? (record(value.error) ? value.error.code : value.code) : undefined; + if (typeof code === "string" && SAFE_PROVIDER_CODES.has(code)) providerCode = code; + } catch { } + const retryHeader = response.headers.get("retry-after"); + const delay = retryHeader && /^\d+(\.\d+)?$/.test(retryHeader) ? Number(retryHeader) * 1_000 : undefined; + return new CursorCloudClientError("http_error", { + status: response.status, providerCode, + ...(delay !== undefined && Number.isFinite(delay) ? { retryAfterMs: Math.min(delay, 86_400_000) } : {}), + }); + } +} + +class CursorCloudSseParser { + #buffer = ""; + #frameBytes = 0; + #event = ""; + #id: string | undefined; + #data: string[] = []; + + constructor(readonly maxBytes: number) {} + + *push(text: string, end = false): Generator { + this.#buffer += text; + while (true) { + const boundary = /[\r\n]/.exec(this.#buffer); + if (!boundary || (!end && boundary.index === this.#buffer.length - 1 && boundary[0] === "\r")) break; + const delimiter = this.#buffer.startsWith("\r\n", boundary.index) ? 2 : 1; + const line = this.#buffer.slice(0, boundary.index); + this.#buffer = this.#buffer.slice(boundary.index + delimiter); + this.#frameBytes += Buffer.byteLength(line) + delimiter; + if (this.#frameBytes > this.maxBytes) throw new CursorCloudClientError("payload_too_large"); + if (!line) { + const event = this.#finish(); + if (event) yield event; + } else if (!line.startsWith(":")) { + const colon = line.indexOf(":"); + const field = colon < 0 ? line : line.slice(0, colon); + const value = colon < 0 ? "" : line.slice(colon + 1).replace(/^ /, ""); + if (field === "event") this.#event = value; + if (field === "id" && !value.includes("\0")) this.#id = value; + if (field === "data") this.#data.push(value); + } + } + if (this.#frameBytes + Buffer.byteLength(this.#buffer) > this.maxBytes) throw new CursorCloudClientError("payload_too_large"); + if (end && this.#buffer) invalidResponse(); + } + + #finish(): CursorCloudSseEvent | undefined { + let data: unknown = null; + const event = this.#event || "message"; + const id = this.#id; + const present = this.#data.length > 0 || this.#event.length > 0; + if (this.#data.length) { + try { data = JSON.parse(this.#data.join("\n")); } catch { invalidResponse(); } + } + this.#data = []; + this.#event = ""; + this.#id = undefined; + this.#frameBytes = 0; + if (!present) return undefined; + if (event.length > 128 || /[\0]/.test(event) || (id !== undefined && (id.length > 1_024 || /[\0]/.test(id)))) invalidResponse(); + return { event, ...(id !== undefined ? { id } : {}), data }; + } +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/config.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/config.ts new file mode 100644 index 00000000000..02fcd44d9cf --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/config.ts @@ -0,0 +1,22 @@ +export { parseNativeCursorCloudConfig, type NativeCursorCloudConfig } from "../../contracts/cursor-cloud.js"; + +export const CURSOR_CLOUD_MCP_SERVER_NAME = "paperclip" as const; + +export interface CursorCloudBinding { + companyId: string; + agentId: string; + issueId: string; + normalizedSessionId: string; +} + +export function cursorCloudRecord(value: unknown): Record { + if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Cursor Cloud configuration must be an object"); + return value as Record; +} + +export function parseCursorCloudBinding(value: unknown): CursorCloudBinding { + const source = cursorCloudRecord(value); + if (Object.keys(source).sort().join(",") !== "agentId,companyId,issueId,normalizedSessionId" + || !Object.values(source).every(value => typeof value === "string" && value.trim().length > 0 && value.length <= 1_024 && !/[\x00-\x1f\x7f]/.test(value))) throw new Error("Cursor Cloud binding is invalid"); + return { companyId: source.companyId as string, agentId: source.agentId as string, issueId: source.issueId as string, normalizedSessionId: source.normalizedSessionId as string }; +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.test.ts new file mode 100644 index 00000000000..532faaf17b6 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.test.ts @@ -0,0 +1,1391 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { lstat, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises"; +import { spawn } from "node:child_process"; +import { once } from "node:events"; +import { createHash } from "node:crypto"; +import { request } from "node:http"; +import { join } from "node:path"; +import type { HarnessSession } from "../../contracts/harness-driver.js"; +import type { PrpEvent } from "../../protocol/replay-contract.js"; +import type { CursorCloudArtifact, CursorCloudCreateInput, CursorCloudFollowupInput, CursorCloudRun, CursorCloudSseEvent } from "./cloud-client.js"; +import { CursorCloudClient, CursorCloudClientError } from "./cloud-client.js"; +import { CursorCloudCheckpointStore, cursorCloudDigest } from "./checkpoint.js"; +import { reserveCursorCloudArtifactStaging } from "./artifact-staging-budget.js"; +import { semanticCanonicalJson } from "../semantic-tool-receipt.js"; +import { RUNNER_TOOL_SCOPE_TOKEN_HEADER } from "../runner-tool-bridge.js"; +import { CursorCloudDriver, cursorCloudDriverDescriptor, type CursorCloudDriverOptions, type CursorCloudSessionHandle } from "./cursor-cloud-driver.js"; + +const roots: string[] = []; +const sessions: HarnessSession[] = []; +afterEach(async () => { + for (const session of sessions.splice(0)) await session.close({ reason: "test_cleanup" }).catch(() => {}); + for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); +}); +const runId = "run-11111111-1111-4111-8111-111111111111"; +function deferred() { let resolve!: (value: T | PromiseLike) => void; const promise = new Promise(accept => { resolve = accept; }); return { promise, resolve }; } + +class Peer { + request: CursorCloudCreateInput | CursorCloudFollowupInput | null = null; + native: CursorCloudRun | null = null; + created = deferred(); + release = deferred(); + failCreate = false; + replay = false; + cursor: string | undefined; + createAgent = vi.fn(async (input: CursorCloudCreateInput) => { + this.request = input; + this.native = { id: runId, agentId: input.agentId!, status: "RUNNING", createdAt: "2026-10-28T00:00:00Z", updatedAt: "2026-10-28T00:00:00Z" }; + this.created.resolve(); + if (this.failCreate) throw new Error("lost response"); + return { agent: { id: input.agentId!, status: "ACTIVE" as const, env: { type: "cloud" as const }, url: "https://cursor.com/agents/example", createdAt: this.native.createdAt, updatedAt: this.native.updatedAt, latestRunId: runId }, run: { ...this.native } }; + }); + createRun = vi.fn(async (_id: string, input: CursorCloudFollowupInput) => { + this.request = input; this.release = deferred(); this.native!.status = "RUNNING"; + return { run: { ...this.native! } }; + }); + getAgent = vi.fn(async (id: string) => ({ id, status: "ACTIVE" as const, env: { type: "cloud" as const }, url: "https://cursor.com/agents/example", createdAt: "2026-10-28T00:00:00Z", updatedAt: "2026-10-28T00:00:00Z", latestRunId: runId })); + getRun = vi.fn(async () => ({ ...this.native! })); + cancelRun = vi.fn(async () => { this.native!.status = "CANCELLED"; this.release.resolve(); return { id: runId }; }); + getUsage = vi.fn(async () => ({ totalUsage: { inputTokens: 3, outputTokens: 2, cacheWriteTokens: 0, cacheReadTokens: 0, totalTokens: 5 }, runs: [] })); + listArtifacts = vi.fn(async (): Promise<{ items: CursorCloudArtifact[] }> => ({ items: [] })); + downloadArtifact = vi.fn(async () => Buffer.alloc(0)); + async *streamRun(_agent: string, _run: string, options: { signal?: AbortSignal; lastEventId?: string } = {}): AsyncGenerator { + this.cursor = options.lastEventId; + if (!this.replay) { yield { id: "opaque-1", event: "assistant", data: { text: "Working." } }; this.replay = true; } + else yield { id: "opaque-1", event: "assistant", data: { text: "Working." } }; + await Promise.race([this.release.promise, new Promise(accept => options.signal?.addEventListener("abort", () => accept(), { once: true }))]); + if (options.signal?.aborted) return; + yield { id: "opaque-2", event: "result", data: { runId, status: this.native!.status } }; + } +} + +function maintainedMutations(peer: Peer, maxResponseBytes?: number) { + const fetch = vi.fn(async (url: string | URL | Request, init?: RequestInit) => { + const body = JSON.parse(String(init?.body)); + const result = new URL(String(url)).pathname === "/v1/agents" ? await peer.createAgent(body) : await peer.createRun(peer.native!.agentId, body); + return new Response(JSON.stringify(result), { headers: { "content-type": "application/json" } }); + }); + const client = new CursorCloudClient({ apiKey: "private-cursor-key", fetch, maxResponseBytes }); + return { fetch, client: { ...peer, createAgent: client.createAgent.bind(client), createRun: client.createRun.bind(client), streamRun: peer.streamRun.bind(peer) } }; +} + +async function fixture(peer = new Peer(), extra: Partial = {}) { + const root = await mkdtemp("/tmp/cc-"); roots.push(root); + const handler = vi.fn(async () => ({ success: true, contentItems: [{ type: "inputText", text: "accepted" }] })); + const options: CursorCloudDriverOptions = { model: "explicit-model", config: { schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo", startingRef: "main" }] }, + binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId: "session" }, runtimeDirectory: root, + relay: { url: "https://relay.example.test/mcp", token: "private-relay-token", socketPath: join(root, "mcp.sock"), expiresAt: Date.now() + 600_000 }, instructions: "Follow these exact instructions.", + dynamicTools: [{ name: "write_note", inputSchema: { type: "object", required: ["note"], properties: { note: { type: "string" } }, additionalProperties: false } }], dynamicToolHandler: handler, + environment: { CURSOR_API_KEY: "private-cursor-key" }, client: peer, reconnectDelayMs: 1, cancelTimeoutMs: 300, ...extra }; + const driver = new CursorCloudDriver(options); + const session = await driver.openSession({ runId: "paperclip-run", normalizedSessionId: "session", workingDirectory: root }); sessions.push(session); + const events: PrpEvent[] = []; + const pump = (async () => { for await (const event of session.events()) events.push(event); })(); + return { root, peer, handler, options, driver, session, events, pump }; +} + +async function waitFor(check: () => boolean) { await vi.waitFor(() => expect(check()).toBe(true), { timeout: 2_000, interval: 5 }); } + +async function acknowledgeTerminal(session: CursorCloudSessionHandle) { + const pending = (await session.read?.())?.pendingTerminalDelivery as { turnId: string; receiptId: string }; + await session.acknowledgeTerminalDelivery(pending); +} + +function distinctFollowup(peer: Peer) { + peer.createRun.mockImplementation(async (_id, input) => { + peer.request = input; peer.native = { ...peer.native!, id: "run-22222222-2222-4222-8222-222222222222", status: "RUNNING" }; + return { run: { ...peer.native } }; + }); +} + +async function savedCheckpoint(root: string, session: CursorCloudSessionHandle) { + await session.snapshot(); + return JSON.parse(await readFile(join(root, (await readdir(root)).find(name => /^checkpoint-.*\.json$/.test(name))!), "utf8")); +} + +async function nextAuthority(f: Awaited>) { + await acknowledgeTerminal(f.session); + await f.session.attachRun!({ runId: "paperclip-followup" }); + const next = await f.session.startTurn({ message: { role: "user", text: "Next task" } }); + await waitFor(() => f.events.some(event => event.turnId === next.turnId && event.eventType === "item.delta")); + return { next, checkpoint: await savedCheckpoint(f.root, f.session), eventCount: f.events.length }; +} + +function relayHeaders(peer: Peer): Record { return structuredClone(peer.request!.mcpServers[0]!.headers!); } + +async function rpc(path: string, body: unknown, token: string | Record = "private-relay-token", session?: string): Promise<{ status: number; value: any; session?: string }> { + return new Promise((accept, reject) => { + const req = request({ socketPath: path, path: "/mcp", method: "POST", headers: { ...(typeof token === "string" ? { Authorization: `Bearer ${token}` } : token), "content-type": "application/json", ...(session ? { "Mcp-Session-Id": session } : {}) } }, response => { + let text = ""; response.setEncoding("utf8"); response.on("data", chunk => { text += chunk; }); + response.on("end", () => accept({ status: response.statusCode!, value: text ? JSON.parse(text) : null, session: response.headers["mcp-session-id"] as string | undefined })); + }); + req.on("error", reject); req.end(JSON.stringify({ jsonrpc: "2.0", ...body as object })); + }); +} + +describe("Cursor Cloud native driver", () => { + it.each(["rejected", "ambiguous"])("retains bounded staging custody after %s controller registration across restart", async mode => { + const runtimeDirectory = await mkdtemp("/tmp/cc-artifact-controller-"); roots.push(runtimeDirectory); + const artifactRoot = join(runtimeDirectory, "artifacts"), signal = new AbortController().signal; + for (let count = 0; count < 255; count++) await reserveCursorCloudArtifactStaging({ runtimeDirectory, artifactRoot, byteSize: 0, signal }); + const peer = new Peer(), bytes = Buffer.from("verified controller-rejected file"); + const sha256 = createHash("sha256").update(bytes).digest("hex"); + peer.listArtifacts.mockImplementation(async () => ({ items: [{ path: "artifacts/result.txt", sizeBytes: bytes.length, updatedAt: "2026-10-28T00:00:00Z" }] })); + peer.downloadArtifact.mockResolvedValue(bytes); + const handler = vi.fn(async () => { + if (mode === "ambiguous") throw new Error("fixture controller registration unavailable"); + return { success: false, error: "fixture controller registration rejected" }; + }); + const f = await fixture(peer, { runtimeDirectory, artifactRoot, dynamicTools: [{ name: "register_deliverable", inputSchema: { type: "object" } }], dynamicToolHandler: handler }); + await f.session.startTurn({ message: { role: "user", text: "Register the verified result" } }); await peer.created.promise; + const input = { contentRef: "cursor-artifact:artifacts/result.txt", filename: "result.txt", byteSize: bytes.length, sha256 }; + const initialized = await rpc(f.options.relay.socketPath, { id: 0, method: "initialize" }, relayHeaders(peer)); + const first = await rpc(f.options.relay.socketPath, { id: 1, method: "tools/call", params: { name: "register_deliverable", arguments: input } }, relayHeaders(peer), initialized.session); + expect(JSON.stringify(first.value)).toContain("fixture controller registration"); + expect(handler).toHaveBeenCalledOnce(); + expect(await readFile(join(artifactRoot, sha256, input.filename))).toEqual(bytes); + const budgetPath = join(runtimeDirectory, ".artifact-staging-budget", "usage.json"); + const budget = await readFile(budgetPath, "utf8"); expect(JSON.parse(budget)).toMatchObject({ allocations: 256, reservedBytes: bytes.length }); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + const reinitialized = await rpc(f.options.relay.socketPath, { id: 2, method: "initialize" }, relayHeaders(peer)); + const denied = await rpc(f.options.relay.socketPath, { id: 3, method: "tools/call", params: { name: "register_deliverable", arguments: { ...input, filename: "over-budget.txt" } } }, relayHeaders(peer), reinitialized.session); + expect(JSON.stringify(denied.value)).toContain("staging budget"); + expect(handler).toHaveBeenCalledOnce(); expect(peer.downloadArtifact).toHaveBeenCalledOnce(); + expect(await readFile(budgetPath, "utf8")).toBe(budget); + await expect(lstat(join(artifactRoot, sha256, "over-budget.txt"))).rejects.toMatchObject({ code: "ENOENT" }); + }, 20_000); + + it.each([503, 429])("retries a transient observation HTTP %i without replacing work or extending its deadline", async status => { + let agentId = "", creates = 0, reads = 0, streams = 0; + const deadlines: Array = []; + const now = "2026-10-28T00:00:00Z"; + let checkpoint!: () => Promise; + const json = (value: unknown, code = 200) => new Response(JSON.stringify(value), { status: code, headers: { "content-type": "application/json" } }); + const nativeFetch: typeof globalThis.fetch = async (url, init) => { + const target = new URL(String(url)); + expect(target.origin).toBe("https://controlled.cursor.test"); + const run = { id: runId, agentId, status: "FINISHED", createdAt: now, updatedAt: now }; + if (target.pathname === "/v1/agents" && init?.method === "POST") { + creates++; agentId = JSON.parse(String(init.body)).agentId; + return json({ agent: { id: agentId, status: "ACTIVE", env: { type: "cloud" }, url: `https://cursor.com/agents/${agentId}`, createdAt: now, updatedAt: now, latestRunId: runId }, run: { ...run, agentId, status: "RUNNING" } }); + } + if (target.pathname.endsWith("/stream")) { + streams++; + return new Response('id: opaque-observation\nevent: assistant\ndata: {"text":"Working."}\n\n', { headers: { "content-type": "text/event-stream" } }); + } + if (target.pathname === `/v1/agents/${agentId}/runs/${runId}`) { + deadlines.push(await checkpoint()); + return ++reads === 1 ? json({ message: "temporary read failure" }, status) : json(run); + } + throw new Error("Unexpected controlled provider request"); + }; + const f = await fixture(new Peer(), { client: new CursorCloudClient({ apiKey: "synthetic-key", baseUrl: "https://controlled.cursor.test", fetch: nativeFetch }) }); + checkpoint = async () => (await savedCheckpoint(f.root, f.session)).deadlineAt; + await f.session.startTurn({ message: { role: "user", text: "Complete despite a temporary observation failure" } }); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + expect(creates).toBe(1); expect(reads).toBe(2); expect(streams).toBe(1); + expect(deadlines[0]).toBeGreaterThan(Date.now()); expect(deadlines[1]).toBe(deadlines[0]); + expect(f.events.filter(event => event.eventType === "turn.completed")).toHaveLength(1); + expect(f.events.filter(event => event.eventType === "item.delta")).toHaveLength(1); + expect(f.events.some(event => event.eventType === "turn.failed")).toBe(false); + }); + + it("aborts the pending observation read when Stop settles the same native run", async () => { + const peer = new Peer(), reading = deferred(); + const blocked = deferred(); + let readAborted = false; + peer.streamRun = async function* () {}; + const original = peer.getRun.getMockImplementation()!; + peer.getRun.mockImplementationOnce((...args: unknown[]) => { + const signal = (args[2] as { signal?: AbortSignal } | undefined)?.signal; + signal?.addEventListener("abort", () => { readAborted = true; }, { once: true }); + reading.resolve(); return blocked.promise; + }); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Stop an observation in flight" } }); + await reading.promise; + try { + await f.session.interrupt!(); + await vi.waitFor(() => expect(readAborted).toBe(true), { timeout: 100 }); + expect((await f.session.read()).phase).toBe("terminal"); + } finally { blocked.resolve(await original()); } + }); + + it("bounds repeated transient observation reads by the original deadline", async () => { + const peer = new Peer(); peer.streamRun = async function* () {}; + peer.getRun.mockRejectedValue(new CursorCloudClientError("http_error", { status: 503 })); + const f = await fixture(peer, { config: { schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo" }], timeoutMs: 1_000 }, cancelTimeoutMs: 25 }); + await f.session.startTurn({ message: { role: "user", text: "Keep the original observation deadline" } }); + await peer.created.promise; + const deadlineAt = (await savedCheckpoint(f.root, f.session)).deadlineAt; + try { + await waitFor(() => peer.getRun.mock.calls.length >= 5); + expect((await savedCheckpoint(f.root, f.session)).deadlineAt).toBe(deadlineAt); + await waitFor(() => Date.now() >= deadlineAt); + await vi.waitFor(async () => expect((await f.session.read()).phase).toBe("stopping")); + const observerSignal = (peer.getRun.mock.calls[0] as unknown[])[2] as { signal: AbortSignal }; + const observationReads = () => peer.getRun.mock.calls.filter(call => ((call as unknown[])[2] as { signal?: AbortSignal } | undefined)?.signal === observerSignal.signal).length; + await vi.waitFor(() => expect(observerSignal.signal.aborted).toBe(true)); + const reads = observationReads(); + await new Promise(resolve => setTimeout(resolve, 30)); + expect(observationReads()).toBe(reads); + expect(peer.createAgent).toHaveBeenCalledTimes(1); expect(peer.createRun).not.toHaveBeenCalled(); + expect(f.events.some(event => ["turn.completed", "turn.failed", "turn.interrupted"].includes(event.eventType))).toBe(false); + } finally { peer.getRun.mockImplementation(async () => ({ ...peer.native! })); } + }); + + it.each(["http_error", "invalid_response"] as const)("does not retry a non-transient observation %s", async code => { + const peer = new Peer(); peer.streamRun = async function* () {}; + const original = peer.getRun.getMockImplementation()!; + peer.getRun.mockRejectedValue(new CursorCloudClientError(code, code === "http_error" ? { status: 401 } : {})); + const f = await fixture(peer); + try { + await f.session.startTurn({ message: { role: "user", text: "Keep unauthorized or invalid observations fenced" } }); + await waitFor(() => f.events.some(event => (event.payload as { code?: string }).code === "cursor_cloud_remote_state_unknown")); + await new Promise(resolve => setTimeout(resolve, 20)); + expect(peer.getRun).toHaveBeenCalledTimes(1); + expect((await f.session.read()).phase).toBe("running"); + expect(f.events.some(event => ["turn.completed", "turn.failed", "turn.interrupted"].includes(event.eventType))).toBe(false); + } finally { peer.getRun.mockImplementation(original); } + }); + + it("aborts observation backoff without delaying Stop or buying another run", async () => { + const peer = new Peer(); peer.streamRun = async function* () {}; + peer.getRun.mockRejectedValueOnce(new CursorCloudClientError("http_error", { status: 429, retryAfterMs: 60_000 })); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Stop during a provider retry delay" } }); + await waitFor(() => f.events.some(event => (event.payload as { code?: string }).code === "cursor_cloud_observation_retry")); + const signal = ((peer.getRun.mock.calls[0] as unknown[])[2] as { signal: AbortSignal }).signal; + await f.session.interrupt!(); + expect(signal.aborted).toBe(true); + expect((await f.session.read()).phase).toBe("terminal"); + expect(peer.createAgent).toHaveBeenCalledTimes(1); expect(peer.createRun).not.toHaveBeenCalled(); + expect(f.events.filter(event => event.eventType === "turn.interrupted")).toHaveLength(1); + }); + + it.each(["fresh", "follow-up"])("serializes the injected native MCP discovery and semantic controls on a %s run", async phase => { + const requests: Array<{ path: string; body: CursorCloudCreateInput }> = []; + const now = "2026-10-28T00:00:00Z"; + let agentId = ""; + let currentRunId = runId; + const nativeFetch: typeof globalThis.fetch = async (url, init) => { + const target = new URL(String(url)); + expect(target.origin).toBe("https://controlled.cursor.test"); + const json = (value: unknown) => new Response(JSON.stringify(value), { headers: { "content-type": "application/json" } }); + if (init?.method === "POST" && (target.pathname === "/v1/agents" || target.pathname === `/v1/agents/${agentId}/runs`)) { + const body = JSON.parse(String(init.body)) as CursorCloudCreateInput; + requests.push({ path: target.pathname, body }); + agentId ||= body.agentId!; + currentRunId = requests.length === 1 ? runId : "run-22222222-2222-4222-8222-222222222222"; + const run = { id: currentRunId, agentId, status: "RUNNING", createdAt: now, updatedAt: now }; + return json(target.pathname === "/v1/agents" + ? { agent: { id: agentId, status: "ACTIVE", env: { type: "cloud" }, url: `https://cursor.com/agents/${agentId}`, createdAt: now, updatedAt: now, latestRunId: currentRunId }, run } + : { run }); + } + if (target.pathname.endsWith("/stream")) return new Response(`id: completed\nevent: result\ndata: ${JSON.stringify({ runId: currentRunId, status: "FINISHED" })}\n\n`, { headers: { "content-type": "text/event-stream" } }); + if (target.pathname === `/v1/agents/${agentId}/runs/${currentRunId}`) return json({ id: currentRunId, agentId, status: "FINISHED", createdAt: now, updatedAt: now }); + throw new Error("Unexpected controlled provider request"); + }; + const instructions = "Exact assigned instructions.\n\nAssigned skill content stays intact."; + const f = await fixture(new Peer(), { instructions, modelParams: [{ id: "effort", value: "high" }], client: new CursorCloudClient({ apiKey: "synthetic-private-key", baseUrl: "https://controlled.cursor.test", fetch: nativeFetch }) }); + const task = "Ask the assigned question.\nPreserve this exact task text."; + await f.session.startTurn({ message: { role: "user", text: task } }); + await waitFor(() => f.events.filter(event => event.eventType === "turn.completed").length === 1); + if (phase === "follow-up") { + await acknowledgeTerminal(f.session); + await f.session.startTurn({ message: { role: "user", text: task } }); + await waitFor(() => f.events.filter(event => event.eventType === "turn.completed").length === 2); + } + const sent = requests.at(-1)!; + expect(sent.path).toBe(phase === "fresh" ? "/v1/agents" : `/v1/agents/${agentId}/runs`); + expect(sent.body).toMatchObject({ model: { id: "explicit-model", params: [{ id: "effort", value: "high" }] }, mode: "agent", mcpServers: [{ name: "paperclip", type: "http", url: f.options.relay.url, headers: { Authorization: `Bearer ${f.options.relay.token}` } }] }); + const prompt = sent.body.prompt.text; + expect(prompt).toContain('get_mcp_tools({server:"paperclip"})'); + expect(prompt).toContain("native Paperclip Runner"); + expect(prompt).toContain("controller-managed MCP authentication"); + expect(prompt).toContain("do not need Paperclip REST credentials in the Cloud VM"); + expect(prompt).toContain("unrelated inherited dashboard MCP namespaces"); + for (const tool of ["request_human_input", "paperclip_finish", "paperclip_block"]) expect(prompt).toContain(tool); + expect(prompt.endsWith(`\n\nPaperclip task:\n${task}`)).toBe(true); + expect(requests[0]!.body.prompt.text.startsWith(instructions)).toBe(true); + if (phase === "follow-up") expect(prompt).not.toContain(instructions); + expect(prompt).not.toContain(f.options.relay.token); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + const checkpoint = JSON.parse(await readFile(checkpointPath, "utf8")); + expect(checkpoint.instructionsDigest).toBe(cursorCloudDigest(requests[0]!.body.prompt.text.slice(0, -`\n\nPaperclip task:\n${task}`.length))); + const { prompt: submittedPrompt, model, mode, mcpServers } = sent.body; + expect(checkpoint.requestDigest).toBe(cursorCloudDigest(semanticCanonicalJson({ prompt: submittedPrompt, model, mode, mcpServers }))); + }); + + it.each(["observer", "reconcile", "recovery"] as const)("keeps a delayed old %s result outside the next turn authority", async source => { + const peer = new Peer(); + const oldRead = deferred(); + const reading = deferred(); + const followupRunId = "run-22222222-2222-4222-8222-222222222222"; + peer.createRun.mockImplementation(async (_id, input) => { + peer.request = input; + peer.native = { ...peer.native!, id: followupRunId, status: "RUNNING" }; + return { run: { ...peer.native } }; + }); + peer.streamRun = async function* (_agent, providerRunId, options = {}) { + if (providerRunId === runId && source === "observer") return; + yield { id: providerRunId === runId ? "old-cursor" : "new-cursor", event: "assistant", data: { text: "Current stream." } }; + if (!options.signal?.aborted) await new Promise(accept => options.signal?.addEventListener("abort", () => accept(), { once: true })); + }; + const holdRead = () => peer.getRun.mockImplementationOnce(async () => { reading.resolve(); return oldRead.promise; }); + if (source === "observer") holdRead(); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await peer.created.promise; + const previous = { ...peer.native!, status: "FINISHED" as const, result: "Old final result." }; + let session = f.session; + let events = f.events; + let reconciled: Promise | undefined; + if (source !== "observer") { + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + if (source === "recovery") { + const snapshot = await session.snapshot(); await session.detachControllerForRestart!(); await f.pump; + holdRead(); + session = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; + sessions.push(session); events = []; + void (async () => { for await (const event of session.events()) events.push(event); })(); + } else { + holdRead(); reconciled = session.reconcile!(); + } + } + await reading.promise; + await session.interrupt!(); + await acknowledgeTerminal(session); + await session.attachRun!({ runId: "paperclip-followup" }); + const next = await session.startTurn({ message: { role: "user", text: "Second task" } }); + await waitFor(() => events.some(event => event.turnId === next.turnId && event.eventType === "item.delta")); + await session.snapshot(); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + const before = JSON.parse(await readFile(checkpointPath, "utf8")); + const eventCount = events.length; + oldRead.resolve(previous); + await reconciled; + await new Promise(accept => setImmediate(accept)); + await session.snapshot(); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toEqual(before); + expect(await session.read()).toMatchObject({ agentId: previous.agentId, runId: followupRunId, turnId: next.turnId, phase: "running", pendingTerminalDelivery: null }); + expect(events.slice(eventCount)).toEqual([]); + await session.interrupt!(); + expect(await session.read()).toMatchObject({ runId: followupRunId, phase: "terminal", pendingTerminalDelivery: { providerRunId: followupRunId, turnId: next.turnId, status: "CANCELLED" } }); + expect(events.filter(event => event.turnId === next.turnId && event.eventType === "turn.interrupted")).toHaveLength(1); + }); + + it.each(["assistant", "tool_call", "error"] as const)("discards an old %s stream continuation without disturbing the new observer", async kind => { + const peer = new Peer(); distinctFollowup(peer); + const release = deferred(); + const waiting = deferred(); + const streams: Array<{ runId: string; signal?: AbortSignal }> = []; + peer.streamRun = async function* (_agent, providerRunId, options = {}) { + streams.push({ runId: providerRunId, signal: options.signal }); + if (providerRunId === runId) { + waiting.resolve(); await release.promise; + if (kind === "error") throw new CursorCloudClientError("http_error", { status: 410 }); + yield { id: "stale-cursor", event: kind, data: kind === "assistant" ? { text: "Stale assistant." } : { callId: "stale-tool", name: "old_tool", status: "completed" } }; + return; + } + yield { id: "current-cursor", event: "assistant", data: { text: "Current assistant." } }; + if (!options.signal?.aborted) await new Promise(accept => options.signal?.addEventListener("abort", () => accept(), { once: true })); + }; + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await waiting.promise; + await f.session.interrupt!(); + const next = await nextAuthority(f); + release.resolve(); await new Promise(accept => setImmediate(accept)); + expect(await savedCheckpoint(f.root, f.session)).toEqual(next.checkpoint); + expect(f.events.slice(next.eventCount)).toEqual([]); + expect(streams.map(stream => stream.runId)).toEqual([runId, peer.native!.id]); + expect(streams[1]!.signal!.aborted).toBe(false); + await f.session.interrupt!(); + expect((await f.session.read()).pendingTerminalDelivery).toMatchObject({ providerRunId: peer.native!.id, turnId: next.next.turnId }); + }); + + it.each(["response", "rejection"] as const)("ignores an old create %s after another reconciler proves its terminal", async outcome => { + const peer = new Peer(); distinctFollowup(peer); + const released = deferred(); + const create = peer.createAgent.getMockImplementation()!; + peer.createAgent.mockImplementationOnce(async input => { + const response = await create(input); await released.promise; + if (outcome === "rejection") throw new CursorCloudClientError("http_error", { status: 422 }); + return response; + }); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await peer.created.promise; + peer.getRun.mockResolvedValueOnce({ ...peer.native!, status: "FINISHED" }); + await f.session.reconcile!(); + const next = await nextAuthority(f); + released.resolve(); await new Promise(accept => setImmediate(accept)); + expect(await savedCheckpoint(f.root, f.session)).toEqual(next.checkpoint); + expect(f.events.slice(next.eventCount)).toEqual([]); + await f.session.interrupt!(); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: peer.native!.id, turnId: next.next.turnId } }); + }); + + it("does not bind an old pending Agent read over a newer Run", async () => { + const peer = new Peer(); peer.failCreate = true; distinctFollowup(peer); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + const getAgent = peer.getAgent.getMockImplementation()!; + const oldAgent = await getAgent(peer.native!.agentId); + const released = deferred(); const reading = deferred(); + peer.getAgent.mockImplementationOnce(async () => { reading.resolve(); return released.promise; }); + const oldReconcile = f.session.reconcile!(); await reading.promise; + peer.getRun.mockResolvedValueOnce({ ...peer.native!, status: "FINISHED" }); + await f.session.reconcile!(); + const next = await nextAuthority(f); + released.resolve(oldAgent); await oldReconcile; + expect(await savedCheckpoint(f.root, f.session)).toEqual(next.checkpoint); + expect(f.events.slice(next.eventCount)).toEqual([]); + await f.session.interrupt!(); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: peer.native!.id, turnId: next.next.turnId } }); + }); + + it("keeps an old interrupt from cancelling or clearing the next turn Stop", async () => { + const peer = new Peer(); distinctFollowup(peer); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const previous = { ...peer.native! }; + const oldRead = deferred(), reading = deferred(); + peer.getRun.mockImplementationOnce(async () => { reading.resolve(); return oldRead.promise; }); + const oldStop = f.session.interrupt!(); await reading.promise; + peer.getRun.mockResolvedValueOnce({ ...previous, status: "FINISHED" }); + await f.session.reconcile!(); + const next = await nextAuthority(f); + const currentRead = deferred(), currentReading = deferred(); + peer.getRun.mockImplementationOnce(async () => { currentReading.resolve(); return currentRead.promise; }); + const currentStop = f.session.interrupt!(); await currentReading.promise; + const before = await savedCheckpoint(f.root, f.session); + oldRead.resolve(previous); await oldStop; + expect(await savedCheckpoint(f.root, f.session)).toEqual(before); + expect(peer.cancelRun).not.toHaveBeenCalled(); + const readCount = peer.getRun.mock.calls.length; + const duplicateStop = f.session.interrupt!(); + await new Promise(accept => setImmediate(accept)); + expect(peer.getRun).toHaveBeenCalledTimes(readCount); + currentRead.resolve({ ...peer.native! }); await Promise.all([currentStop, duplicateStop]); + expect(peer.cancelRun).toHaveBeenCalledTimes(1); + expect(peer.cancelRun).toHaveBeenCalledWith(previous.agentId, peer.native!.id, expect.anything()); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: peer.native!.id, turnId: next.next.turnId } }); + }); + + it.each(["fresh", "follow-up"])("restores a provably unsent %s turn after an actual checkpoint publication failure", async phase => { + const peer = new Peer(); distinctFollowup(peer); + const f = await fixture(peer); + if (phase === "follow-up") { + await f.session.startTurn({ message: { role: "user", text: "First task" } }); + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + await f.session.interrupt!(); await acknowledgeTerminal(f.session); + await f.session.attachRun!({ runId: "paperclip-followup" }); + } + const before = await savedCheckpoint(f.root, f.session); + const eventCount = f.events.length; + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + const savedPath = `${checkpointPath}.before-failure`; + await rename(checkpointPath, savedPath); await mkdir(checkpointPath, { mode: 0o700 }); + try { + await expect(f.session.startTurn({ message: { role: "user", text: "No remote request before durable custody" } })).rejects.toThrow(); + } finally { + await rm(checkpointPath, { recursive: true }); await rename(savedPath, checkpointPath); + } + expect(peer.createAgent).toHaveBeenCalledTimes(phase === "fresh" ? 0 : 1); + expect(peer.createRun).not.toHaveBeenCalled(); + expect(await savedCheckpoint(f.root, f.session)).toEqual(before); + expect(f.events.slice(eventCount)).toEqual([]); + const reconciliations = peer.getAgent.mock.calls.length, cancellations = peer.cancelRun.mock.calls.length; + await f.session.interrupt!(); + expect(peer.getAgent).toHaveBeenCalledTimes(reconciliations); expect(peer.cancelRun).toHaveBeenCalledTimes(cancellations); + const snapshot = await f.session.snapshot(); await f.session.close({ reason: "storage_recovered" }); await f.pump; + expect(peer.getAgent).toHaveBeenCalledTimes(reconciliations); expect(peer.cancelRun).toHaveBeenCalledTimes(cancellations); + const recovered = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; + sessions.push(recovered); + expect(await savedCheckpoint(f.root, recovered)).toEqual({ ...before, relayTurnToken: before.relayTurnToken ?? null }); + await recovered.startTurn({ message: { role: "user", text: "Retry after storage recovery" } }); + await waitFor(() => peer.createAgent.mock.calls.length === 1 && peer.createRun.mock.calls.length === (phase === "fresh" ? 0 : 1)); + await recovered.interrupt!(); + }); + + it("retains accepted provider work when its confirmed-identity checkpoint write fails", async () => { + const peer = new Peer(); + const f = await fixture(peer); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + const savedPath = `${checkpointPath}.before-confirmation`; + const create = peer.createAgent.getMockImplementation()!; + peer.createAgent.mockImplementationOnce(async input => { + const response = await create(input); + await rename(checkpointPath, savedPath); await mkdir(checkpointPath, { mode: 0o700 }); + return response; + }); + try { + await f.session.startTurn({ message: { role: "user", text: "Accepted provider work retains its custody" } }); + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + expect(await f.session.read()).toMatchObject({ agentId: peer.native!.agentId, runId, phase: "running" }); + expect(peer.createAgent).toHaveBeenCalledTimes(1); + await expect(f.session.startTurn({ message: { role: "user", text: "No duplicate" } })).rejects.toThrow("unresolved remote work"); + } finally { + await rm(checkpointPath, { recursive: true }); await rename(savedPath, checkpointPath); + } + expect(await savedCheckpoint(f.root, f.session)).toMatchObject({ agentId: peer.native!.agentId, runId, phase: "running", pendingOperation: null }); + await f.session.interrupt!(); + expect(peer.createAgent).toHaveBeenCalledTimes(1); expect(peer.cancelRun).toHaveBeenCalledTimes(1); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { status: "CANCELLED", providerRunId: runId } }); + }); + + it("restores an unsent launch behind a concurrent Stop write after persistence rejects", async () => { + const f = await fixture(); + const before = await savedCheckpoint(f.root, f.session); + const held = deferred(), release = deferred(), stoppingWritten = deferred(); + const failure = new Error("controlled post-publication persistence failure"); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + let intercepted = false; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + const persisted = originalWrite.call(this, value); + if (value.phase === "creating" && !intercepted) { + intercepted = true; + return persisted.then(async () => { held.resolve(); await release.promise; throw failure; }); + } + if (value.phase === "stopping") void persisted.then(() => stoppingWritten.resolve()); + return persisted; + }); + try { + const started = f.session.startTurn({ message: { role: "user", text: "Stop before unsent launch" } }); + const rejected = expect(started).rejects.toBe(failure); + await held.promise; + const stopped = f.session.interrupt!(); await stoppingWritten.promise; + expect(f.peer.createAgent).not.toHaveBeenCalled(); + release.resolve(); await rejected; await stopped; + expect(await savedCheckpoint(f.root, f.session)).toEqual(before); + expect(f.peer.createAgent).not.toHaveBeenCalled(); expect(f.peer.getAgent).not.toHaveBeenCalled(); expect(f.peer.cancelRun).not.toHaveBeenCalled(); + await f.session.startTurn({ message: { role: "user", text: "Next admitted task" } }); await f.peer.created.promise; + await f.session.interrupt!(); + } finally { release.resolve(); write.mockRestore(); } + }); + + it("registers the new turn launch before Stop can enter its initial checkpoint await", async () => { + const peer = new Peer(); distinctFollowup(peer); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "First task" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + await f.session.interrupt!(); await acknowledgeTerminal(f.session); + const held = deferred(), release = deferred(), stoppingWritten = deferred(); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + const persisted = originalWrite.call(this, value); + if (value.phase === "creating") return persisted.then(async () => { held.resolve(); await release.promise; }); + if (value.phase === "stopping") void persisted.then(() => stoppingWritten.resolve()); + return persisted; + }); + try { + const started = f.session.startTurn({ message: { role: "user", text: "Second task" } }); await held.promise; + const stopped = f.session.interrupt!(); await stoppingWritten.promise; + expect(peer.createRun).not.toHaveBeenCalled(); + release.resolve(); + const next = await started; await stopped; + expect(peer.cancelRun).toHaveBeenCalledTimes(2); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: peer.native!.id, turnId: next.turnId, status: "CANCELLED" } }); + } finally { release.resolve(); write.mockRestore(); } + }); + + it("retains a confirmed same-turn Run when its delayed create rejects", async () => { + const peer = new Peer(); + const release = deferred(); + const create = peer.createAgent.getMockImplementation()!; + peer.createAgent.mockImplementationOnce(async input => { await create(input); await release.promise; throw new CursorCloudClientError("http_error", { status: 422 }); }); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Current task" } }); await peer.created.promise; + await f.session.reconcile!(); + const before = await savedCheckpoint(f.root, f.session); + release.resolve(); + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + const after = await savedCheckpoint(f.root, f.session); + expect(after).toEqual({ ...before, sourceSequence: before.sourceSequence + 1 }); + expect(f.events.some(event => event.eventType === "turn.failed")).toBe(false); + await f.session.interrupt!(); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: runId } }); + }); + + it.each(["agent", "run"] as const)("keeps a current terminal with a mismatched %s identity fenced", async identity => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Current task" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const before = await savedCheckpoint(f.root, f.session); + f.peer.getRun.mockResolvedValueOnce({ ...f.peer.native!, status: "FINISHED", ...(identity === "agent" ? { agentId: "bc-different" } : { id: "run-22222222-2222-4222-8222-222222222222" }) }); + await expect(f.session.reconcile!()).rejects.toThrow("confirmed Agent/Run identity"); + expect(await savedCheckpoint(f.root, f.session)).toEqual(before); + await f.session.interrupt!(); + expect(await f.session.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { providerRunId: runId } }); + }); + + it("refuses expired relay authority before remote work while retaining idle recovery for cleanup", async () => { + const f = await fixture(); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const restored = (await new CursorCloudDriver({ ...f.options, relay: { ...f.options.relay, expiresAt: Date.now() - 1 } }).recoverSession(snapshot)).session!; + sessions.push(restored); + await expect(restored.startTurn({ message: { role: "user", text: "Must not launch" } })).rejects.toThrow("relay capability expired"); + expect(f.peer.createAgent).not.toHaveBeenCalled(); expect(f.peer.createRun).not.toHaveBeenCalled(); + await restored.close({ reason: "expired_cleanup" }); + }); + + it("lists exact current Agent artifact paths through its bounded provider-owned read-only helper", async () => { + const f = await fixture(); + f.peer.listArtifacts.mockResolvedValue({ items: [{ path: "artifacts/evidence.txt", sizeBytes: 12, updatedAt: "2026-10-28T00:00:00Z" }] } as any); + await f.session.startTurn({ message: { role: "user", text: "Find the artifact" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const initialized = await rpc(f.options.relay.socketPath, { id: 0, method: "initialize" }, relayHeaders(f.peer)); + const result = await rpc(f.options.relay.socketPath, { id: 1, method: "tools/call", params: { name: "list_cursor_cloud_artifacts", arguments: {} } }, relayHeaders(f.peer), initialized.session); + expect(JSON.parse(result.value.result.content[0].text)).toEqual({ items: [{ path: "artifacts/evidence.txt", sizeBytes: 12 }] }); + expect(f.peer.listArtifacts).toHaveBeenCalledWith(f.peer.native!.agentId, expect.objectContaining({ signal: expect.any(AbortSignal) })); + expect(f.handler).not.toHaveBeenCalled(); + }); + + it("binds revised idle instructions once on same-Agent followup and rejects revised active recovery", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Original task" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const revised = { ...f.options, instructions: "Updated assigned instructions and skill bundle." }; + const restored = (await new CursorCloudDriver(revised).recoverSession(snapshot)).session!; sessions.push(restored); + await acknowledgeTerminal(restored); + await restored.startTurn({ message: { role: "user", text: "Follow up" } }); + await waitFor(() => f.peer.createRun.mock.calls.length === 1); + expect(f.peer.request?.prompt.text).toMatch(/^Updated assigned instructions and skill bundle\.[\s\S]*\n\nPaperclip task:\nFollow up$/); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); + const activeSnapshot = await restored.snapshot(); await restored.detachControllerForRestart!(); + await expect(new CursorCloudDriver(f.options).recoverSession(activeSnapshot)).rejects.toThrow("instructions changed"); + const final = (await new CursorCloudDriver(revised).recoverSession(activeSnapshot)).session!; sessions.push(final); + await final.interrupt!(); + await acknowledgeTerminal(final); + await final.startTurn({ message: { role: "user", text: "One more task" } }); + await waitFor(() => f.peer.createRun.mock.calls.length === 2); + expect(f.peer.request?.prompt.text).toMatch(/\n\nPaperclip task:\nOne more task$/); + expect(f.peer.request?.prompt.text).not.toContain(revised.instructions); + }); + + it("opens without paid work, sends exact model/instructions and current private MCP headers only on turn", async () => { + const f = await fixture(); + expect(cursorCloudDriverDescriptor().capabilities).toMatchObject({ usage: false, unsupported: expect.arrayContaining(["production_usage_accounting"]) }); + expect(f.peer.createAgent).not.toHaveBeenCalled(); + expect((await f.session.read?.())?.effectiveModelAcknowledged).toBe(false); + await f.session.startTurn({ message: { role: "user", text: "Task one" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + expect(f.peer.request).toMatchObject({ model: { id: "explicit-model" }, prompt: { text: expect.stringMatching(/^Follow these exact instructions\.[\s\S]*\n\nPaperclip task:\nTask one$/) }, mcpServers: [{ url: "https://relay.example.test/mcp", headers: { Authorization: "Bearer private-relay-token" } }] }); + expect(f.peer.request).not.toHaveProperty("schema"); + const identity = f.events.filter(event => event.payload.code === "cursor_cloud_remote_identity").map(event => JSON.parse(String(event.payload.message))).find(value => value.runId !== null); + expect(identity).toEqual({ schema: "paperclip.cursor-cloud.remote-identity.v1", provider: "cursor_cloud", agentId: f.peer.native!.agentId, runId, ownerRunId: "paperclip-run", normalizedSessionId: "session", phase: "running" }); + const checkpoint = await readFile(join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!), "utf8"); + expect(checkpoint).not.toContain("private-relay-token"); expect(checkpoint).not.toContain("private-cursor-key"); expect(checkpoint).not.toContain("Task one"); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + expect(f.events.some(event => event.eventType === "run.result.proposed")).toBe(false); + await acknowledgeTerminal(f.session); + await f.session.startTurn({ message: { role: "user", text: "Task two" } }); + await waitFor(() => f.peer.createRun.mock.calls.length === 1); + expect(f.peer.request?.prompt.text).toMatch(/\n\nPaperclip task:\nTask two$/); expect(f.peer.request?.prompt.text).not.toContain(f.options.instructions); expect(f.peer.createAgent).toHaveBeenCalledTimes(1); + }); + + it("delivers the full admitted semantic response through the real Unix MCP bridge, rejects unknown/late calls", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Use a tool" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const path = f.options.relay.socketPath; + expect((await rpc(path, { id: "bad", method: "tools/list" }, "wrong")).status).toBe(401); + const initialized = await rpc(path, { id: 1, method: "initialize" }, relayHeaders(f.peer)); + const response = await rpc(path, { id: "call-1", method: "tools/call", params: { name: "write_note", arguments: { note: "first" } } }, relayHeaders(f.peer), initialized.session); + expect(response.value.result.content[0].text).toContain('"success":true'); + expect(f.handler).toHaveBeenCalledWith(expect.objectContaining({ tool: "write_note", arguments: { note: "first" }, turnId: expect.stringMatching(/^turn-/) })); + await rpc(path, { id: "missing", method: "tools/call", params: { name: "not_admitted", arguments: {} } }, relayHeaders(f.peer), initialized.session); + expect(f.handler).toHaveBeenCalledTimes(1); + await f.session.interrupt!(); + expect(f.peer.cancelRun).toHaveBeenCalledTimes(1); + expect(f.peer.getRun.mock.calls.length).toBeGreaterThanOrEqual(2); + const late = await rpc(path, { id: "late", method: "tools/call", params: { name: "write_note", arguments: { note: "late" } } }, relayHeaders(f.peer), initialized.session); + expect(late.status).toBe(403); expect(f.handler).toHaveBeenCalledTimes(1); + expect((await f.session.read?.())?.providerStatus).toBe("CANCELLED"); + }); + + it("retains only an accepted semantic receipt and waits for actual provider termination", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Finish semantically" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const initialized = await rpc(f.options.relay.socketPath, { id: 0, method: "initialize" }, relayHeaders(f.peer)); + const args = { reportedWorkDisposition: "done", summary: "Completed.", evidence: [], verification: [], completionClaim: { contractRevision: "1", objectiveSatisfied: true, criteria: [], remainingWork: [] } }; + f.handler.mockResolvedValueOnce({ success: false, contentItems: [{ type: "inputText", text: "rejected" }] }); + await rpc(f.options.relay.socketPath, { id: "rejected", method: "tools/call", params: { name: "paperclip_finish", arguments: args } }, relayHeaders(f.peer), initialized.session); + expect((await f.session.read?.())?.semanticCompletionReceipt).toBeNull(); + await rpc(f.options.relay.socketPath, { id: "accepted", method: "tools/call", params: { name: "paperclip_finish", arguments: args } }, relayHeaders(f.peer), initialized.session); + expect((await f.session.read?.())?.semanticCompletionReceipt).toMatchObject({ inputDigest: expect.stringMatching(/^[a-f0-9]{64}$/) }); + expect(f.events.some(event => event.eventType === "turn.completed" || event.eventType === "run.result.proposed")).toBe(false); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + }); + + it("resumes the saved opaque stream cursor without duplicating a replayed text frame", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Reconnect" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + f.peer.cursor = undefined; + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + const replay: PrpEvent[] = []; void (async () => { for await (const event of restored.events()) replay.push(event); })(); + await waitFor(() => f.peer.cursor === "opaque-1"); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => replay.some(event => event.eventType === "turn.completed")); + expect(replay.some(event => event.eventType === "item.delta")).toBe(false); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); + }); + + it("namespaces repeated RPC id zero by initialized MCP session and rejects an old session after a new turn", async () => { + const f = await fixture(); const path = f.options.relay.socketPath; + await f.session.startTurn({ message: { role: "user", text: "First turn" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const first = await rpc(path, { id: 0, method: "initialize" }, relayHeaders(f.peer)); + const second = await rpc(path, { id: 0, method: "initialize" }, relayHeaders(f.peer)); + const call = { id: 0, method: "tools/call", params: { name: "write_note", arguments: { note: "same wire ID" } } }; + await rpc(path, call, relayHeaders(f.peer), first.session); await rpc(path, call, relayHeaders(f.peer), second.session); + expect(f.handler).toHaveBeenCalledTimes(2); + expect(f.handler.mock.calls[0]![0].callId).not.toBe(f.handler.mock.calls[1]![0].callId); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + await acknowledgeTerminal(f.session); + await f.session.startTurn({ message: { role: "user", text: "Next turn" } }); + const third = await rpc(path, { id: 0, method: "initialize" }, relayHeaders(f.peer)); + expect((await rpc(path, call, relayHeaders(f.peer), first.session)).status).toBe(404); + await rpc(path, call, relayHeaders(f.peer), third.session); expect(f.handler).toHaveBeenCalledTimes(3); + }); + + it("rejects prior-turn relay credentials before a fresh MCP initialization", async () => { + const f = await fixture(); const path = f.options.relay.socketPath; + distinctFollowup(f.peer); + await f.session.startTurn({ message: { role: "user", text: "First turn" } }); + await f.peer.created.promise; + const previousHeaders = relayHeaders(f.peer); + const first = await rpc(path, { id: 0, method: "initialize" }, previousHeaders); + expect(first.status).toBe(200); + const call = { id: 1, method: "tools/call", params: { name: "write_note", arguments: { note: "current authority" } } }; + expect((await rpc(path, call, previousHeaders, first.session)).status).toBe(200); + expect(f.handler).toHaveBeenCalledTimes(1); + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + await nextAuthority(f); + const currentHeaders = relayHeaders(f.peer); + expect((await rpc(path, { id: 2, method: "initialize" }, previousHeaders)).status).toBe(401); + expect((await rpc(path, call, previousHeaders, first.session)).status).toBe(401); + expect(f.handler).toHaveBeenCalledTimes(1); + const current = await rpc(path, { id: 3, method: "initialize" }, currentHeaders); + expect(current.status).toBe(200); + expect((await rpc(path, call, currentHeaders, current.session)).status).toBe(200); + expect(f.handler).toHaveBeenCalledTimes(2); + }); + + it("retains the current relay capability on active recovery without exposing it in snapshots or events", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Recover this turn" } }); + await f.peer.created.promise; + const headers = relayHeaders(f.peer); + const token = headers[RUNNER_TOOL_SCOPE_TOKEN_HEADER]!.slice(7); + const snapshot = await f.session.snapshot(); + await f.session.detachControllerForRestart!(); await f.pump; + const restored = (await f.driver.recoverSession(snapshot)).session!; sessions.push(restored); + expect((await rpc(f.options.relay.socketPath, { id: 0, method: "initialize" }, headers)).status).toBe(200); + expect(JSON.stringify(await restored.read())).not.toContain(token); + expect(JSON.stringify(await restored.snapshot())).not.toContain(token); + expect(JSON.stringify(f.events)).not.toContain(token); + expect((await savedCheckpoint(f.root, restored)).relayTurnToken).toBe(token); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); + expect(f.peer.createRun).not.toHaveBeenCalled(); + }); + + it("redacts the current turn capability from provider events and terminal delivery", async () => { + const peer = new Peer(); + peer.streamRun = async function* () { + const token = relayHeaders(this)[RUNNER_TOOL_SCOPE_TOKEN_HEADER]!.slice(7); + yield { id: "capability-text", event: "assistant", data: { text: `Private value ${token}` } }; + this.native!.status = "FINISHED"; this.native!.result = token; + yield { id: "capability-result", event: "result", data: { runId, status: "FINISHED" } }; + }; + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Keep private metadata out of output" } }); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + const token = relayHeaders(peer)[RUNNER_TOOL_SCOPE_TOKEN_HEADER]!.slice(7); + expect(JSON.stringify(f.events)).not.toContain(token); + expect(JSON.stringify(await f.session.read())).not.toContain(token); + expect(f.events.find(event => event.eventType === "item.delta")?.payload.text).toBe("Private value [redacted]"); + expect((await f.session.read()).pendingTerminalDelivery).toMatchObject({ result: "[redacted]" }); + }); + + it("keeps legacy active recovery cleanup-only when its turn capability is absent", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Legacy state" } }); await f.peer.created.promise; + const headers = relayHeaders(f.peer); const checkpoint = await savedCheckpoint(f.root, f.session); + const snapshot = await f.session.snapshot(); + await f.session.detachControllerForRestart!(); await f.pump; + delete checkpoint.relayTurnToken; + const path = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + await writeFile(path, JSON.stringify(checkpoint), { mode: 0o600 }); + const restored = (await f.driver.recoverSession(snapshot)).session!; sessions.push(restored); + expect((await rpc(f.options.relay.socketPath, { id: 0, method: "initialize" }, headers)).status).toBe(403); + await restored.interrupt(); + expect(f.peer.cancelRun).toHaveBeenCalledTimes(1); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); + expect(f.peer.createRun).not.toHaveBeenCalled(); + }); + + it("recovers an ambiguous create by saved agent identity, without another create or caller model acknowledgment", async () => { + const peer = new Peer(); peer.failCreate = true; + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Ambiguous create" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + const snapshot = await f.session.snapshot(); + await f.session.detachControllerForRestart!(); await f.pump; + const result = await new CursorCloudDriver(f.options).recoverSession(snapshot); + expect(result.recovered).toBe(true); const restored = result.session!; sessions.push(restored); + await waitFor(() => peer.getAgent.mock.calls.length > 0); + expect(peer.createAgent).toHaveBeenCalledTimes(1); + expect((await restored.read?.())?.effectiveModelAcknowledged).toBe(false); + await restored.interrupt!(); + const restoredSnapshot = await restored.snapshot(); await restored.close({ reason: "done" }); + await expect(new CursorCloudDriver({ ...f.options, model: "different-model" }).recoverSession(restoredSnapshot)).rejects.toThrow("changed"); + }); + + it.each([401, 403, 404, 422])("retains a saved ambiguous create identity when reconciliation returns HTTP %s", async status => { + const peer = new Peer(); peer.failCreate = true; + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Accepted remotely but response lost" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!); + const before = JSON.parse(await readFile(checkpointPath, "utf8")); + const getAgent = peer.getAgent.getMockImplementation()!; + peer.getAgent.mockRejectedValue(new CursorCloudClientError("http_error", { status })); + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + const events: PrpEvent[] = []; void (async () => { for await (const event of restored.events()) events.push(event); })(); + await waitFor(() => events.some(event => event.payload.code === "cursor_cloud_remote_state_unknown")); + await restored.snapshot(); + const after = JSON.parse(await readFile(checkpointPath, "utf8")); + expect(after).toMatchObject({ phase: "creating", pendingOperation: "create_agent", requestedAgentId: before.requestedAgentId, idempotencyKey: before.idempotencyKey, requestDigest: before.requestDigest }); + expect(after.requestedAgentId).toMatch(/^bc-/); + await expect(restored.startTurn({ message: { role: "user", text: "Must not replace uncertain work" } })).rejects.toThrow("unresolved remote work"); + expect(peer.createAgent).toHaveBeenCalledTimes(1); expect(peer.createRun).not.toHaveBeenCalled(); + peer.getAgent.mockImplementation(getAgent); await restored.interrupt!(); + }); + + it("allows a definitive direct mutation rejection to settle without pretending work was accepted", async () => { + const peer = new Peer(); + peer.createAgent.mockRejectedValue(new CursorCloudClientError("http_error", { status: 422 })); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Invalid native request" } }); + await waitFor(() => f.events.some(event => event.eventType === "turn.failed")); + expect(await f.session.read?.()).toMatchObject({ phase: "idle", providerStatus: "REJECTED" }); + expect(f.events.some(event => event.eventType === "turn.failed" && event.payload.remoteWorkAccepted === false)).toBe(true); + }); + + it.each(["fresh", "follow-up"] as const)("settles an encoded request rejected before fetch for a %s turn", async phase => { + const peer = new Peer(); + const { client, fetch } = maintainedMutations(peer); + const f = await fixture(peer, { client }); + if (phase === "follow-up") { + await f.session.startTurn({ message: { role: "user", text: "Previous accepted task" } }); + await peer.created.promise; + await f.session.interrupt!(); await acknowledgeTerminal(f.session); + } + const before = { fetch: fetch.mock.calls.length, getAgent: peer.getAgent.mock.calls.length, getRun: peer.getRun.mock.calls.length, cancel: peer.cancelRun.mock.calls.length }; + const text = "\u0001".repeat(400_000); + expect(Buffer.byteLength(text)).toBeLessThanOrEqual(1_048_576); + expect(Buffer.byteLength(JSON.stringify({ prompt: { text } }))).toBeGreaterThan(2_097_152); + const turn = await f.session.startTurn({ message: { role: "user", text } }); + await waitFor(() => f.events.some(event => event.turnId === turn.turnId && + (event.eventType === "turn.failed" || event.payload.code === "cursor_cloud_remote_state_unknown"))); + expect(fetch).toHaveBeenCalledTimes(before.fetch); + expect(await f.session.read()).toMatchObject({ phase: "idle", providerStatus: "REJECTED" }); + expect(f.events.some(event => event.turnId === turn.turnId && event.eventType === "turn.failed" && event.payload.remoteWorkAccepted === false)).toBe(true); + await f.session.interrupt!(); + expect(peer.getAgent).toHaveBeenCalledTimes(before.getAgent); + expect(peer.getRun).toHaveBeenCalledTimes(before.getRun); + expect(peer.cancelRun).toHaveBeenCalledTimes(before.cancel); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart(); await f.pump; + const recovered = await new CursorCloudDriver(f.options).recoverSession(snapshot); + expect(recovered.recovered).toBe(true); + const restored = recovered.session!; sessions.push(restored); + expect(await restored.read()).toMatchObject({ phase: "idle", providerStatus: "REJECTED" }); + await restored.attachRun!({ runId: "paperclip-after-size-rejection" }); + distinctFollowup(peer); peer.release = deferred(); + const next = await restored.startTurn({ message: { role: "user", text: "A smaller admitted task" } }); + await vi.waitFor(async () => expect(await restored.read()).toMatchObject({ phase: "running", turnId: next.turnId })); + expect(fetch).toHaveBeenCalledTimes(before.fetch + 1); + await restored.interrupt!(); + }); + + it.each(["fresh", "follow-up"] as const)("keeps a %s oversized response fenced after the mutation was sent", async phase => { + const peer = new Peer(); + const mutations = maintainedMutations(peer, 1024); + const f = await fixture(peer, { client: mutations.client }); + if (phase === "follow-up") { + await f.session.startTurn({ message: { role: "user", text: "Previous accepted task" } }); + await peer.created.promise; await f.session.interrupt!(); await acknowledgeTerminal(f.session); + } + const before = mutations.fetch.mock.calls.length; + mutations.fetch.mockImplementationOnce(async (url, init) => { + const input = JSON.parse(String(init?.body)); + const accepted = new URL(String(url)).pathname === "/v1/agents" ? await peer.createAgent(input) : await peer.createRun(peer.native!.agentId, input); + return new Response(JSON.stringify({ ...accepted, padding: "x".repeat(2048) }), { headers: { "content-type": "application/json" } }); + }); + const turn = await f.session.startTurn({ message: { role: "user", text: "Remote work may have started" } }); + await waitFor(() => f.events.some(event => event.turnId === turn.turnId && event.payload.code === "cursor_cloud_remote_state_unknown")); + expect(mutations.fetch).toHaveBeenCalledTimes(before + 1); + expect(await f.session.read()).toMatchObject({ phase: "creating" }); + expect(f.events.some(event => event.turnId === turn.turnId && event.payload.remoteWorkAccepted === false)).toBe(false); + await expect(f.session.startTurn({ message: { role: "user", text: "Do not replace uncertain work" } })).rejects.toThrow("unresolved remote work"); + }); + + it.each((["fresh", "follow-up"] as const).flatMap(phase => + (["stop_write", "rejection_write"] as const).flatMap(overlap => + (["http_422", "unsent_payload"] as const).map(rejection => ({ phase, overlap, rejection }))))) ( + "commits a rejected $phase create across $overlap before Stop and the next turn ($rejection)", async ({ phase, overlap, rejection }) => { + const peer = new Peer(); + const mutations = rejection === "unsent_payload" ? maintainedMutations(peer) : null; + const f = await fixture(peer, mutations ? { client: mutations.client } : {}); + if (phase === "follow-up") { + await f.session.startTurn({ message: { role: "user", text: "Previous accepted task" } }); + await peer.created.promise; + await f.session.interrupt!(); + await acknowledgeTerminal(f.session); + } + const entered = deferred(), rejectCreate = deferred(), stopHeld = deferred(), releaseStop = deferred(); + const rejectionHeld = deferred(), releaseRejection = deferred(); + if (!mutations) { + (phase === "fresh" ? peer.createAgent : peer.createRun).mockImplementationOnce(async () => { + entered.resolve(); await rejectCreate.promise; + throw new CursorCloudClientError("http_error", { status: 422 }); + }); + } else if (phase === "fresh") { + const create = mutations.client.createAgent; + mutations.client.createAgent = async (input, options) => { entered.resolve(); await rejectCreate.promise; return create(input, options); }; + } else { + const create = mutations.client.createRun; + mutations.client.createRun = async (id, input, options) => { entered.resolve(); await rejectCreate.promise; return create(id, input, options); }; + } + const fetchesBefore = mutations?.fetch.mock.calls.length; + const before = { getAgent: peer.getAgent.mock.calls.length, getRun: peer.getRun.mock.calls.length, cancel: peer.cancelRun.mock.calls.length }; + const originalWrite = CursorCloudCheckpointStore.prototype.write; + let pausedStop = false, pausedRejection = false; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + if (value.phase === "idle" && value.terminalStatus === "REJECTED" && !pausedRejection) { + pausedRejection = true; rejectionHeld.resolve(); + return releaseRejection.promise.then(() => originalWrite.call(this, value)); + } + const persisted = originalWrite.call(this, value); + if (value.phase === "stopping" && !pausedStop) { + pausedStop = true; + return persisted.then(async () => { stopHeld.resolve(); if (overlap === "stop_write") await releaseStop.promise; }); + } + return persisted; + }); + let stopDone = false; + let stopped: Promise<{ error: unknown | null }> | undefined; + const stop = () => stopped = f.session.interrupt!().then(() => ({ error: null }), error => ({ error })) + .finally(() => { stopDone = true; }); + try { + const turn = await f.session.startTurn({ message: { role: "user", text: rejection === "unsent_payload" ? "\u0001".repeat(400_000) : "Rejected task" } }); + await entered.promise; + if (overlap === "stop_write") { + stop(); await stopHeld.promise; + rejectCreate.resolve(); await new Promise(accept => setImmediate(accept)); + releaseStop.resolve(); + await waitFor(() => pausedRejection || stopDone); + expect(pausedRejection, "the definite rejection must reach durable settlement even while stopping").toBe(true); + } else { + rejectCreate.resolve(); await rejectionHeld.promise; + stop(); await new Promise(accept => setImmediate(accept)); + } + expect(stopDone, "Stop must wait for the rejected-create checkpoint").toBe(false); + expect(await f.session.read()).toMatchObject({ phase: "stopping" }); + await expect(f.session.startTurn({ message: { role: "user", text: "Too early" } })).rejects.toThrow("unresolved remote work"); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + expect(JSON.parse(await readFile(checkpointPath, "utf8")).phase).not.toBe("idle"); + releaseRejection.resolve(); + expect(await stopped).toEqual({ error: null }); + await waitFor(() => f.events.some(event => event.turnId === turn.turnId && event.eventType === "turn.failed" && event.payload.remoteWorkAccepted === false)); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "idle", terminalStatus: "REJECTED", pendingOperation: null, requestedAgentId: null }); + expect(peer.getAgent).toHaveBeenCalledTimes(before.getAgent); + expect(peer.getRun).toHaveBeenCalledTimes(before.getRun); + expect(peer.cancelRun).toHaveBeenCalledTimes(before.cancel); + if (mutations) expect(mutations.fetch).toHaveBeenCalledTimes(fetchesBefore!); + const snapshot = await f.session.snapshot(); + await f.session.detachControllerForRestart(); await f.pump; + const recovered = await new CursorCloudDriver(f.options).recoverSession(snapshot); + expect(recovered.recovered).toBe(true); + const restored = recovered.session!; sessions.push(restored); + await restored.attachRun!({ runId: "paperclip-after-rejection" }); + distinctFollowup(peer); peer.release = deferred(); + const next = await restored.startTurn({ message: { role: "user", text: "Next admitted task" } }); + await vi.waitFor(async () => expect(await restored.read()).toMatchObject({ phase: "running", turnId: next.turnId })); + await restored.interrupt!(); + expect(await restored.read()).toMatchObject({ phase: "terminal", pendingTerminalDelivery: { turnId: next.turnId } }); + } finally { + rejectCreate.resolve(); releaseStop.resolve(); releaseRejection.resolve(); + await stopped; write.mockRestore(); + } + }); + + it.each(["snapshot", "reconcile", "detachControllerForRestart"] as const)("orders %s after an in-flight definite rejection checkpoint", async operation => { + const peer = new Peer(); + peer.createAgent.mockRejectedValue(new CursorCloudClientError("http_error", { status: 422 })); + const f = await fixture(peer), held = deferred(), release = deferred(); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + let paused = false; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + if (value.phase === "idle" && value.terminalStatus === "REJECTED" && !paused) { + paused = true; held.resolve(); return release.promise.then(() => originalWrite.call(this, value)); + } + return originalWrite.call(this, value); + }); + let done = false; + let called: Promise | undefined; + try { + await f.session.startTurn({ message: { role: "user", text: "Rejected task" } }); await held.promise; + called = f.session[operation]!().finally(() => { done = true; }); + await new Promise(accept => setImmediate(accept)); + expect(done).toBe(false); + expect(await f.session.read()).toMatchObject({ phase: "creating" }); + release.resolve(); await called; + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "idle", terminalStatus: "REJECTED", pendingOperation: null }); + expect(peer.getAgent).not.toHaveBeenCalled(); expect(peer.getRun).not.toHaveBeenCalled(); + } finally { release.resolve(); await called; write.mockRestore(); } + }); + + it("does not let a stale create error replace the current rejection custody barrier", async () => { + const peer = new Peer(), oldReleased = deferred(); + const create = peer.createAgent.getMockImplementation()!; + peer.createAgent.mockImplementationOnce(async input => { await create(input); await oldReleased.promise; throw new CursorCloudClientError("http_error", { status: 422 }); }); + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Previously accepted task" } }); await peer.created.promise; + peer.getRun.mockResolvedValueOnce({ ...peer.native!, status: "FINISHED" }); + await f.session.reconcile!(); await acknowledgeTerminal(f.session); await f.session.attachRun!({ runId: "current-owner" }); + peer.createRun.mockRejectedValue(new CursorCloudClientError("http_error", { status: 422 })); + const held = deferred(), release = deferred(), originalWrite = CursorCloudCheckpointStore.prototype.write; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + if (value.phase === "idle" && value.terminalStatus === "REJECTED") { held.resolve(); return release.promise.then(() => originalWrite.call(this, value)); } + return originalWrite.call(this, value); + }); + let snapshot: Promise | undefined, done = false; + try { + await f.session.startTurn({ message: { role: "user", text: "Current rejected task" } }); await held.promise; + oldReleased.resolve(); await new Promise(accept => setImmediate(accept)); + snapshot = f.session.snapshot().finally(() => { done = true; }); + await new Promise(accept => setImmediate(accept)); + expect(done, "the current rejected-create custody gate survives a stale error").toBe(false); + release.resolve(); await snapshot; + expect(await savedCheckpoint(f.root, f.session)).toMatchObject({ phase: "idle", ownerRunId: "current-owner", terminalStatus: "REJECTED", pendingOperation: null }); + } finally { oldReleased.resolve(); release.resolve(); await snapshot; write.mockRestore(); } + }); + + it.each((["fresh", "follow-up"] as const).flatMap(phase => + (["http_422", "unsent_payload"] as const).map(rejection => ({ phase, rejection })), + ))("keeps a rejected $phase create fenced when its settlement cannot commit ($rejection)", async ({ phase, rejection }) => { + const peer = new Peer(), mutations = rejection === "unsent_payload" ? maintainedMutations(peer) : null; + const f = await fixture(peer, mutations ? { client: mutations.client } : {}); + if (phase === "follow-up") { + await f.session.startTurn({ message: { role: "user", text: "Previous accepted task" } }); await peer.created.promise; + await f.session.interrupt!(); await acknowledgeTerminal(f.session); + } + const entered = deferred(), rejected = deferred(); + if (mutations) { + const launch = phase === "fresh" ? mutations.client.createAgent : mutations.client.createRun; + vi.spyOn(mutations.client, phase === "fresh" ? "createAgent" : "createRun").mockImplementationOnce(async (...args: unknown[]) => { + entered.resolve(); await rejected.promise; + return (launch as (...values: unknown[]) => Promise)(...args); + }); + } else (phase === "fresh" ? peer.createAgent : peer.createRun).mockImplementationOnce(async () => { + entered.resolve(); await rejected.promise; throw new CursorCloudClientError("http_error", { status: 422 }); + }); + peer.getAgent.mockRejectedValue(new CursorCloudClientError("http_error", { status: 404 })); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + return value.phase === "idle" && value.terminalStatus === "REJECTED" + ? Promise.reject(new Error("injected rejection checkpoint failure")) : originalWrite.call(this, value); + }); + try { + const before = mutations?.fetch.mock.calls.length; + const turn = await f.session.startTurn({ message: { role: "user", text: mutations ? "\u0001".repeat(400_000) : "Rejected task" } }); await entered.promise; + const stopped = f.session.interrupt!().then(() => null, error => error); + rejected.resolve(); + expect(await stopped).toMatchObject({ message: expect.stringContaining("remains fenced") }); + if (mutations) expect(mutations.fetch).toHaveBeenCalledTimes(before!); + expect(await f.session.read()).toMatchObject({ phase: "stopping", turnId: turn.turnId }); + await expect(f.session.startTurn({ message: { role: "user", text: "Cannot replace unresolved custody" } })).rejects.toThrow("unresolved remote work"); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => /^checkpoint-.*\.json$/.test(name))!); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "stopping", pendingOperation: phase === "fresh" ? "create_agent" : "create_run", terminalStatus: null }); + expect(f.events.some(event => event.turnId === turn.turnId && event.payload.remoteWorkAccepted === false)).toBe(false); + } finally { rejected.resolve(); write.mockRestore(); } + }); + + it.each(["ambiguous", "server_failure"] as const)("does not classify a concurrent Stop with %s create outcome as definite no-work", async outcome => { + const peer = new Peer(), entered = deferred(), released = deferred(); + peer.createAgent.mockImplementationOnce(async () => { + entered.resolve(); await released.promise; + throw outcome === "ambiguous" ? new TypeError("response lost") : new CursorCloudClientError("http_error", { status: 503 }); + }); + peer.getAgent.mockRejectedValue(new CursorCloudClientError("http_error", { status: 404 })); + const f = await fixture(peer), turn = await f.session.startTurn({ message: { role: "user", text: "Unknown create" } }); + await entered.promise; + const stopped = f.session.interrupt!().then(() => null, error => error); released.resolve(); + expect(await stopped).toMatchObject({ message: expect.stringContaining("remains fenced") }); + expect(await savedCheckpoint(f.root, f.session)).toMatchObject({ phase: "stopping", pendingOperation: "create_agent", terminalStatus: null }); + expect(f.events.some(event => event.turnId === turn.turnId && event.payload.remoteWorkAccepted === false)).toBe(false); + await expect(f.session.startTurn({ message: { role: "user", text: "No replacement" } })).rejects.toThrow("unresolved remote work"); + }); + + it("retains unconfirmed Stop as fenced active work, never emits a terminal on cancel acknowledgment alone", async () => { + const peer = new Peer(); peer.cancelRun = vi.fn(async () => ({ id: runId })); + const f = await fixture(peer, { cancelTimeoutMs: 120 }); + await f.session.startTurn({ message: { role: "user", text: "Keep running" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + await expect(f.session.interrupt!()).rejects.toThrow("did not confirm"); + expect(f.events.some(event => event.eventType === "turn.interrupted" || event.eventType === "turn.completed")).toBe(false); + expect((await f.session.read?.())?.phase).toBe("stopping"); + await expect(f.session.startTurn({ message: { role: "user", text: "New work" } })).rejects.toThrow("unresolved"); + peer.native!.status = "CANCELLED"; + }); + + it("releases a private stale Unix socket only after its real child owner was killed", async () => { + const f = await fixture(); const snapshot = await f.session.snapshot(); await f.session.close({ reason: "initial_idle" }); await f.pump; + const { client: _client, dynamicToolHandler: _handler, ...childOptions } = f.options; + const script = `import {CursorCloudDriver} from ${JSON.stringify(new URL("./cursor-cloud-driver.ts", import.meta.url).href)}; process.umask(0o022); const driver=new CursorCloudDriver({...JSON.parse(process.argv[1]),dynamicToolHandler:async()=>{throw new Error('Unexpected tool call')}}); await driver.recoverSession(JSON.parse(process.argv[2])); process.stdout.write('ready\\n');`; + const child = spawn(process.execPath, ["--import", new URL("../../../node_modules/tsx/dist/loader.mjs", import.meta.url).pathname, "--input-type=module", "-e", script, JSON.stringify(childOptions), JSON.stringify(snapshot)], { stdio: ["ignore", "pipe", "pipe"] }); + let errors = ""; child.stderr!.on("data", chunk => { errors += chunk; }); + try { + await Promise.race([once(child.stdout!, "data"), once(child, "exit").then(() => { throw new Error(`Controlled driver child exited before readiness: ${errors}`); })]); + expect((await lstat(f.options.relay.socketPath)).mode & 0o777).toBe(0o600); + const exited = once(child, "exit"); child.kill("SIGKILL"); await exited; + } + finally { child.kill("SIGKILL"); } + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + expect((await restored.read?.())?.phase).toBe("idle"); expect(f.peer.createAgent).not.toHaveBeenCalled(); + }); + + it("refuses a live checkpoint owner and never removes an unknown file at the socket path", async () => { + const f = await fixture(); const snapshot = await f.session.snapshot(); + await expect(new CursorCloudDriver(f.options).recoverSession(snapshot)).rejects.toThrow("live owner"); + await f.session.close({ reason: "idle" }); await f.pump; + await writeFile(f.options.relay.socketPath, "unowned file", { mode: 0o600 }); + await expect(new CursorCloudDriver(f.options).recoverSession(snapshot)).rejects.toThrow("without safe dead-owner"); + expect(await readFile(f.options.relay.socketPath, "utf8")).toBe("unowned file"); + }); + + it("retries a failed terminal checkpoint save without ending its active delivery obligation", async () => { + const f = await fixture(new Peer(), { cancelTimeoutMs: 1_000, config: { + schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo" }], timeoutMs: 10_000, + } }); + const started = await f.session.startTurn({ message: { role: "user", text: "Save the final answer durably" } }); + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const before = await savedCheckpoint(f.root, f.session); + const checkpointPath = join(f.root, `checkpoint-${cursorCloudDigest("session")}.json`); + const backupPath = `${checkpointPath}.before-terminal`; + const failed = deferred(), releaseRetry = deferred(); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + const attempts: Array> = []; + let injected = false; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(async function(value) { + if (this.path !== checkpointPath || value.phase !== "terminal") return originalWrite.call(this, value); + attempts.push(structuredClone(value.pendingTerminalDelivery)); + if (injected) { await releaseRetry.promise; return originalWrite.call(this, value); } + injected = true; + await rename(checkpointPath, backupPath); + await mkdir(checkpointPath, { mode: 0o700 }); + let failure: unknown; + try { await originalWrite.call(this, value); } + catch (error) { failure = error; } + finally { + await rm(checkpointPath, { recursive: true }); + await rename(backupPath, checkpointPath); + } + failed.resolve(failure); + if (!failure) throw new Error("The controlled checkpoint rename must fail"); + throw failure; + }); + try { + f.peer.native!.status = "FINISHED"; f.peer.native!.result = "Durable final answer"; f.peer.release.resolve(); + expect(await failed.promise).toMatchObject({ code: "EISDIR" }); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "running", deadlineAt: before.deadlineAt }); + expect(f.events.filter(event => event.turnId === started.turnId && event.eventType === "turn.completed")).toHaveLength(0); + releaseRetry.resolve(); + await waitFor(() => f.events.some(event => event.turnId === started.turnId && event.eventType === "turn.completed")); + const pending = (await f.session.read()).pendingTerminalDelivery; + expect(attempts.length).toBeGreaterThanOrEqual(2); + expect(attempts.every(delivery => JSON.stringify(delivery) === JSON.stringify(pending))).toBe(true); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "terminal", deadlineAt: null, pendingTerminalDelivery: pending }); + expect(f.events.filter(event => event.eventType === "item.completed" && event.payload.channel === "final")).toHaveLength(1); + expect(f.events.filter(event => event.eventType === "turn.completed")).toHaveLength(1); + expect(f.peer.createAgent).toHaveBeenCalledOnce(); expect(f.peer.createRun).not.toHaveBeenCalled(); expect(f.peer.cancelRun).not.toHaveBeenCalled(); + } finally { releaseRetry.resolve(); write.mockRestore(); } + }); + + it.each(["FINISHED", "ERROR"] as const)("fences late tools and serializes a pending %s checkpoint with Stop, reconciliation and snapshots", async status => { + const f = await fixture(); + const started = await f.session.startTurn({ message: { role: "user", text: "Complete this exact run" } }); + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const initialized = await rpc(f.options.relay.socketPath, { id: "initialize", method: "initialize" }, relayHeaders(f.peer)); + const checkpointPath = join(f.root, `checkpoint-${cursorCloudDigest("session")}.json`); + const held = deferred(), release = deferred(); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + let paused = false; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + if (this.path === checkpointPath && value.phase === "terminal" && !paused) { + paused = true; held.resolve(); return release.promise.then(() => originalWrite.call(this, value)); + } + return originalWrite.call(this, value); + }); + try { + f.peer.native!.status = status; f.peer.native!.result = "One terminal answer"; f.peer.release.resolve(); + await held.promise; + expect(await f.session.read()).toMatchObject({ phase: "running", semanticCompletionReceipt: null }); + const late = await rpc(f.options.relay.socketPath, { id: "late", method: "tools/call", params: { name: "write_note", arguments: { note: "No authority after provider termination" } } }, relayHeaders(f.peer), initialized.session); + expect(late.status).toBe(403); expect(f.handler).not.toHaveBeenCalled(); + let stopped = false, reconciled = false, snapshotted = false; + const stop = f.session.interrupt!().finally(() => { stopped = true; }); + const reconcile = f.session.reconcile!().finally(() => { reconciled = true; }); + const snapshot = f.session.snapshot().finally(() => { snapshotted = true; }); + await new Promise(accept => setImmediate(accept)); + expect({ stopped, reconciled, snapshotted }).toEqual({ stopped: false, reconciled: false, snapshotted: false }); + await expect(f.session.startTurn({ message: { role: "user", text: "No replacement" } })).rejects.toThrow("unresolved remote work"); + await expect(f.session.attachRun!({ runId: "different-owner" })).rejects.toThrow("active run"); + release.resolve(); await Promise.all([stop, reconcile, snapshot]); + const terminalEvent = status === "FINISHED" ? "turn.completed" : "turn.failed"; + await waitFor(() => f.events.some(event => event.turnId === started.turnId && event.eventType === terminalEvent)); + const state = await f.session.read(); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "terminal", deadlineAt: null, pendingTerminalDelivery: state.pendingTerminalDelivery }); + expect(f.events.filter(event => event.eventType === "item.completed" && event.payload.channel === "final")).toHaveLength(1); + expect(f.events.filter(event => event.eventType === terminalEvent)).toHaveLength(1); + expect(f.peer.cancelRun).not.toHaveBeenCalled(); + } finally { release.resolve(); write.mockRestore(); } + }); + + it("retains a failed terminal batch after bounded retries and preserves its event sequence on recovery", async () => { + const f = await fixture(new Peer(), { cancelTimeoutMs: 30, config: { + schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo" }], timeoutMs: 10_000, + } }); + await f.session.startTurn({ message: { role: "user", text: "Retain the completed result while storage is unavailable" } }); + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const before = await savedCheckpoint(f.root, f.session); + const checkpointPath = join(f.root, `checkpoint-${cursorCloudDigest("session")}.json`); + const originalWrite = CursorCloudCheckpointStore.prototype.write; + const deliveries: unknown[] = []; + let unavailable = true; + const write = vi.spyOn(CursorCloudCheckpointStore.prototype, "write").mockImplementation(function(value) { + if (this.path === checkpointPath && value.phase === "terminal") { + deliveries.push(structuredClone(value.pendingTerminalDelivery)); + if (unavailable) return Promise.reject(Object.assign(new Error("controlled unavailable checkpoint storage"), { code: "ENOSPC" })); + } + return originalWrite.call(this, value); + }); + try { + f.peer.native!.status = "FINISHED"; f.peer.native!.result = "Exact retained result"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.payload.code === "cursor_cloud_terminal_checkpoint_pending")); + await expect(f.session.reconcile!()).rejects.toThrow("terminal checkpoint"); + expect(await f.session.read()).toMatchObject({ phase: "running", pendingTerminalDelivery: null }); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "running", deadlineAt: before.deadlineAt, pendingTerminalDelivery: null }); + await expect(f.session.startTurn({ message: { role: "user", text: "No new provider work" } })).rejects.toThrow("unresolved remote work"); + const reads = f.peer.getRun.mock.calls.length; + unavailable = false; + await f.session.reconcile!(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + const pending = (await f.session.read()).pendingTerminalDelivery; + expect(deliveries.every(delivery => JSON.stringify(delivery) === JSON.stringify(pending))).toBe(true); + const sequences = f.events.map(event => event.sourceSeq); + expect(new Set(f.events.map(event => event.sourceEventId)).size).toBe(f.events.length); + expect(sequences.every((seq, index) => index === 0 || seq === sequences[index - 1]! + 1)).toBe(true); + const snapshot = await f.session.snapshot(); + expect(snapshot.lastSourceSequence).toBe(sequences.at(-1)); + expect(JSON.parse(await readFile(checkpointPath, "utf8"))).toMatchObject({ phase: "terminal", sourceSequence: sequences.at(-1), pendingTerminalDelivery: pending }); + expect(f.events.filter(event => event.eventType === "turn.completed")).toHaveLength(1); + expect(f.peer.getRun).toHaveBeenCalledTimes(reads); expect(f.peer.createAgent).toHaveBeenCalledOnce(); + expect(f.peer.createRun).not.toHaveBeenCalled(); expect(f.peer.cancelRun).not.toHaveBeenCalled(); + } finally { unavailable = false; write.mockRestore(); } + }); + + it("retains the exact terminal delivery across restart until its receipt is acknowledged", async () => { + const f = await fixture(); + const started = await f.session.startTurn({ message: { role: "user", text: "Retain the final result" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + f.peer.native!.result = "Recovered final private-cursor-key private-relay-token"; + f.peer.native!.status = "FINISHED"; f.peer.release.resolve(); + await waitFor(() => f.events.some(event => event.eventType === "turn.completed")); + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!); + expect(JSON.parse(await readFile(checkpointPath, "utf8")).sourceSequence).toBe(f.events.find(event => event.eventType === "turn.completed")!.sourceSeq); + const pending = (await f.session.read?.())?.pendingTerminalDelivery as Record; + expect(pending).toMatchObject({ schema: "paperclip.cursor-cloud.terminal-delivery.v1", threadId: "session", turnId: started.turnId, providerRunId: runId, status: "FINISHED", interrupted: false, result: "Recovered final [redacted] [redacted]", receiptId: expect.any(String) }); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + expect((await restored.read?.())?.pendingTerminalDelivery).toEqual(pending); + await expect(restored.startTurn({ message: { role: "user", text: "Must not replace the pending receipt" } })).rejects.toThrow("terminal delivery"); + await expect(restored.acknowledgeTerminalDelivery({ turnId: started.turnId, receiptId: "wrong" })).rejects.toThrow("receipt"); + expect((await restored.read?.())?.pendingTerminalDelivery).toEqual(pending); + await restored.acknowledgeTerminalDelivery({ turnId: started.turnId, receiptId: pending.receiptId as string }); + expect((await restored.read?.())?.pendingTerminalDelivery).toBeNull(); + const acknowledged = await restored.snapshot(); await restored.detachControllerForRestart!(); + const final = (await new CursorCloudDriver(f.options).recoverSession(acknowledged)).session!; sessions.push(final); + expect((await final.read?.())?.pendingTerminalDelivery).toBeNull(); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); expect(f.peer.createRun).not.toHaveBeenCalled(); + }); + + it.each(["agent", "run"])("retries a transient recovery %s read without replacing work or extending its deadline", async read => { + const peer = new Peer(); peer.failCreate = read === "agent"; + const f = await fixture(peer); + await f.session.startTurn({ message: { role: "user", text: "Recover the existing work" } }); await peer.created.promise; + await waitFor(() => f.events.some(event => read === "agent" ? event.payload.code === "cursor_cloud_remote_state_unknown" : event.eventType === "item.delta")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!); + const deadlineAt = JSON.parse(await readFile(checkpointPath, "utf8")).deadlineAt; + const error = new CursorCloudClientError("http_error", { status: 503 }); + if (read === "agent") peer.getAgent.mockRejectedValueOnce(error); + else peer.getRun.mockRejectedValueOnce(error); + const stream = vi.spyOn(peer, "streamRun"); + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + await waitFor(() => stream.mock.calls.length > 0); + expect(peer.createAgent).toHaveBeenCalledTimes(1); expect(peer.createRun).not.toHaveBeenCalled(); + expect(JSON.parse(await readFile(checkpointPath, "utf8")).deadlineAt).toBe(deadlineAt); + await restored.interrupt!(); + }); + + it("enforces the saved deadline while the first recovery read remains pending", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Recover with a slow read" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const checkpointPath = join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!); + const checkpoint = JSON.parse(await readFile(checkpointPath, "utf8")); + checkpoint.deadlineAt = Date.now() + 100; await writeFile(checkpointPath, JSON.stringify(checkpoint), { mode: 0o600 }); + const blocked = deferred(); + const getRun = f.peer.getRun.getMockImplementation()!; + f.peer.getRun.mockImplementationOnce(() => blocked.promise); + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + try { + await waitFor(() => f.peer.cancelRun.mock.calls.length === 1); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); expect(f.peer.createRun).not.toHaveBeenCalled(); + await vi.waitFor(async () => expect((await restored.read?.())?.phase).toBe("terminal")); + } finally { blocked.resolve(await getRun()); } + }); + + it("treats an expired persisted active deadline as cleanup-only instead of buying another full turn", async () => { + const f = await fixture(); + await f.session.startTurn({ message: { role: "user", text: "Expire during outage" } }); await f.peer.created.promise; + await waitFor(() => f.events.some(event => event.eventType === "item.delta")); + const snapshot = await f.session.snapshot(); await f.session.detachControllerForRestart!(); await f.pump; + const path = join(f.root, (await readdir(f.root)).find(name => name.endsWith(".json"))!); + const checkpoint = JSON.parse(await readFile(path, "utf8")); expect(checkpoint.deadlineAt).toBeGreaterThan(Date.now()); + checkpoint.deadlineAt = Date.now() - 1; await writeFile(path, JSON.stringify(checkpoint), { mode: 0o600 }); + const restored = (await new CursorCloudDriver(f.options).recoverSession(snapshot)).session!; sessions.push(restored); + await waitFor(() => f.peer.cancelRun.mock.calls.length === 1); + await waitFor(() => f.peer.native!.status === "CANCELLED"); + expect(f.peer.createAgent).toHaveBeenCalledTimes(1); expect(f.peer.createRun).not.toHaveBeenCalled(); + await vi.waitFor(async () => expect((await restored.read?.())?.phase).toBe("terminal")); + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.ts new file mode 100644 index 00000000000..630e065ea04 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/cursor-cloud-driver.ts @@ -0,0 +1,618 @@ +import { randomBytes, randomUUID } from "node:crypto"; +import { chmod, lstat } from "node:fs/promises"; +import { dirname, isAbsolute, resolve } from "node:path"; +import { setTimeout as delay } from "node:timers/promises"; +import type { HarnessDriver, HarnessDriverDescriptor, HarnessSession, HarnessSessionRecoveryOptions, OpenHarnessSessionInput, PersistedHarnessSession } from "../../contracts/harness-driver.js"; +import { HarnessCapabilityUnavailableError, HarnessReconciliationError, HarnessStaleTurnError } from "../../contracts/harness-driver.js"; +import type { NativeRuntimeContextSnapshot } from "../../contracts/runtime-context.js"; +import type { NativeUserMessage } from "../../contracts/types.js"; +import { CURSOR_CLOUD_CANCEL_TIMEOUT_MS, CURSOR_CLOUD_DEFAULT_TIMEOUT_MS } from "../../contracts/cursor-cloud.js"; +import { PRP_BLOCK_TOOL_NAME, PRP_COMPLETION_TOOL_NAME } from "../../contracts/completion-result.js"; +import type { PrpEvent } from "../../protocol/replay-contract.js"; +import { RUNNER_TOOL_SCOPE_TOKEN_HEADER, startRunnerToolBridge, type RunnerToolBridge, type RunnerToolCall } from "../runner-tool-bridge.js"; +import { semanticCanonicalJson } from "../semantic-tool-receipt.js"; +import { CursorCloudClient, CursorCloudClientError, isCursorCloudUnsentRequestError, isCursorCloudRunActive, type CursorCloudModelRef, type CursorCloudRun, type CursorCloudSseEvent } from "./cloud-client.js"; +import { CURSOR_CLOUD_MCP_SERVER_NAME, parseNativeCursorCloudConfig, parseCursorCloudBinding, type NativeCursorCloudConfig, type CursorCloudBinding } from "./config.js"; +import { CursorCloudCheckpointStore, cursorCloudDigest, type CursorCloudCheckpoint, type CursorCloudTerminalDelivery } from "./checkpoint.js"; +import { cursorCloudInlineInstructions } from "./inline-assets.js"; +import { stageCursorCloudArtifact } from "./artifact-delivery.js"; +import { releaseCursorCloudStaleSocket } from "./stale-socket.js"; + +export const CURSOR_CLOUD_DRIVER_KIND = "cursor_cloud_api" as const; +export const CURSOR_CLOUD_DRIVER_VERSION = "cursor-cloud-v1" as const; +const CURSOR_CLOUD_CONTROL_INSTRUCTIONS = [ + "You are executing in native Paperclip Runner, not a legacy REST adapter.", + `Paperclip control tools are provided by the injected MCP server "${CURSOR_CLOUD_MCP_SERVER_NAME}" with controller-managed MCP authentication; you do not need Paperclip REST credentials in the Cloud VM.`, + `At the start of each run, call get_mcp_tools({server:"${CURSOR_CLOUD_MCP_SERVER_NAME}"}) to discover its tools, then use the returned tool schemas for Paperclip task context and control.`, + "For Paperclip control, do not search unrelated inherited dashboard MCP namespaces or wait for their authentication.", + `When you need a human answer, use this server's offered request_human_input tool. Report completion with its offered ${PRP_COMPLETION_TOOL_NAME} tool, or a blocker with its offered ${PRP_BLOCK_TOOL_NAME} tool, following their schemas. Text alone does not submit a question, completion, or blocker.`, +].join("\n"); +type TurnAuthority = { generation: number; ownerRunId: string; turnId: string | null }; +type RemoteAuthority = TurnAuthority & { agentId: string; runId: string }; +type PendingAuthority = TurnAuthority & Pick; +type PendingTerminal = { + authority: RemoteAuthority; + delivery: CursorCloudTerminalDelivery; + events: Array<{ eventType: PrpEvent["eventType"]; payload: Record; itemId?: string }>; +}; +type CloudClient = Pick; + +export interface CursorCloudSessionHandle extends HarnessSession { + read(): Promise>; + acknowledgeTerminalDelivery(input: { turnId: string; receiptId: string }): Promise; +} + +export interface CursorCloudDriverOptions { + model: string; + modelParams?: CursorCloudModelRef["params"]; + config: NativeCursorCloudConfig; + binding: CursorCloudBinding; + runtimeDirectory: string; + artifactRoot?: string; + relay: { url: string; token: string; socketPath: string; expiresAt: number }; + instructions: string; + runtimeContext?: NativeRuntimeContextSnapshot | null; + dynamicTools?: readonly Readonly>[]; + dynamicToolHandler(call: { tool: string; callId: string; threadId: string; turnId: string; arguments: unknown }): Promise; + environment?: NodeJS.ProcessEnv; + client?: CloudClient; + runnerInstanceId?: string; + cancelTimeoutMs?: number; + reconnectDelayMs?: number; +} + +class EventQueue { + #events: PrpEvent[] = []; + #waiter: ((result: IteratorResult) => void) | null = null; + #closed = false; + push(event: PrpEvent): void { + if (this.#closed) return; + if (this.#waiter) { const waiter = this.#waiter; this.#waiter = null; waiter({ value: event, done: false }); return; } + if (this.#events.length >= 2_048) throw new Error("Cursor Cloud event consumer exceeded its bounded queue"); + this.#events.push(event); + } + close(): void { this.#closed = true; this.#waiter?.({ value: undefined, done: true }); this.#waiter = null; } + async *stream(): AsyncGenerator { + while (true) { + if (this.#events.length) { yield this.#events.shift()!; continue; } + if (this.#closed) return; + const result = await new Promise>(resolveValue => { this.#waiter = resolveValue; }); + if (result.done) return; + yield result.value; + } + } +} + +function record(value: unknown): Record { return value && typeof value === "object" && !Array.isArray(value) ? value as Record : {}; } +function active(cp: CursorCloudCheckpoint): boolean { return cp.phase === "creating" || cp.phase === "running" || cp.phase === "stopping"; } +function boundedPositive(value: number | undefined, fallback: number): number { + const result = value ?? fallback; + if (!Number.isSafeInteger(result) || result < 1 || result > 120_000) throw new Error("Cursor Cloud lifecycle timeout exceeds its bound"); + return result; +} +async function withAbort(operation: Promise, signal: AbortSignal): Promise { + signal.throwIfAborted(); + let cancelled!: () => void; + const cancellation = new Promise((_resolve, reject) => { cancelled = () => reject(new Error("Cursor Cloud lifecycle deadline expired")); signal.addEventListener("abort", cancelled, { once: true }); }); + try { return await Promise.race([operation, cancellation]); } + finally { signal.removeEventListener("abort", cancelled); } +} + +export function cursorCloudDriverDescriptor(): HarnessDriverDescriptor { + return { kind: CURSOR_CLOUD_DRIVER_KIND, displayName: "Cursor Cloud (experimental)", version: CURSOR_CLOUD_DRIVER_VERSION, protocolVersion: "http+sse/v1", + runtimeContextCapabilities: { instructions: "native", skills: "native", mcp: "native" }, + capabilities: { resume: true, typedEvents: true, steering: false, queuedFollowUp: false, interruption: true, structuredResult: true, read: true, reconciliation: true, usage: false, dynamicTools: true, toolRefreshOnResume: true, runtimeRequestResolution: false, runtimeRequestHandoff: false, goals: false, threadLineage: false, + unsupported: ["native_permissions", "native_questions", "native_plan_decisions", "preprompt_model_acknowledgment", "preprompt_instruction_acknowledgment", "per_run_dollar_limit", "production_usage_accounting", "persistent_agent_directory", "binary_skill_assets", "steering", "goals", "threadLineage"] } }; +} + +export class CursorCloudDriver implements HarnessDriver { + readonly #options: CursorCloudDriverOptions; + constructor(options: CursorCloudDriverOptions) { + const model = options.model.trim(); + if (!model || model.length > 512 || /[\x00-\x1f\x7f]/.test(model)) throw new Error("Cursor Cloud requires an explicit model ID"); + const relay = new URL(options.relay.url); + if (relay.protocol !== "https:" || relay.username || relay.password || relay.search || relay.hash) throw new Error("Cursor Cloud semantic relay requires a public credential-free HTTPS URL"); + if (!options.relay.token || /[\r\n\0]/.test(options.relay.token)) throw new Error("Cursor Cloud semantic relay token is required"); + if (!Number.isSafeInteger(options.relay.expiresAt) || options.relay.expiresAt <= 0) throw new Error("Cursor Cloud semantic relay expiry is required"); + if (!isAbsolute(options.runtimeDirectory) || !isAbsolute(options.relay.socketPath)) throw new Error("Cursor Cloud relay socket and runtime directory must be absolute controller bindings"); + this.#options = { ...options, model, config: parseNativeCursorCloudConfig(options.config), binding: parseCursorCloudBinding(options.binding) }; + } + async descriptor(): Promise { + return cursorCloudDriverDescriptor(); + } + async openSession(input: OpenHarnessSessionInput): Promise { return this.#open(input, false); } + async recoverSession(snapshot: PersistedHarnessSession, options?: HarnessSessionRecoveryOptions) { + if (snapshot.driverKind !== CURSOR_CLOUD_DRIVER_KIND) return { recovered: false, reason: "Cursor Cloud recovery driver mismatch" }; + const session = await this.#open({ runId: snapshot.runId ?? "", normalizedSessionId: snapshot.normalizedSessionId ?? snapshot.driverSessionId, workingDirectory: snapshot.workingDirectory ?? this.#options.runtimeDirectory, signal: options?.signal }, true, snapshot.driverSessionId); + return { recovered: true, session }; + } + async #open(input: OpenHarnessSessionInput, recovering: boolean, sessionId = input.normalizedSessionId): Promise { + input.signal?.throwIfAborted(); + if (!input.runId || input.normalizedSessionId !== this.#options.binding.normalizedSessionId) throw new Error("Cursor Cloud session binding mismatch"); + const instructions = `${await cursorCloudInlineInstructions(this.#options.instructions, this.#options.runtimeContext)}\n\n${CURSOR_CLOUD_CONTROL_INSTRUCTIONS}`; + input.signal?.throwIfAborted(); + const store = new CursorCloudCheckpointStore(this.#options.runtimeDirectory, sessionId); + await store.acquire(); + let opened: CursorCloudSession | null = null; + try { + const existing = await store.read(); + if (recovering !== Boolean(existing)) throw new Error(recovering ? "Cursor Cloud checkpoint is missing; refusing a replacement remote create" : "Cursor Cloud checkpoint already exists; resume it explicitly"); + const bindingDigest = cursorCloudDigest(semanticCanonicalJson(this.#options.binding)); + const configDigest = cursorCloudDigest(semanticCanonicalJson(this.#options.config)); + const modelDigest = cursorCloudDigest(semanticCanonicalJson({ id: this.#options.model, params: this.#options.modelParams ?? [] })); + const instructionsDigest = cursorCloudDigest(instructions); + if (existing && (existing.driverSessionId !== sessionId || existing.normalizedSessionId !== input.normalizedSessionId || existing.bindingDigest !== bindingDigest || existing.configDigest !== configDigest || existing.modelDigest !== modelDigest || (active(existing) && (existing.instructionsDigest !== instructionsDigest || existing.ownerRunId !== input.runId)))) throw new Error("Cursor Cloud recovery identity/configuration/instructions changed"); + const checkpoint: CursorCloudCheckpoint = existing ?? { schema: "paperclip.cursor-cloud.checkpoint.v1", driverSessionId: sessionId, normalizedSessionId: input.normalizedSessionId, bindingDigest, configDigest, modelDigest, instructionsDigest, instructionsRevisionPending: false, ownerRunId: input.runId, agentId: null, runId: null, turnId: null, phase: "idle", pendingOperation: null, idempotencyKey: null, requestedAgentId: null, requestDigest: null, lastEventId: null, lastEventFingerprints: [], sourceSequence: 0, terminalStatus: null, deadlineAt: null, pendingTerminalDelivery: null, acceptedCompletion: null }; + if (checkpoint.instructionsDigest !== instructionsDigest) { checkpoint.instructionsDigest = instructionsDigest; checkpoint.instructionsRevisionPending = true; } + checkpoint.ownerRunId = input.runId; + await store.write(checkpoint); + opened = new CursorCloudSession(this.#options, input, instructions, checkpoint, store); + await opened.initialize(); + input.signal?.throwIfAborted(); + opened.startRecovery(); + return opened; + } catch (error) { + if (opened) await opened.detachControllerForRestart().catch(() => store.release()); + else await store.release(); + throw error; + } + } +} + +class CursorCloudSession implements CursorCloudSessionHandle { + readonly #options: CursorCloudDriverOptions; + readonly #input: OpenHarnessSessionInput; + readonly #instructions: string; + readonly #cp: CursorCloudCheckpoint; + readonly #store: CursorCloudCheckpointStore; + readonly #client: CloudClient; + readonly #events = new EventQueue(); + readonly #transcript: PrpEvent[] = []; + readonly #cancelTimeoutMs: number; + #bridge: RunnerToolBridge | null = null; + #closed = false; + #generation = 0; + #stopping = false; + #streamAbort: AbortController | null = null; + #launch: Promise | null = null; + #work: Promise | null = null; + #stop: Promise | null = null; + #stopCheckpoint: Promise | null = null; + #rejectionSettlement: Promise | null = null; + #terminalSettlement: Promise | null = null; + #pendingTerminal: PendingTerminal | null = null; + #turnDeadline: ReturnType | null = null; + + constructor(options: CursorCloudDriverOptions, input: OpenHarnessSessionInput, instructions: string, checkpoint: CursorCloudCheckpoint, store: CursorCloudCheckpointStore) { + this.#options = options; this.#input = input; this.#instructions = instructions; this.#cp = checkpoint; this.#store = store; + this.#client = options.client ?? new CursorCloudClient({ apiKey: options.environment?.CURSOR_API_KEY ?? "" }); + this.#cancelTimeoutMs = boundedPositive(options.cancelTimeoutMs, CURSOR_CLOUD_CANCEL_TIMEOUT_MS); + } + async initialize(): Promise { + const socketDirectory = await lstat(dirname(this.#options.relay.socketPath)); + if (!socketDirectory.isDirectory() || socketDirectory.isSymbolicLink() || (socketDirectory.mode & 0o077) !== 0 || (process.getuid && socketDirectory.uid !== process.getuid())) throw new Error("Cursor Cloud relay socket directory must be owned and private (0700)"); + await releaseCursorCloudStaleSocket(this.#options.relay.socketPath, this.#store.recoveredDeadOwner); + const tools = [...(this.#options.dynamicTools ?? []).filter(tool => tool.name !== PRP_COMPLETION_TOOL_NAME && tool.name !== PRP_BLOCK_TOOL_NAME && tool.name !== "list_cursor_cloud_artifacts").map(tool => tool.name === "register_deliverable" + ? { ...tool, description: `${tool.description ?? "Register an inspectable file result."} Cursor Cloud: create the file in the provider artifacts directory, discover its exact path with list_cursor_cloud_artifacts, then use contentRef cursor-artifact:. Supply the actual filename, byteSize and lowercase SHA-256; these are independently verified before registration. Cloud filesystem paths and host paths are not accepted.` } + : tool), { name: "list_cursor_cloud_artifacts", description: "List files exposed by the current Cursor Cloud Agent artifact API. Use the exact returned relative path in register_deliverable contentRef cursor-artifact:. This read-only provider helper does not register a deliverable.", inputSchema: { type: "object", properties: {}, additionalProperties: false } }]; + this.#bridge = await startRunnerToolBridge({ socketPath: this.#options.relay.socketPath, secret: this.#options.relay.token, tools, preserveToolNames: true, timeoutMs: null, + sessionScope: () => this.#closed || this.#stopping || this.#pendingTerminal || !active(this.#cp) ? null : this.#cp.turnId, + scopeToken: () => this.#closed || this.#stopping || this.#pendingTerminal || !active(this.#cp) ? null : this.#cp.relayTurnToken ?? null, + handler: call => this.#dispatch(call) }); + const socket = await lstat(this.#options.relay.socketPath); + if (!socket.isSocket() || socket.isSymbolicLink() || (process.getuid && socket.uid !== process.getuid())) throw new Error("Cursor Cloud bound relay socket ownership is unsafe"); + await chmod(this.#options.relay.socketPath, 0o600); + const secured = await lstat(this.#options.relay.socketPath); + if (!secured.isSocket() || secured.isSymbolicLink() || secured.ino !== socket.ino || secured.dev !== socket.dev || (secured.mode & 0o777) !== 0o600 || (process.getuid && secured.uid !== process.getuid())) throw new Error("Cursor Cloud bound relay socket changed while securing it"); + } + #authority(): TurnAuthority { return { generation: this.#generation, ownerRunId: this.#cp.ownerRunId, turnId: this.#cp.turnId }; } + #current(authority: TurnAuthority): boolean { return !this.#closed && authority.generation === this.#generation && authority.ownerRunId === this.#cp.ownerRunId && authority.turnId === this.#cp.turnId; } + #remote(authority: TurnAuthority): RemoteAuthority | null { return this.#current(authority) && this.#cp.agentId && this.#cp.runId ? { ...authority, agentId: this.#cp.agentId, runId: this.#cp.runId } : null; } + #pending(authority: TurnAuthority): PendingAuthority { return { ...authority, pendingOperation: this.#cp.pendingOperation, requestedAgentId: this.#cp.requestedAgentId, idempotencyKey: this.#cp.idempotencyKey, agentId: this.#cp.agentId }; } + #currentPending(authority: PendingAuthority): boolean { return this.#current(authority) && active(this.#cp) && authority.pendingOperation === this.#cp.pendingOperation && authority.requestedAgentId === this.#cp.requestedAgentId && authority.idempotencyKey === this.#cp.idempotencyKey && authority.agentId === this.#cp.agentId; } + #currentRemote(authority: RemoteAuthority): boolean { return !this.#pendingTerminal && this.#current(authority) && active(this.#cp) && authority.agentId === this.#cp.agentId && authority.runId === this.#cp.runId; } + #acceptRun(authority: RemoteAuthority, run: CursorCloudRun): boolean { + if (!this.#currentRemote(authority)) return false; + if (run.agentId !== authority.agentId || run.id !== authority.runId) throw new HarnessReconciliationError("Cursor Cloud response changed the confirmed Agent/Run identity"); + return true; + } + startRecovery(): void { if (active(this.#cp)) { const authority = this.#authority(); this.#armDeadline(); this.#work = this.#recoverActive(authority).catch(error => this.#unresolved(error, authority)); } } + ids() { return { driverSessionId: this.#cp.driverSessionId, providerSessionId: this.#cp.agentId, displayId: this.#cp.agentId ?? this.#cp.driverSessionId }; } + events(): AsyncIterable { return this.#events.stream(); } + turnControlCapabilities() { return { steering: false, queuedFollowUp: false }; } + async attachRun(input: { runId: string }): Promise { + if (active(this.#cp) || this.#closed) throw new Error("Cursor Cloud cannot replace an active run binding"); + this.#generation += 1; this.#cp.ownerRunId = input.runId; await this.#store.write(this.#cp); + } + async startTurn(input: { message: NativeUserMessage; requestedCollaborationMode?: "default" | "plan" }): Promise<{ turnId: string; effectiveCollaborationMode: "default" }> { + if (input.requestedCollaborationMode === "plan") throw new HarnessCapabilityUnavailableError("plan", "native Cloud plan decisions are unsupported"); + if (this.#closed || active(this.#cp)) throw new Error("Cursor Cloud session is closed or has unresolved remote work"); + if (this.#cp.pendingTerminalDelivery) throw new Error("Cursor Cloud terminal delivery must be acknowledged before new work"); + if (this.#options.relay.expiresAt <= Date.now()) throw new Error("Cursor Cloud semantic relay capability expired; only recovery cleanup is permitted"); + if (!input.message.text.trim() || Buffer.byteLength(input.message.text) > 1_048_576) throw new Error("Cursor Cloud turn text is empty or exceeds its bound"); + const previous = structuredClone(this.#cp); + const turnId = `turn-${randomUUID()}`; + const relayTurnToken = randomBytes(32).toString("base64url"); + const first = this.#cp.agentId === null; + const prompt = `${first || this.#cp.instructionsRevisionPending ? this.#instructions : CURSOR_CLOUD_CONTROL_INSTRUCTIONS}\n\nPaperclip task:\n${input.message.text}`; + const request = { prompt: { text: prompt }, model: { id: this.#options.model, ...(this.#options.modelParams ? { params: this.#options.modelParams } : {}) }, mode: "agent" as const, + mcpServers: [{ name: CURSOR_CLOUD_MCP_SERVER_NAME, type: "http" as const, url: this.#options.relay.url, headers: { Authorization: `Bearer ${this.#options.relay.token}`, [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: `Bearer ${relayTurnToken}` } }] }; + this.#cp.turnId = turnId; this.#cp.relayTurnToken = relayTurnToken; this.#cp.runId = null; this.#cp.phase = "creating"; this.#cp.pendingOperation = first ? "create_agent" : "create_run"; + this.#cp.requestedAgentId = first ? `bc-${randomUUID()}` : null; this.#cp.idempotencyKey = `paperclip-${randomUUID()}`; + this.#cp.requestDigest = cursorCloudDigest(semanticCanonicalJson(request)); this.#cp.lastEventId = null; this.#cp.lastEventFingerprints = []; this.#cp.terminalStatus = null; this.#cp.acceptedCompletion = null; this.#cp.pendingTerminalDelivery = null; + this.#cp.deadlineAt = Date.now() + (this.#options.config.timeoutMs ?? CURSOR_CLOUD_DEFAULT_TIMEOUT_MS); + this.#generation += 1; + const authority = this.#pending(this.#authority()); + this.#stopping = false; this.#stop = null; this.#stopCheckpoint = null; + const streamAbort = new AbortController(); this.#streamAbort = streamAbort; + const persisted = this.#store.write(this.#cp).catch(async error => { + if (this.#current(authority)) { + this.#generation += 1; + Object.assign(this.#cp, previous); + if (previous.relayTurnToken === undefined) delete this.#cp.relayTurnToken; + this.#stopping = false; this.#clearDeadline(); streamAbort.abort(); + if (this.#streamAbort === streamAbort) this.#streamAbort = null; + await this.#store.write(this.#cp); + } + throw error; + }); + const launch = (async () => { + await persisted; + if (!this.#currentPending(authority)) return; + const options = { signal: streamAbort.signal, idempotencyKey: authority.idempotencyKey! }; + const { schema: _schema, timeoutMs: _timeoutMs, ...cloudConfiguration } = this.#options.config; + let response; + try { + response = first + ? await this.#client.createAgent({ ...cloudConfiguration, ...request, agentId: authority.requestedAgentId! }, options) + : await this.#client.createRun(authority.agentId!, request, options); + } catch (error) { + if (!this.#currentPending(authority) || !(error instanceof CursorCloudClientError) + || (!isCursorCloudUnsentRequestError(error) + && (error.status === undefined || ![400, 401, 403, 404, 422].includes(error.status)))) throw error; + const settlement = this.#rejectCreate(error, authority); + this.#rejectionSettlement = settlement; + try { await settlement; return; } + finally { if (this.#rejectionSettlement === settlement) this.#rejectionSettlement = null; } + } + if (!this.#currentPending(authority)) return; + if (response.run.agentId !== (first ? authority.requestedAgentId : authority.agentId)) throw new HarnessReconciliationError("Cursor Cloud create response changed the requested Agent identity"); + this.#cp.agentId = response.run.agentId; this.#cp.runId = response.run.id; this.#cp.pendingOperation = null; this.#cp.instructionsRevisionPending = false; + if (!this.#stopping) this.#cp.phase = "running"; + await this.#store.write(this.#cp); + if (this.#current(authority)) this.#publishRemoteIdentity(); + })(); + this.#launch = launch; + this.#work = launch.then(async () => { const remote = this.#remote(authority); if (remote && !this.#stopping && active(this.#cp)) await this.#observe(remote); }).catch(error => this.#unresolved(error, authority)); + await persisted; + if (this.#current(authority) && active(this.#cp)) { + this.#emit("turn.started", { provider: "cursor_cloud", submittedModel: this.#options.model, effectiveModelAcknowledged: false, instructionsAcknowledged: false }); + this.#publishRemoteIdentity(); this.#armDeadline(); + } + return { turnId, effectiveCollaborationMode: "default" }; + } + async interrupt(input: { turnId?: string; signal?: AbortSignal } = {}): Promise { + if (input.turnId && input.turnId !== this.#cp.turnId) throw new HarnessStaleTurnError(input.turnId); + if (this.#pendingTerminal) { + const settlement = this.#persistTerminal(); + await (input.signal ? withAbort(settlement, input.signal) : settlement); + return; + } + if (!active(this.#cp)) return; + if (!this.#stop) { + const stop = this.#interrupt(this.#authority(), input.signal).finally(() => { if (this.#stop === stop) this.#stop = null; }); + this.#stop = stop; + } + return this.#stop; + } + async #interrupt(authority: TurnAuthority, signal?: AbortSignal): Promise { + const launch = this.#launch, streamAbort = this.#streamAbort; + this.#stopping = true; this.#cp.phase = "stopping"; + await (this.#stopCheckpoint = this.#store.write(this.#cp)); + if (!this.#current(authority) || !active(this.#cp)) return; + streamAbort?.abort(); + const abort = new AbortController(); + const cancelled = () => abort.abort(); + signal?.addEventListener("abort", cancelled, { once: true }); if (signal?.aborted) abort.abort(); + const timer = setTimeout(() => abort.abort(), this.#cancelTimeoutMs); + try { + if (launch) await withAbort(launch.catch(() => {}), abort.signal); + if (!this.#current(authority) || !active(this.#cp)) return; + await this.#resolvePending(authority, abort.signal); + if (!this.#current(authority) || !active(this.#cp)) return; + const remote = this.#remote(authority); + if (!remote) throw new HarnessReconciliationError("Cursor Cloud pending create has no confirmed run"); + let run = await this.#client.getRun(remote.agentId, remote.runId, { signal: abort.signal }); + if (!this.#acceptRun(remote, run)) return; + if (isCursorCloudRunActive(run.status)) { + try { await this.#client.cancelRun(remote.agentId, remote.runId, { signal: abort.signal }); } + catch (error) { if (!(error instanceof CursorCloudClientError && error.providerCode === "run_not_cancellable")) throw error; } + if (!this.#currentRemote(remote)) return; + do { + run = await this.#client.getRun(remote.agentId, remote.runId, { signal: abort.signal }); + if (!this.#acceptRun(remote, run)) return; + if (!isCursorCloudRunActive(run.status)) break; + await delay(100, undefined, { signal: abort.signal }); + if (!this.#currentRemote(remote)) return; + } while (!abort.signal.aborted); + } + if (isCursorCloudRunActive(run.status)) throw new Error("Remote work remains active"); + await this.#settle(remote, run, true); + } catch { if (this.#current(authority) && active(this.#cp)) throw new HarnessReconciliationError("Cursor Cloud Stop did not confirm remote terminal state; the run remains fenced"); } + finally { clearTimeout(timer); signal?.removeEventListener("abort", cancelled); } + } + async #resolvePending(authority: TurnAuthority, signal?: AbortSignal): Promise { + if (!this.#current(authority) || !active(this.#cp)) return; + const pending = this.#pending(authority); + if (pending.pendingOperation === "create_agent") { + const agent = await this.#client.getAgent(pending.requestedAgentId!, { signal }); + if (!this.#currentPending(pending)) return; + if (agent.id !== pending.requestedAgentId || !agent.latestRunId) throw new HarnessReconciliationError("Cursor Cloud pending create has no matching observable run"); + this.#cp.agentId = agent.id; this.#cp.runId = agent.latestRunId; this.#cp.pendingOperation = null; this.#cp.instructionsRevisionPending = false; await this.#store.write(this.#cp); + } else if (pending.pendingOperation === "create_run") { + throw new HarnessReconciliationError("Cursor Cloud follow-up outcome is unknown; refusing duplicate create or unbound cancellation"); + } + } + async #recoverActive(authority: TurnAuthority): Promise { + const streamAbort = new AbortController(); this.#streamAbort = streamAbort; + const signal = streamAbort.signal; + let run: CursorCloudRun | undefined; + let remote: RemoteAuthority | null = null; + for (let attempt = 0; this.#current(authority) && !this.#stopping && active(this.#cp); attempt += 1) { + try { + await this.#resolvePending(authority, signal); + if (!this.#current(authority) || this.#stopping || signal.aborted || !active(this.#cp)) return; + remote = this.#remote(authority); + if (!remote) throw new HarnessReconciliationError("Cursor Cloud recovery is missing remote identity"); + run = await this.#client.getRun(remote.agentId, remote.runId, { signal }); + if (!this.#acceptRun(remote, run)) return; + break; + } catch (error) { + if (!this.#current(authority) || this.#stopping || signal.aborted || !active(this.#cp)) return; + if (!(error instanceof CursorCloudClientError && error.retryable)) throw error; + await this.#unresolved(error, authority); + await delay(boundedPositive(this.#options.reconnectDelayMs, Math.min(250 * 2 ** attempt, 2_000)), undefined, { signal }) + .catch(error => { if (!signal.aborted) throw error; }); + } + } + if (!run || !remote || !this.#currentRemote(remote) || this.#stopping || signal.aborted) return; + this.#emit("turn.started", { recovered: true, submittedModel: this.#options.model, effectiveModelAcknowledged: false, instructionsAcknowledged: false }); + this.#publishRemoteIdentity(); + if (!isCursorCloudRunActive(run.status)) { await this.#settle(remote, run, this.#cp.phase === "stopping"); return; } + if (this.#cp.phase === "stopping" || this.#cp.deadlineAt === null || this.#cp.deadlineAt <= Date.now()) { await this.interrupt({ turnId: remote.turnId! }); return; } + await this.#observe(remote); + } + async #readObservedRun(authority: RemoteAuthority, signal: AbortSignal): Promise { + for (let attempt = 0; this.#currentRemote(authority) && !this.#stopping && !signal.aborted; attempt += 1) { + if (this.#cp.deadlineAt === null || this.#cp.deadlineAt <= Date.now()) return null; + try { + const run = await withAbort(this.#client.getRun(authority.agentId, authority.runId, { signal }), signal); + return this.#currentRemote(authority) && !this.#stopping && !signal.aborted ? run : null; + } catch (error) { + if (!this.#currentRemote(authority) || this.#stopping || signal.aborted) return null; + if (!(error instanceof CursorCloudClientError && error.retryable)) throw error; + if (attempt === 0) this.#emit("harness.diagnostic", { code: "cursor_cloud_observation_retry", message: "Cursor Cloud observation is temporarily unavailable; retrying the saved run within its original deadline." }); + const remaining = (this.#cp.deadlineAt ?? 0) - Date.now(); + if (remaining <= 0) return null; + const backoff = boundedPositive(this.#options.reconnectDelayMs, Math.min(250 * 2 ** Math.min(attempt, 4), 2_000)); + await delay(Math.min(remaining, Math.max(backoff, error.retryAfterMs ?? 0)), undefined, { signal }) + .catch(error => { if (!signal.aborted) throw error; }); + } + } + return null; + } + async #observe(authority: RemoteAuthority): Promise { + for (let attempt = 0; this.#currentRemote(authority) && !this.#stopping; attempt += 1) { + if (this.#cp.deadlineAt === null || this.#cp.deadlineAt <= Date.now()) return; + const streamAbort = new AbortController(); this.#streamAbort = streamAbort; + try { + for await (const event of this.#client.streamRun(authority.agentId, authority.runId, { signal: streamAbort.signal, ...(this.#cp.lastEventId ? { lastEventId: this.#cp.lastEventId } : {}) })) { + if (!this.#currentRemote(authority) || this.#stopping || streamAbort.signal.aborted) return; + await this.#consume(event); + if (event.event === "result" || event.event === "done") break; + } + } catch (error) { + if (!this.#currentRemote(authority) || this.#stopping || streamAbort.signal.aborted) return; + if (error instanceof CursorCloudClientError && error.status === 410) this.#emit("harness.diagnostic", { code: "cursor_cloud_stream_expired", message: "Cursor Cloud stream retention expired; reconciling saved run state." }); + else if (!(error instanceof CursorCloudClientError && error.retryable)) throw error; + } + if (!this.#currentRemote(authority) || this.#stopping || streamAbort.signal.aborted) return; + const run = await this.#readObservedRun(authority, streamAbort.signal); + if (!run || !this.#acceptRun(authority, run) || this.#stopping || streamAbort.signal.aborted) return; + if (!isCursorCloudRunActive(run.status)) { await this.#settle(authority, run); return; } + const remaining = (this.#cp.deadlineAt ?? 0) - Date.now(); + if (remaining <= 0) return; + await delay(Math.min(remaining, boundedPositive(this.#options.reconnectDelayMs, Math.min(250 * 2 ** Math.min(attempt, 4), 2_000))), undefined, { signal: streamAbort.signal }); + } + } + async #consume(event: CursorCloudSseEvent): Promise { + const fingerprint = cursorCloudDigest(semanticCanonicalJson(event)); + if (event.id && event.id === this.#cp.lastEventId && this.#cp.lastEventFingerprints.includes(fingerprint)) return; + const data = record(event.data); + if (event.event === "status" || event.event === "result") { + if (data.runId !== this.#cp.runId || !["CREATING", "RUNNING", "WAITING_FOR_BACKGROUND_WORK", "FINISHED", "ERROR", "CANCELLED", "EXPIRED"].includes(String(data.status))) throw new Error("Cursor Cloud stream lifecycle event has an invalid run identity/status"); + } + if (event.event === "assistant" && typeof data.text === "string") this.#emit("item.delta", { kind: "agentMessage", text: this.#redact(data.text) }, "assistant"); + else if (event.event === "thinking" && typeof data.text === "string") this.#emit("item.delta", { kind: "reasoning", text: this.#redact(data.text) }, "reasoning"); + else if (event.event === "tool_call") { + if (typeof data.callId !== "string" || !data.callId || data.callId.length > 512 || typeof data.name !== "string" || data.name.length > 512 || !["running", "completed", "error"].includes(String(data.status))) throw new Error("Cursor Cloud tool event omitted identity or status"); + this.#emit(data.status === "running" ? "item.started" : "item.completed", { kind: "tool", item: { id: data.callId, type: "mcpToolCall", name: data.name, status: data.status, ...(data.args === undefined ? {} : { arguments: this.#redactJson(data.args) }), ...(data.result === undefined ? {} : { result: this.#redactJson(data.result) }), ...(data.truncated ? { truncated: data.truncated } : {}) } }, data.callId); + } else if (event.event === "error") this.#emit("harness.diagnostic", { code: "cursor_cloud_stream_error", message: "Cursor Cloud stream reported an error; checking the saved run." }); + if (event.id) { + if (event.id !== this.#cp.lastEventId) this.#cp.lastEventFingerprints = []; + if (this.#cp.lastEventFingerprints.length >= 32) throw new Error("Cursor Cloud event cursor has too many variants"); + this.#cp.lastEventId = event.id; this.#cp.lastEventFingerprints.push(fingerprint); + } + await this.#store.write(this.#cp); + } + async #settle(authority: RemoteAuthority, run: CursorCloudRun, interrupted = false): Promise { + if (this.#acceptRun(authority, run) && !isCursorCloudRunActive(run.status)) { + const turnId = this.#cp.turnId!; + const delivery: CursorCloudTerminalDelivery = { schema: "paperclip.cursor-cloud.terminal-delivery.v1", threadId: this.#cp.driverSessionId, turnId, providerRunId: run.id, receiptId: randomUUID(), status: run.status as CursorCloudTerminalDelivery["status"], interrupted: interrupted || run.status === "CANCELLED", result: run.result ? this.#redact(run.result) : null }; + const events: PendingTerminal["events"] = []; + if (delivery.result) events.push({ eventType: "item.completed", payload: { kind: "agentMessage", text: delivery.result, channel: "final" }, itemId: "final" }); + events.push({ eventType: delivery.interrupted ? "turn.interrupted" : run.status === "FINISHED" ? "turn.completed" : "turn.failed", payload: { cursorCloudTerminalDelivery: delivery, providerStatus: run.status, remoteTerminalConfirmed: true, semanticCompletionAccepted: this.#cp.acceptedCompletion !== null, ...(run.status === "ERROR" || run.status === "EXPIRED" ? { error: { code: `cursor_cloud_${run.status.toLowerCase()}`, message: "Cursor Cloud run ended without successful provider completion." } } : {}) } }); + this.#pendingTerminal = { authority, delivery, events }; + await this.#persistTerminal(); + } + } + async #persistTerminal(): Promise { + if (this.#terminalSettlement) return this.#terminalSettlement; + const pending = this.#pendingTerminal; + if (!pending) return; + const settlement = this.#saveTerminal(pending); + this.#terminalSettlement = settlement; + try { await settlement; } + finally { if (this.#terminalSettlement === settlement) this.#terminalSettlement = null; } + } + async #saveTerminal(pending: PendingTerminal): Promise { + const expiresAt = Date.now() + this.#cancelTimeoutMs; + for (let attempt = 0; this.#current(pending.authority) && this.#pendingTerminal === pending; attempt += 1) { + // Reserve the final sequence range in the durable candidate, but allocate + // events only after it saves. A failed-save diagnostic cannot consume an + // unpublished final event's identity or let a snapshot regress the cursor. + const checkpoint: CursorCloudCheckpoint = { ...this.#cp, phase: "terminal", terminalStatus: pending.delivery.status, + pendingOperation: null, deadlineAt: null, pendingTerminalDelivery: pending.delivery, + sourceSequence: this.#cp.sourceSequence + pending.events.length }; + try { await this.#store.write(checkpoint); } + catch { + if (attempt === 0 && this.#current(pending.authority)) this.#publish(this.#event("harness.diagnostic", { + code: "cursor_cloud_terminal_checkpoint_pending", message: "Cursor Cloud finished, but its final checkpoint could not be saved. Its exact final delivery remains fenced until persistence succeeds.", + })); + const remaining = expiresAt - Date.now(); + if (remaining <= 0 || !this.#current(pending.authority)) throw new HarnessReconciliationError("Cursor Cloud terminal checkpoint could not be saved; the delivery remains fenced"); + await delay(Math.min(remaining, boundedPositive(this.#options.reconnectDelayMs, Math.min(250 * 2 ** Math.min(attempt, 4), 2_000)))); + continue; + } + if (!this.#current(pending.authority)) return; + const events = pending.events.map(event => this.#event(event.eventType, event.payload, event.itemId, pending.delivery.turnId)); + Object.assign(this.#cp, checkpoint); + this.#pendingTerminal = null; this.#clearDeadline(); + for (const event of events) this.#publish(event); + return; + } + } + async #dispatch(call: RunnerToolCall): Promise { + const turnId = this.#cp.turnId; + if (this.#closed || this.#stopping || this.#pendingTerminal || !turnId || !active(this.#cp) || this.#cp.acceptedCompletion || call.signal.aborted) throw new Error("Cursor Cloud tool call has no current run authority"); + if (call.tool === "list_cursor_cloud_artifacts") { + if (!this.#cp.agentId) throw new Error("Cursor Cloud Agent artifact identity is not confirmed"); + const listed = await this.#client.listArtifacts(this.#cp.agentId, { signal: call.signal }); + if (listed.items.length > 256) throw new Error("Cursor Cloud artifact catalog exceeds its 256-file bound"); + const result = { items: listed.items.map(item => ({ path: item.path, sizeBytes: item.sizeBytes })) }; + if (Buffer.byteLength(JSON.stringify(result)) > 65_536) throw new Error("Cursor Cloud artifact catalog exceeds its byte bound"); + if (this.#closed || this.#stopping || this.#pendingTerminal || call.signal.aborted || this.#cp.turnId !== turnId || !active(this.#cp)) throw new Error("Cursor Cloud artifact list arrived after run authority ended"); + return result; + } + const callId = `${turnId}:${call.callId}`; + let args = call.arguments; + let normalized: (() => void) | undefined; + if (call.tool === "register_deliverable") { + if (!this.#options.artifactRoot || !this.#cp.agentId) throw new Error("Cursor Cloud artifact registration is not bound to an admitted run/root"); + args = await stageCursorCloudArtifact({ arguments: args, agentId: this.#cp.agentId, runtimeDirectory: this.#options.runtimeDirectory, artifactRoot: this.#options.artifactRoot, client: this.#client, signal: call.signal }); + normalized = call.captureNormalizedInput?.(args); + } + if (this.#stopping || this.#closed || this.#pendingTerminal || call.signal.aborted || this.#cp.turnId !== turnId) throw new Error("Cursor Cloud run stopped before tool forwarding"); + const response = this.#options.dynamicToolHandler({ tool: call.tool, callId, threadId: this.#cp.driverSessionId, turnId, arguments: args }); + normalized?.(); + const result = await response; + if (this.#closed || this.#stopping || this.#pendingTerminal || this.#cp.turnId !== turnId || !active(this.#cp) || call.signal.aborted) throw new Error("Cursor Cloud tool result arrived after its run authority ended"); + if ((call.tool === PRP_COMPLETION_TOOL_NAME || call.tool === PRP_BLOCK_TOOL_NAME) && record(result).success === true) { + this.#cp.acceptedCompletion = { callIdDigest: cursorCloudDigest(callId), inputDigest: cursorCloudDigest(semanticCanonicalJson(call.arguments)), resultDigest: cursorCloudDigest(semanticCanonicalJson(result)), turnId }; + await this.#store.write(this.#cp); + } + return result; + } + #armDeadline(): void { + this.#clearDeadline(); + const authority = this.#authority(); + this.#turnDeadline = setTimeout(() => { if (this.#current(authority) && active(this.#cp)) void this.interrupt({ turnId: authority.turnId! }).catch(error => this.#unresolved(error, authority)); }, Math.max(0, (this.#cp.deadlineAt ?? 0) - Date.now())); + this.#turnDeadline.unref?.(); + } + #clearDeadline(): void { if (this.#turnDeadline) clearTimeout(this.#turnDeadline); this.#turnDeadline = null; } + #publishRemoteIdentity(): void { + const agentId = this.#cp.agentId ?? this.#cp.requestedAgentId; + if (!agentId) return; + this.#emit("harness.diagnostic", { code: "cursor_cloud_remote_identity", message: JSON.stringify({ schema: "paperclip.cursor-cloud.remote-identity.v1", provider: "cursor_cloud", agentId, runId: this.#cp.runId, ownerRunId: this.#cp.ownerRunId, normalizedSessionId: this.#cp.normalizedSessionId, phase: this.#cp.phase }) }); + } + async #rejectCreate(error: CursorCloudClientError, authority: PendingAuthority): Promise { + const rejected = { phase: "idle", pendingOperation: null, requestedAgentId: null, terminalStatus: "REJECTED", deadlineAt: null } as const; + // Keep admission fenced until the definite rejection is durable. Stop awaits + // this launch promise, and its checkpoint must not overwrite the settlement. + let stopCheckpoint = this.#stopCheckpoint; + for (;;) { + if (stopCheckpoint) await stopCheckpoint; + if (!this.#currentPending(authority)) return; + await this.#store.write({ ...this.#cp, ...rejected }); + if (!this.#currentPending(authority)) return; + if (this.#stopCheckpoint !== stopCheckpoint) { + stopCheckpoint = this.#stopCheckpoint; + continue; + } + Object.assign(this.#cp, rejected); this.#clearDeadline(); + const unsent = isCursorCloudUnsentRequestError(error); + this.#emit("turn.failed", { error: { code: unsent ? error.code : error.providerCode ?? "cursor_cloud_launch_rejected", message: unsent + ? "The encoded Cursor Cloud request exceeds the client limit. Reduce the task or instructions before retrying; no provider request was sent." + : "Cursor Cloud rejected the run before accepting provider work. Check the configured account, repository access and explicit model." }, remoteWorkAccepted: false }); + return; + } + } + async #unresolved(_error: unknown, authority: TurnAuthority): Promise { + if (!this.#current(authority) || !active(this.#cp)) return; + this.#emit("harness.diagnostic", { code: "cursor_cloud_remote_state_unknown", message: "Cursor Cloud work could not be reconciled. Saved identity is retained; no replacement work was created. Stop or reconnect to reconcile it." }); + } + #redact(text: string): string { + return this.#redactUnbounded(text).slice(0, 65_536); + } + #redactUnbounded(text: string): string { + for (const secret of [this.#options.environment?.CURSOR_API_KEY, this.#options.relay.token, this.#cp.relayTurnToken]) if (secret) text = text.replaceAll(secret, "[redacted]"); + return text; + } + #redactJson(value: unknown): unknown { + const text = this.#redactUnbounded(JSON.stringify(value)); + return Buffer.byteLength(text) > 65_536 ? { omitted: true, reason: "payload_limit" } : JSON.parse(text); + } + #event(eventType: PrpEvent["eventType"], payload: Record, itemId?: string, turnId = this.#cp.turnId ?? undefined): PrpEvent { + const seq = ++this.#cp.sourceSequence; + return { schema: "paperclip.prp.event.v1", schemaVersion: 1, sourceEventId: `cursor-cloud:${this.#cp.ownerRunId}:${seq}`, sourceSeq: seq, sourceInstanceId: this.#options.runnerInstanceId ?? "cursor-cloud-sidecar", sourceKind: "runner", runId: this.#cp.ownerRunId, normalizedSessionId: this.#cp.normalizedSessionId, ...(turnId ? { turnId } : {}), ...(itemId ? { itemId } : {}), eventType, priority: 1, emittedAt: new Date().toISOString(), payload }; + } + #publish(event: PrpEvent): void { + if (this.#closed) return; + this.#transcript.push(event); if (this.#transcript.length > 1_024) this.#transcript.shift(); this.#events.push(event); + } + #emit(eventType: PrpEvent["eventType"], payload: Record, itemId?: string, turnId = this.#cp.turnId ?? undefined): void { + if (!this.#closed && !this.#pendingTerminal) this.#publish(this.#event(eventType, payload, itemId, turnId)); + } + async acknowledgeTerminalDelivery(input: { turnId: string; receiptId: string }): Promise { + const pending = this.#cp.pendingTerminalDelivery; + if (!pending || pending.turnId !== input.turnId || pending.receiptId !== input.receiptId) throw new Error("Cursor Cloud terminal delivery receipt does not match"); + await this.#store.write({ ...this.#cp, pendingTerminalDelivery: null }); + this.#cp.pendingTerminalDelivery = null; + } + async read(): Promise> { return { provider: "cursor_cloud", agentId: this.#cp.agentId, runId: this.#cp.runId, turnId: this.#cp.turnId, phase: this.#cp.phase, providerStatus: this.#cp.terminalStatus, submittedModel: this.#options.model, effectiveModelAcknowledged: false, instructionsDigest: this.#cp.instructionsDigest, instructionsAcknowledged: false, semanticCompletionReceipt: this.#cp.acceptedCompletion, pendingTerminalDelivery: structuredClone(this.#cp.pendingTerminalDelivery) }; } + async reconcile(): Promise> { + if (this.#rejectionSettlement) await this.#rejectionSettlement; + if (this.#pendingTerminal) { await this.#persistTerminal(); return this.read(); } + const authority = this.#authority(); + await this.#resolvePending(authority); + const remote = this.#remote(authority); + if (remote && active(this.#cp)) { const run = await this.#client.getRun(remote.agentId, remote.runId); await this.#settle(remote, run); } + return this.read(); + } + async usage(): Promise | null> { return this.#cp.agentId ? { ...(await this.#client.getUsage(this.#cp.agentId, this.#cp.runId ? { runId: this.#cp.runId } : {})), cost: null, costUnavailable: true } : null; } + async transcript() { return { schema: "paperclip-runner/harness-transcript/v1" as const, complete: this.#transcript.length < 1_024, eventCount: this.#transcript.length, events: structuredClone(this.#transcript), omissionReason: this.#transcript.length >= 1_024 ? "bounded_history" : null }; } + async snapshot(): Promise { if (this.#rejectionSettlement) await this.#rejectionSettlement; if (this.#pendingTerminal) await this.#persistTerminal(); await this.#store.write(this.#cp); return { driverKind: CURSOR_CLOUD_DRIVER_KIND, driverSessionId: this.#cp.driverSessionId, providerSessionId: this.#cp.agentId, workingDirectory: this.#input.workingDirectory, runId: this.#cp.ownerRunId, normalizedSessionId: this.#cp.normalizedSessionId, activeTurnId: active(this.#cp) ? this.#cp.turnId : null, lastSourceSequence: this.#cp.sourceSequence }; } + async detachControllerForRestart(): Promise { if (this.#rejectionSettlement) await this.#rejectionSettlement; if (this.#pendingTerminal) await this.#persistTerminal(); this.#closed = true; this.#streamAbort?.abort(); this.#clearDeadline(); await this.#bridge?.close(); this.#events.close(); await this.#store.write(this.#cp); await this.#store.release(); } + async close(_input: { reason: string; force?: boolean }): Promise { + if (this.#closed) return; + let failure: unknown; + try { if (this.#pendingTerminal) await this.#persistTerminal(); else if (active(this.#cp)) await this.interrupt(); } catch (error) { failure = error; } + this.#closed = true; this.#streamAbort?.abort(); this.#clearDeadline(); + await this.#bridge?.close(); this.#events.close(); + // A failed terminal write may have committed before its acknowledgement was + // lost. Retain the last durable checkpoint instead of overwriting it active. + if (!this.#pendingTerminal) await this.#store.write(this.#cp); + await this.#store.release(); + if (failure) throw failure; + } +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.test.ts new file mode 100644 index 00000000000..ded49939a6d --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.test.ts @@ -0,0 +1,50 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { createHash } from "node:crypto"; +import { chmod, mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { composeNativeSystemInstructions, type NativeRuntimeAssetReference, type NativeRuntimeContextSnapshot } from "../../contracts/runtime-context.js"; +import { cursorCloudInlineInstructions } from "./inline-assets.js"; + +const roots: string[] = []; +const hash = (value: string | Buffer) => createHash("sha256").update(value).digest("hex"); +afterEach(async () => { for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true }); }); +async function asset(files: Record): Promise { + const root = await mkdtemp("/tmp/cc-assets-"); roots.push(root); + const manifestFiles = []; + for (const [path, content] of Object.entries(files).sort(([a], [b]) => a.localeCompare(b))) { + const target = join(root, path); await mkdir(join(target, ".."), { recursive: true }); await writeFile(target, content); await chmod(target, 0o444); + manifestFiles.push({ path, sha256: hash(content), mode: 0o444, size: Buffer.byteLength(content) }); + } + const totalBytes = manifestFiles.reduce((sum, file) => sum + file.size, 0); const digest = hash(JSON.stringify(manifestFiles)); + return { schema: "paperclip.runtime-asset.v1", rootPath: root, digest, manifestDigest: hash(`${JSON.stringify({ schema: "paperclip.runtime-asset-manifest.v1", digest, fileCount: manifestFiles.length, totalBytes, files: manifestFiles })}\n`), fileCount: manifestFiles.length, totalBytes }; +} +function context(bundle: NativeRuntimeAssetReference, skills: NativeRuntimeContextSnapshot["skills"] = []): NativeRuntimeContextSnapshot { + return { prompt: { revision: "test", text: "Paperclip policy.", digest: hash("Paperclip policy.") }, instructions: { entryPath: "AGENTS.md", bundle }, skills, mcp: { assignmentSetId: "set", digest: hash("set"), bindingId: "binding" }, aggregateDigest: hash("context") }; +} + +describe("Cursor Cloud immutable inline assets", () => { + it("delivers exact instruction siblings and all assigned skill files with virtual labels and no host path claim", async () => { + const instructions = await asset({ "AGENTS.md": "Follow references/details.md", "references/details.md": "Exact sibling bytes.\n" }); + const skill = await asset({ "SKILL.md": "Use references/input.txt", "references/input.txt": "Exact skill input." }); + const result = await cursorCloudInlineInstructions("local path promises must not survive", context(instructions, [{ key: "skill", runtimeName: "test-skill", versionId: "v1", bundle: skill }])); + expect(result).toContain("instructions/references/details.md"); expect(result).toContain("Exact sibling bytes.\\n"); expect(result).toContain("skills/test-skill/references/input.txt"); + expect(result).not.toContain(instructions.rootPath); expect(result).not.toContain(skill.rootPath); expect(result).not.toContain("AGENT_HOME"); + }); + it("rejects symlinks, binary payloads, digest mismatch and oversize before any native work", async () => { + const good = await asset({ "AGENTS.md": "safe" }); + await expect(cursorCloudInlineInstructions("", context({ ...good, digest: hash("wrong") }))).rejects.toThrow("digest mismatch"); + const binary = await asset({ "AGENTS.md": Buffer.from([0, 255]) }); + await expect(cursorCloudInlineInstructions("", context(binary))).rejects.toThrow("binary"); + await symlink("/etc/passwd", join(good.rootPath, "outside")); + await expect(cursorCloudInlineInstructions("", context(good))).rejects.toThrow("symlinks"); + await expect(cursorCloudInlineInstructions("", context({ ...good, totalBytes: 2_000_000 }))).rejects.toThrow("bound"); + }); + it("preserves current supplied instructions while removing only the trusted host asset suffix", async () => { + const bundle = await asset({ "AGENTS.md": "Exact entry instruction." }); + const snapshot = context(bundle); + snapshot.instructions.workingCopy = { rootPath: "/private/local/agent-files", entryPath: "AGENTS.md", kind: "agent_files" }; + const result = await cursorCloudInlineInstructions(composeNativeSystemInstructions(snapshot, "Exact entry instruction."), snapshot); + expect(result).toContain("Exact entry instruction."); expect(result).not.toContain(bundle.rootPath); expect(result).not.toContain("/private/local/agent-files"); expect(result).not.toContain("AGENT_HOME"); + expect(await cursorCloudInlineInstructions("Additional current grant instructions.", snapshot)).toContain("Additional current grant instructions."); + }); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.ts new file mode 100644 index 00000000000..4d9354eb6ba --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/inline-assets.ts @@ -0,0 +1,72 @@ +import { createHash } from "node:crypto"; +import { constants } from "node:fs"; +import { lstat, open, readdir } from "node:fs/promises"; +import { join, resolve } from "node:path"; +import { composeNativeSystemInstructions, type NativeRuntimeAssetReference, type NativeRuntimeContextSnapshot } from "../../contracts/runtime-context.js"; + +const MAX_INLINE_BYTES = 1_048_576; +const MAX_INLINE_FILES = 1_024; +const hash = (value: string | Uint8Array) => createHash("sha256").update(value).digest("hex"); + +export async function cursorCloudInlineInstructions(instructions: string, context?: NativeRuntimeContextSnapshot | null): Promise { + if (!context) { + if (!instructions.trim() || Buffer.byteLength(instructions) > MAX_INLINE_BYTES) throw new Error("Cursor Cloud instructions are empty or exceed the inline delivery bound"); + return instructions; + } + const files: Array<{ path: string; text: string }> = []; + let totalBytes = 0; + async function bundle(asset: NativeRuntimeAssetReference, label: string): Promise { + if (asset.totalBytes + totalBytes > MAX_INLINE_BYTES || asset.fileCount + files.length > MAX_INLINE_FILES) throw new Error("Cursor Cloud instruction/skill assets exceed the 1 MiB inline delivery bound"); + const root = resolve(asset.rootPath); + const collected: Array<{ path: string; sha256: string; mode: number; size: number; text: string }> = []; + async function visit(relative = ""): Promise { + const directory = relative ? join(root, relative) : root; + const directoryStat = await lstat(directory); + if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) throw new Error("Cursor Cloud asset directory is unsafe"); + for (const entry of (await readdir(directory, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) { + if (!entry.name || /[\0\r\n\\]/.test(entry.name) || entry.name === "." || entry.name === "..") throw new Error("Cursor Cloud asset path is unsupported"); + const path = relative ? `${relative}/${entry.name}` : entry.name; + const target = join(root, path); + const stat = await lstat(target); + if (stat.isSymbolicLink()) throw new Error("Cursor Cloud assets cannot contain symlinks"); + if (stat.isDirectory()) { await visit(path); continue; } + if (!stat.isFile() || stat.size > MAX_INLINE_BYTES - totalBytes || collected.length + files.length >= MAX_INLINE_FILES) throw new Error("Cursor Cloud asset is unsupported or exceeds its bound"); + const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)); + try { + const opened = await handle.stat(); + if (!opened.isFile() || opened.ino !== stat.ino || opened.dev !== stat.dev || opened.size !== stat.size) throw new Error("Cursor Cloud asset changed during admission"); + const buffer = Buffer.alloc(opened.size + 1); + const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0); + if (bytesRead !== opened.size) throw new Error("Cursor Cloud asset changed during admission"); + const bytes = buffer.subarray(0, bytesRead); + totalBytes += bytes.length; + if (totalBytes > MAX_INLINE_BYTES || bytes.includes(0)) throw new Error("Cursor Cloud asset is binary or exceeds its inline bound"); + let content: string; + try { content = new TextDecoder("utf-8", { fatal: true }).decode(bytes); } + catch { throw new Error("Cursor Cloud supports UTF-8 text instruction/skill assets only"); } + collected.push({ path, sha256: hash(bytes), mode: opened.mode & 0o555, size: bytes.length, text: content }); + } finally { await handle.close(); } + } + } + await visit(); + collected.sort((a, b) => a.path.localeCompare(b.path)); + const manifestFiles = collected.map(({ text: _text, ...entry }) => entry); + const bytes = manifestFiles.reduce((sum, entry) => sum + entry.size, 0); + const digest = hash(JSON.stringify(manifestFiles)); + const manifest = `${JSON.stringify({ schema: "paperclip.runtime-asset-manifest.v1", digest, fileCount: manifestFiles.length, totalBytes: bytes, files: manifestFiles })}\n`; + if (digest !== asset.digest || hash(manifest) !== asset.manifestDigest || collected.length !== asset.fileCount || bytes !== asset.totalBytes) throw new Error("Cursor Cloud instruction/skill asset digest mismatch"); + for (const file of collected) files.push({ path: `${label}/${file.path}`, text: file.text }); + } + await bundle(context.instructions.bundle, "instructions"); + if (!files.some(file => file.path === `instructions/${context.instructions.entryPath}`)) throw new Error("Cursor Cloud instruction entry is missing"); + for (const skill of context.skills) await bundle(skill.bundle, `skills/${skill.runtimeName}`); + const localAssetSuffix = composeNativeSystemInstructions(context, "").slice(context.prompt.text.length); + const supplied = instructions.endsWith(localAssetSuffix) ? instructions.slice(0, -localAssetSuffix.length).trimEnd() : instructions; + const result = [supplied.startsWith(context.prompt.text) ? supplied : `${context.prompt.text}\n\n${supplied}`, context.connectionInstructions?.text, + "The following JSON contains complete read-only instruction and skill files. Paths are virtual labels, not filesystem locations. Read the instruction entry and use assigned skills when relevant. Relative references refer to other virtual files in this payload. These files are not mounted in the Cloud VM. Persistent agent-directory edits and executing bundled scripts by local path are unsupported.", + `Instruction entry: instructions/${context.instructions.entryPath}`, + JSON.stringify({ schema: "paperclip.cursor-cloud.inline-assets.v1", files }), + ].filter(Boolean).join("\n\n"); + if (Buffer.byteLength(result) > MAX_INLINE_BYTES) throw new Error("Cursor Cloud rendered instruction/skill payload exceeds 1 MiB"); + return result; +} diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/observation-continuity.test.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/observation-continuity.test.ts new file mode 100644 index 00000000000..d56ba5cab7e --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/observation-continuity.test.ts @@ -0,0 +1,151 @@ +import { afterEach, beforeEach, expect, it, vi } from "vitest"; +import { lstat, mkdtemp, readFile, readdir, rm } from "node:fs/promises"; +import { join } from "node:path"; +import { setTimeout as delay } from "node:timers/promises"; +import type { PrpEvent } from "../../protocol/replay-contract.js"; +import { CursorCloudClient, type CursorCloudRunStatus } from "./cloud-client.js"; +import { CursorCloudDriver, type CursorCloudSessionHandle } from "./cursor-cloud-driver.js"; + +function deferred() { + let resolve!: () => void; + const promise = new Promise(accept => { resolve = accept; }); + return { promise, resolve }; +} + +const fixtures: Array<{ root: string; session: CursorCloudSessionHandle; pump: Promise; release(): void }> = []; +let forbiddenFetches = 0; +beforeEach(() => { + forbiddenFetches = 0; + vi.stubGlobal("fetch", async () => { forbiddenFetches++; throw new Error("External fetch is forbidden in the observation fixture"); }); +}); +afterEach(async () => { + try { + for (const fixture of fixtures.splice(0)) { + fixture.release(); + try { await fixture.session.close({ reason: "observation_fixture_cleanup" }); await fixture.pump; } + finally { await rm(fixture.root, { recursive: true, force: true }); } + } + expect(forbiddenFetches).toBe(0); + } finally { vi.unstubAllGlobals(); } +}); + +async function fixture(options: { timeoutMs?: number; reconnectDelayMs?: number; holdFourthRead?: boolean; finishOnFourthRead?: boolean; streamStatus?: number } = {}) { + const root = await mkdtemp("/tmp/cc-observe-"); + const socketPath = join(root, "mcp.sock"); + const fourthRead = deferred(), releaseFourthRead = deferred(); + const counts = { creates: 0, followups: 0, cancels: 0, streams: 0, reads: 0 }; + const observations: Array<{ status: CursorCloudRunStatus; deadlineAt: number | null; at: number }> = []; + const events: PrpEvent[] = []; + const nativeRunId = "run-11111111-1111-4111-8111-111111111111"; + const timestamp = "2026-10-29T00:00:00Z"; + let agentId = "", nativeStatus: CursorCloudRunStatus = "RUNNING"; + const checkpoint = async () => { + const name = (await readdir(root)).find(value => /^checkpoint-[a-f0-9]{64}\.json$/.test(value))!; + return JSON.parse(await readFile(join(root, name), "utf8")); + }; + const run = (status = nativeStatus) => ({ id: nativeRunId, agentId, status, createdAt: timestamp, updatedAt: timestamp, + ...(status === "FINISHED" ? { result: "Exact final answer after disconnected observation." } : {}) }); + const json = (value: unknown, status = 200) => new Response(JSON.stringify(value), { status, headers: { "content-type": "application/json" } }); + const nativeFetch: typeof globalThis.fetch = async (url, init) => { + const target = new URL(String(url)), method = init?.method ?? "GET"; + expect(target.origin).toBe("https://controlled.cursor.test"); + if (target.pathname === "/v1/agents" && method === "POST") { + counts.creates++; agentId = JSON.parse(String(init?.body)).agentId; + return json({ agent: { id: agentId, status: "ACTIVE", env: { type: "cloud" }, url: "https://cursor.com/agents/fixture", createdAt: timestamp, updatedAt: timestamp, latestRunId: nativeRunId }, run: run() }); + } + if (target.pathname === `/v1/agents/${agentId}/runs` && method === "POST") { counts.followups++; throw new Error("Unexpected replacement work"); } + if (target.pathname === `/v1/agents/${agentId}/runs/${nativeRunId}/cancel` && method === "POST") { + counts.cancels++; nativeStatus = "CANCELLED"; return json({ id: nativeRunId }); + } + if (target.pathname === `/v1/agents/${agentId}/runs/${nativeRunId}/stream` && method === "GET") { + counts.streams++; + if (options.streamStatus) return json({ message: "Controlled stream failure" }, options.streamStatus); + return new Response(`id: opaque-${counts.streams}\nevent: assistant\ndata: {"text":"Working before disconnect."}\n\n`, { headers: { "content-type": "text/event-stream" } }); + } + if (target.pathname === `/v1/agents/${agentId}/runs/${nativeRunId}` && method === "GET") { + counts.reads++; + if (options.finishOnFourthRead && counts.reads === 4) nativeStatus = "FINISHED"; + const observed = run(); + observations.push({ status: observed.status, deadlineAt: (await checkpoint()).deadlineAt, at: Date.now() }); + if (counts.reads === 4) { + fourthRead.resolve(); + if (options.holdFourthRead) await releaseFourthRead.promise; + } + return json(observed); + } + throw new Error(`Unexpected synthetic API request ${method} ${target.pathname}`); + }; + const driver = new CursorCloudDriver({ model: "explicit-model", config: { schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/repo" }], timeoutMs: options.timeoutMs ?? 10_000 }, + binding: { companyId: "company", agentId: "agent", issueId: "issue", normalizedSessionId: "session" }, runtimeDirectory: root, + relay: { url: "https://relay.example.test/mcp", token: "synthetic-relay-token", socketPath, expiresAt: Date.now() + 60_000 }, instructions: "Perform only this controlled observation fixture.", + dynamicToolHandler: async () => { throw new Error("No semantic tool is called by this fixture"); }, + client: new CursorCloudClient({ apiKey: "synthetic-key", baseUrl: "https://controlled.cursor.test", fetch: nativeFetch }), reconnectDelayMs: options.reconnectDelayMs ?? 1, cancelTimeoutMs: 200 }); + const session = await driver.openSession({ runId: "paperclip-run", normalizedSessionId: "session", workingDirectory: root }); + const pump = (async () => { for await (const event of session.events()) events.push(event); })(); + fixtures.push({ root, session, pump, release: releaseFourthRead.resolve }); + const socket = await lstat(socketPath); expect(socket.isSocket()).toBe(true); expect(socket.mode & 0o077).toBe(0); + const started = await session.startTurn({ message: { role: "user", text: "Complete after disconnected observation." } }); + const originalDeadline = (await checkpoint()).deadlineAt as number; + return { root, socketPath, session, events, counts, observations, checkpoint, originalDeadline, turnId: started.turnId, + fourthRead: fourthRead.promise, releaseFourthRead: releaseFourthRead.resolve, finish: () => { nativeStatus = "FINISHED"; } }; +} + +const terminals = (events: PrpEvent[]) => events.filter(event => ["turn.completed", "turn.failed", "turn.interrupted"].includes(event.eventType)); + +it("continues observation beyond four active disconnects and delivers the exact terminal once", async () => { + const f = await fixture({ holdFourthRead: true }); + await vi.waitFor(() => expect(f.counts.reads).toBe(4), { timeout: 1_000 }); + await f.fourthRead; + expect(f.observations.map(value => value.status)).toEqual(["RUNNING", "RUNNING", "RUNNING", "RUNNING"]); + f.finish(); f.releaseFourthRead(); + await vi.waitFor(() => expect(terminals(f.events)).toHaveLength(1), { timeout: 1_000 }); + expect(f.counts).toEqual({ creates: 1, followups: 0, cancels: 0, streams: 5, reads: 5 }); + expect(f.observations.every(value => value.deadlineAt === f.originalDeadline)).toBe(true); + expect(Date.now()).toBeLessThan(f.originalDeadline); + const terminal = terminals(f.events)[0]; expect(terminal.eventType).toBe("turn.completed"); expect(terminal.turnId).toBe(f.turnId); + expect(terminal.payload.cursorCloudTerminalDelivery).toMatchObject({ status: "FINISHED", result: "Exact final answer after disconnected observation." }); + expect(f.events.filter(event => event.eventType === "item.completed" && event.payload.channel === "final")).toHaveLength(1); + expect((await f.checkpoint()).pendingTerminalDelivery).toEqual(terminal.payload.cursorCloudTerminalDelivery); + const settled = { ...f.counts }; await delay(30); expect(f.counts).toEqual(settled); +}); + +it("still settles when the fourth disconnected stream's status read is already terminal", async () => { + const f = await fixture({ finishOnFourthRead: true }); + await vi.waitFor(() => expect(terminals(f.events)).toHaveLength(1), { timeout: 1_000 }); + expect(f.counts).toEqual({ creates: 1, followups: 0, cancels: 0, streams: 4, reads: 4 }); + expect((await f.checkpoint()).pendingTerminalDelivery.status).toBe("FINISHED"); +}); + +it("keeps repeated disconnects within the original deadline and cancels only the saved run", async () => { + const f = await fixture({ timeoutMs: 1_000, reconnectDelayMs: 20 }); + await vi.waitFor(() => expect(terminals(f.events)).toHaveLength(1), { timeout: 2_500 }); + expect(terminals(f.events)[0].eventType).toBe("turn.interrupted"); + expect(f.counts.streams).toBeGreaterThan(4); expect(f.counts.streams).toBeLessThan(100); + expect(f.counts.creates).toBe(1); expect(f.counts.followups).toBe(0); expect(f.counts.cancels).toBe(1); + expect(f.observations.every(value => value.deadlineAt === f.originalDeadline)).toBe(true); + expect(Date.now()).toBeGreaterThanOrEqual(f.originalDeadline); + const settled = { ...f.counts }; await delay(40); expect(f.counts).toEqual(settled); +}); + +it.each(["Stop", "close"] as const)("%s aborts observation backoff without a replacement or deadline extension", async operation => { + const f = await fixture({ reconnectDelayMs: 60_000 }); + await vi.waitFor(() => expect(f.counts.reads).toBe(1), { timeout: 1_000 }); + await delay(20); + expect((await f.checkpoint()).deadlineAt).toBe(f.originalDeadline); + const before = Date.now(); + if (operation === "Stop") await f.session.interrupt!({ turnId: f.turnId }); + else await f.session.close({ reason: "controlled_close_during_backoff" }); + expect(Date.now() - before).toBeLessThan(1_000); + expect(terminals(f.events)).toHaveLength(1); + expect(f.counts.creates).toBe(1); expect(f.counts.followups).toBe(0); expect(f.counts.cancels).toBe(1); expect(f.counts.streams).toBe(1); + const settled = { ...f.counts }; await delay(40); expect(f.counts).toEqual(settled); + expect((await f.checkpoint()).deadlineAt).toBeNull(); + if (operation === "close") expect((await readdir(f.root)).includes("mcp.sock")).toBe(false); +}); + +it("keeps non-transient stream authorization failures fenced without repeated requests", async () => { + const f = await fixture({ streamStatus: 401 }); + await vi.waitFor(() => expect(f.events.some(event => event.eventType === "harness.diagnostic" && event.payload.code === "cursor_cloud_remote_state_unknown")).toBe(true), { timeout: 1_000 }); + expect(f.counts).toEqual({ creates: 1, followups: 0, cancels: 0, streams: 1, reads: 0 }); + expect(terminals(f.events)).toHaveLength(0); +}); diff --git a/packages/paperclip-runner/src/drivers/cursor-cloud/stale-socket.ts b/packages/paperclip-runner/src/drivers/cursor-cloud/stale-socket.ts new file mode 100644 index 00000000000..bee386255a5 --- /dev/null +++ b/packages/paperclip-runner/src/drivers/cursor-cloud/stale-socket.ts @@ -0,0 +1,19 @@ +import { lstat, unlink } from "node:fs/promises"; +import { connect } from "node:net"; + +export async function releaseCursorCloudStaleSocket(path: string, recoveredDeadOwner: boolean): Promise { + let before; + try { before = await lstat(path); } + catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return; throw error; } + if (!recoveredDeadOwner || !before.isSocket() || before.isSymbolicLink() || (before.mode & 0o077) !== 0 || (process.getuid && before.uid !== process.getuid())) throw new Error("Cursor Cloud socket exists without safe dead-owner recovery proof"); + const stale = await new Promise(accept => { + const socket = connect({ path }); + const timer = setTimeout(() => { socket.destroy(); accept(false); }, 250); + socket.once("connect", () => { clearTimeout(timer); socket.destroy(); accept(false); }); + socket.once("error", (error: NodeJS.ErrnoException) => { clearTimeout(timer); socket.destroy(); accept(error.code === "ECONNREFUSED"); }); + }); + if (!stale) throw new Error("Cursor Cloud socket has a live or unknown owner"); + const current = await lstat(path); + if (current.ino !== before.ino || current.dev !== before.dev || !current.isSocket()) throw new Error("Cursor Cloud socket owner changed during recovery"); + await unlink(path); +} diff --git a/packages/paperclip-runner/src/drivers/runner-tool-bridge.test.ts b/packages/paperclip-runner/src/drivers/runner-tool-bridge.test.ts index 4b212476c49..c9818c65076 100644 --- a/packages/paperclip-runner/src/drivers/runner-tool-bridge.test.ts +++ b/packages/paperclip-runner/src/drivers/runner-tool-bridge.test.ts @@ -11,6 +11,7 @@ import { } from "../contracts/completion-result.js"; import { + RUNNER_TOOL_SCOPE_TOKEN_HEADER, canonicalRunnerToolName, startRunnerToolBridge, type RunnerToolBridge, @@ -84,6 +85,33 @@ describe("runner semantic MCP bridge", () => { }); }); + it("checks scoped credentials again after a delayed body before dispatch", async () => { + let scope = "first", token = "first-scope-token", reads = 0; + const handler = vi.fn(async () => ({ ok: true })); + const bridge = await startRunnerToolBridge({ tools: [tool("documents.read")], handler, + sessionScope: () => scope, scopeToken: () => { reads++; return token; } }); + bridges.push(bridge); + const headers = (value: string) => ({ Authorization: `Bearer ${bridge.secret}`, "content-type": "application/json", [RUNNER_TOOL_SCOPE_TOKEN_HEADER]: `Bearer ${value}` }); + const initialize = (value: string) => fetch(bridge.url, { method: "POST", headers: headers(value), body: JSON.stringify({ jsonrpc: "2.0", id: 0, method: "initialize" }) }); + expect((await rpc(bridge, { id: 0, method: "initialize" })).status).toBe(401); + const first = await initialize(token); expect(first.status).toBe(200); + const firstSession = first.headers.get("mcp-session-id")!; + const previousReads = reads; + const body = JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "documents.read", arguments: { path: "note" } } }); + let bodyController!: ReadableStreamDefaultController; + const pending = fetch(bridge.url, { method: "POST", headers: { ...headers(token), "mcp-session-id": firstSession }, + body: new ReadableStream({ start(controller) { bodyController = controller; controller.enqueue(new TextEncoder().encode(body.slice(0, 20))); } }), + duplex: "half" } as RequestInit); + await vi.waitFor(() => expect(reads).toBeGreaterThan(previousReads)); + scope = "second"; token = "second-scope-token"; + const second = await initialize(token); expect(second.status).toBe(200); + bodyController.enqueue(new TextEncoder().encode(body.slice(20))); bodyController.close(); + expect((await pending).status).toBe(401); + expect(handler).not.toHaveBeenCalled(); + const accepted = await fetch(bridge.url, { method: "POST", headers: { ...headers(token), "mcp-session-id": second.headers.get("mcp-session-id")! }, body }); + expect(accepted.status).toBe(200); expect(handler).toHaveBeenCalledTimes(1); + }); + it("keeps private operations callable but undiscoverable", async () => { const handler = vi.fn(async ({ tool: name }) => ({ name })); const bridge = await startRunnerToolBridge({ diff --git a/packages/paperclip-runner/src/drivers/runner-tool-bridge.ts b/packages/paperclip-runner/src/drivers/runner-tool-bridge.ts index 624569fa195..f54ed5ce21a 100644 --- a/packages/paperclip-runner/src/drivers/runner-tool-bridge.ts +++ b/packages/paperclip-runner/src/drivers/runner-tool-bridge.ts @@ -18,6 +18,8 @@ import { PRP_COMPLETION_TOOL_NAME, } from "../contracts/completion-result.js"; +export const RUNNER_TOOL_SCOPE_TOKEN_HEADER = "x-paperclip-runner-scope-token"; + export interface RunnerToolDefinition { name: string; description?: string; @@ -53,6 +55,9 @@ export interface RunnerToolBridgeOptions { /** Internal test seam; production bounds headers and body reads to 30 seconds. */ requestBodyTimeoutMs?: number; secret?: string; + socketPath?: string; + sessionScope?: () => string | null; + scopeToken?: () => string | null; } export interface RunnerToolBridge { @@ -143,6 +148,10 @@ export async function startRunnerToolBridge( validators, calls, controllers, + sessionScope: options.sessionScope, + scopeToken: options.scopeToken, + sessions: new Map(), + activeScope: null as string | null, handler: options.handler, captureSemanticReceipt: options.captureSemanticReceipt, timeoutMs: options.timeoutMs === null ? null : positiveBoundedInteger( @@ -184,15 +193,25 @@ export async function startRunnerToolBridge( server.requestTimeout = context.requestBodyTimeoutMs; server.headersTimeout = context.requestBodyTimeoutMs; server.on("clientError", (_error, socket) => socket.destroy()); - await listenLoopback(server); + if (options.socketPath) { + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(options.socketPath, () => { + server.off("error", reject); + resolve(); + }); + }); + } else { + await listenLoopback(server); + } const address = server.address(); - if (address === null || typeof address === "string") { + if (address === null || (typeof address === "string" && !options.socketPath)) { await closeServer(server); throw new Error("Runner tool bridge failed to bind a loopback port"); } let closed = false; return Object.freeze({ - url: `http://127.0.0.1:${address.port}/mcp`, + url: typeof address === "string" ? "http://localhost/mcp" : `http://127.0.0.1:${address.port}/mcp`, secret, async close() { if (closed) return; @@ -208,6 +227,10 @@ async function handleRequest( response: ServerResponse, context: { secret: string; + sessionScope?: () => string | null; + scopeToken?: () => string | null; + sessions: Map; + activeScope: string | null; preserveToolNames: boolean; visibleTools: RunnerToolDefinition[]; admittedTools: Map; @@ -240,6 +263,14 @@ async function handleRequest( response.end(); return; } + const scopeToken = context.scopeToken?.(); + if (context.scopeToken) { + if (!scopeToken) { response.statusCode = 403; response.end(); return; } + const supplied = request.headers[RUNNER_TOOL_SCOPE_TOKEN_HEADER]; + if (typeof supplied !== "string" || !authorized(supplied, scopeToken)) { + response.statusCode = 401; response.end(); return; + } + } let message: Record; try { message = parseMessage( @@ -253,13 +284,33 @@ async function handleRequest( writeRpc(response, null, undefined, rpcError(-32700, safeError(error))); return; } + if (context.scopeToken && scopeToken !== context.scopeToken()) { + response.statusCode = 401; response.end(); return; + } const id = message.id ?? null; const method = typeof message.method === "string" ? message.method : ""; + let sessionKey = ""; + if (context.sessionScope) { + const scope = context.sessionScope(); + if (!scope) { response.statusCode = 403; response.end(); return; } + if (context.activeScope !== scope) { + for (const controller of context.controllers.values()) controller.abort(); + context.sessions.clear(); context.calls.clear(); context.controllers.clear(); + context.activeScope = scope; + } + if (method !== "initialize") { + const supplied = request.headers["mcp-session-id"]; + if (typeof supplied !== "string" || context.sessions.get(supplied) !== scope) { + response.statusCode = 404; response.end(); return; + } + sessionKey = supplied + ":"; + } + } if (method === "notifications/cancelled") { const params = isRecord(message.params) ? message.params : {}; const requestId = params.requestId; if (typeof requestId === "string" || typeof requestId === "number") { - context.controllers.get(rpcIdKey(requestId))?.abort(); + context.controllers.get(sessionKey + rpcIdKey(requestId))?.abort(); } response.statusCode = 202; response.end(); @@ -271,7 +322,12 @@ async function handleRequest( return; } if (method === "initialize") { - response.setHeader("Mcp-Session-Id", randomBytes(16).toString("hex")); + const sessionId = randomBytes(16).toString("hex"); + if (context.sessionScope) { + if (context.sessions.size >= 64) { response.statusCode = 429; response.end(); return; } + context.sessions.set(sessionId, context.activeScope!); + } + response.setHeader("Mcp-Session-Id", sessionId); writeRpc(response, id, { protocolVersion: "2025-03-26", capabilities: { tools: { listChanged: false } }, @@ -308,8 +364,8 @@ async function handleRequest( ); return; } - const callId = String(id); - const callKey = rpcIdKey(id); + const callId = context.sessionScope ? sessionKey + rpcIdKey(id) : String(id); + const callKey = sessionKey + rpcIdKey(id); const args = params.arguments ?? {}; const validator = context.validators.get(tool); if (validator === undefined || !validator(args)) { diff --git a/packages/paperclip-runner/src/index.ts b/packages/paperclip-runner/src/index.ts index 3f5ecb3dc77..5165520217c 100644 --- a/packages/paperclip-runner/src/index.ts +++ b/packages/paperclip-runner/src/index.ts @@ -120,5 +120,11 @@ export type { RunnerProviderLaunchRequirements, RunnerProviderLaunchEnvironment, export { resolveGrokDisableWebSearch } from "./drivers/acpx/grok-web-search.js"; +export { CURSOR_CLOUD_DEFAULT_TIMEOUT_MS, parseNativeCursorCloudConfig, type NativeCursorCloudConfig } from "./contracts/cursor-cloud.js"; + +export { CursorCloudClient, CursorCloudClientError, isCursorCloudRunActive } from "./drivers/cursor-cloud/cloud-client.js"; + +export { archiveCursorCloudSessionCheckpoint } from "./drivers/cursor-cloud/checkpoint.js"; + export { readProviderFailure, type ProviderFailure } from "./contracts/provider-failure.generated.js"; export { providerFailureFromError } from "./drivers/provider-failure.js"; diff --git a/packages/paperclip-runner/src/live/runner-provider-launch.ts b/packages/paperclip-runner/src/live/runner-provider-launch.ts index aa876191fc7..a7afb0b0f5f 100644 --- a/packages/paperclip-runner/src/live/runner-provider-launch.ts +++ b/packages/paperclip-runner/src/live/runner-provider-launch.ts @@ -186,6 +186,7 @@ export interface RunnerProviderLaunchEnvironment { codexCommand?: string; opencodeProxyPath: string; acpxSidecarPath: string; + cursorCloudProxyPath?: string; } export function createRunnerProviderLaunch( @@ -193,6 +194,16 @@ export function createRunnerProviderLaunch( input: RunnerProviderLaunchEnvironment, ): Record { const { identity, instructions: baseInstructions, runtimeContext, settings, provider } = requirements; + if (provider === "cursor_cloud") { + if (input.options.runnerFilesystemRoot || !requirements.model || requirements.readOnly) { + throw new Error("cursor_cloud_local_controller_required: experimental Cursor Cloud supports standard tasks with a local controller"); + } + if (!input.cursorCloudProxyPath) throw new Error("cursor_cloud_proxy_missing"); + return { kind: "cursor_cloud", provider: "cursor_cloud", driver: "cursor_cloud_api", providerVersion: "cursor-cloud-v1", + command: input.providerNodeCommand, args: [input.cursorCloudProxyPath], cwd: input.cwd, + model: requirements.model, instructions: baseInstructions, approvalPolicy: "never", + conversationMode: requirements.preparedConversation ? "prepared" : "task" }; + } const acpxAgent = provider === "acpx" ? settings.acpxAgent ?? "codex" : null; const requestedModel = requirements.model ?? ""; const includeCodexCollaborationInstructions = provider === "codex" && diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts index fc4952e1f19..63628e9caed 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.test.ts @@ -771,6 +771,16 @@ it("reopens Copilot with the current registered files after collecting the previ } finally { await rm(root, { recursive: true, force: true }); } }); +it("refreshes Cloud instructions on cold rotation without replacing the pinned launch profile", () => { + const identity = { runnerInstanceId: "runner", environmentLeaseId: "lease", runId: "next-run", normalizedSessionId: "session", turnId: "turn", itemId: "item" }; + const provider = { kind: "cursor_cloud", provider: "cursor_cloud", instructions: "Prior instructions.", command: "/pinned/node", args: ["/pinned/proxy.cjs"], model: "pinned-model", conversationMode: "task" }; + const payload = runnerdRecoveryInternals.rotatedRunAttachPayload({ runAttachTemplate: { provider } }, identity, null, undefined, + null, { text: "Current instructions.", context: null }); + expect(payload.provider).toEqual({ ...provider, instructions: "Current instructions." }); + expect(provider.instructions).toBe("Prior instructions."); + expect(runnerdRecoveryInternals.rotatedRunAttachPayload({ runAttachTemplate: { provider } }, identity, null, undefined).provider).toEqual(provider); +}); + it.each(["claude", "codex", "cursor", "pi", "copilot"])("keeps %s's pinned grants on same-run recovery", (agent) => { const identity = { runnerInstanceId: "runner", environmentLeaseId: "lease", runId: "same-run", normalizedSessionId: "session", turnId: "turn", itemId: "item" }; const provider = { kind: "acpx", agent, runId: identity.runId, instructions: "Pinned instructions.", runtimeContext: assignedRuntimeContext("/skills", "/pinned") }; diff --git a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts index 28e1f6bb694..2aba43026b2 100644 --- a/packages/paperclip-runner/src/live/runnerd-codex-transport.ts +++ b/packages/paperclip-runner/src/live/runnerd-codex-transport.ts @@ -508,6 +508,11 @@ function retargetRunAttachPayload( provider.runtimeContext = structuredClone(runtimeContext); } payload.provider = provider; + } else if (provider.kind === "cursor_cloud" && currentInstructions !== undefined) { + provider.instructions = currentInstructions.context && runtimeContext !== undefined + ? retargetComposedInstructions(currentInstructions.text, currentInstructions.context, runtimeContext) + : currentInstructions.text; + payload.provider = provider; } if (authorizedTools !== null) payload.authorizedTools = authorizedTools; if (completionContract !== undefined) { @@ -1240,12 +1245,15 @@ export interface CapabilityRunnerdProcessEvidence { export interface CapabilityRunnerdCodexTransportOptions extends RunnerExecutionDriver { observability?: import("../drivers/agent-observability.js").ProviderObservabilityLaunch; homeMode?: "isolated" | "preconfigured"; - provider?: "codex" | "opencode" | "claude_managed" | "aws_agentcore" | "acpx"; + provider?: "cursor_cloud" | "codex" | "opencode" | "claude_managed" | "aws_agentcore" | "acpx"; observeCredentials?: boolean; onCredentialsUpdated?: (event: PrpEvent) => Promise; onAccountingEvent?: (event: PrpEvent) => Promise; onRecoveryAccountingEvent?: (event: PrpEvent, sourceIdentity: DurableRecoveryIdentity) => Promise; recoverSemanticToolInput?: DurablePrpControlPlaneOptions["recoverSemanticToolInput"]; + cursorCloud?: import("../contracts/cursor-cloud.js").NativeCursorCloudConfig; + cursorCloudProxyPath?: string; + cursorCloudProxySha256?: string; recoveryPurpose?: "execution" | "stop_cleanup"; opencodePermissionMode?: NativeOpenCodePermissionMode; acpxAgent?: QualifiedAcpxAgent; @@ -3035,7 +3043,7 @@ async function settleRetainedRunnerdSessionOwned( } type BuildOwnedCliArtifact = - "acpx-runtime-sidecar.cjs" | "opencode-app-server-proxy.cjs"; + "acpx-runtime-sidecar.cjs" | "opencode-app-server-proxy.cjs" | "cursor-cloud-app-server-proxy.cjs"; function buildOwnedCliArtifactCandidates( artifact: BuildOwnedCliArtifact, @@ -3352,6 +3360,16 @@ function createCapabilityRunnerdProviderEnvironmentBase(input: { ? { PAPERCLIP_NATIVE_RUNTIME_CONTEXT_PATH: input.runtimeContextPath } : {}), }; + if (input.provider === "cursor_cloud") { + const env = input.options.environment ?? {}; + if (!env.CURSOR_API_KEY?.trim()) throw new Error("cursor_cloud_api_key_required"); + const selected: NodeJS.ProcessEnv = { CURSOR_API_KEY: env.CURSOR_API_KEY, ...commonIdentity }; + for (const name of ["PAPERCLIP_CURSOR_CLOUD_ARTIFACT_ROOT", "PAPERCLIP_CURSOR_CLOUD_CONFIG_PATH", "PAPERCLIP_CURSOR_CLOUD_RELAY_SOCKET_PATH", "PAPERCLIP_CURSOR_CLOUD_RELAY_TOKEN", "PAPERCLIP_CURSOR_CLOUD_RELAY_URL", "PAPERCLIP_CURSOR_CLOUD_RELAY_EXPIRES_AT"]) { + if (!env[name]) throw new Error("cursor_cloud_relay_binding_required"); + selected[name] = env[name]; + } + return selected; + } if (input.provider === "opencode") { return { ...createSanitizedOpenCodeRunnerEnvironment(input.options.environment), @@ -5141,6 +5159,15 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { )); const providerNodeCommand = this.options.providerNodeCommand ?? process.execPath; + const cursorCloudProxyPath = provider === "cursor_cloud" + ? this.options.cursorCloudProxyPath ?? resolveBuildOwnedCliArtifact("cursor-cloud-app-server-proxy.cjs") : undefined; + const runnerCursorCloudLaunchProfile = cursorCloudProxyPath ? { + command: providerNodeCommand, + commandSha256: this.options.providerNodeCommandSha256 ?? `sha256:${createHash("sha256").update(readFileSync(providerNodeCommand)).digest("hex")}`, + proxyScript: cursorCloudProxyPath, + proxyScriptSha256: this.options.cursorCloudProxySha256 ?? `sha256:${createHash("sha256").update(readFileSync(cursorCloudProxyPath)).digest("hex")}`, + } : undefined; + const effectiveCodexCommand = provider === "codex" ? this.options.codexCommand ?? resolveCodexCommand(undefined, this.options.environment, String(params.cwd ?? tmpdir())) : undefined; @@ -5229,10 +5256,10 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { ), { options: this.options, root: this.#root, cwd: String(params.cwd ?? tmpdir()), codexHome, providerNodeCommand, codexCommand: effectiveCodexCommand, - opencodeProxyPath, acpxSidecarPath, + opencodeProxyPath, acpxSidecarPath, cursorCloudProxyPath, }), }; - return { runAttachTemplate, runnerAcpxLaunchProfile, runnerOpenCodeLaunchProfile, + return { runAttachTemplate, runnerAcpxLaunchProfile, runnerOpenCodeLaunchProfile, runnerCursorCloudLaunchProfile, environment: withRunnerdProviderTrace( createCapabilityRunnerdProviderEnvironment({ provider, @@ -5368,6 +5395,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { runnerDigest: runnerArtifact.digest, acpxLaunchProfile: prepared.runnerAcpxLaunchProfile, opencodeLaunchProfile: prepared.runnerOpenCodeLaunchProfile, + cursorCloudLaunchProfile: prepared.runnerCursorCloudLaunchProfile, environment: prepared.environment, diagnosticsDirectory: resolve(this.#root, "diagnostics"), processLauncher: this.options.runnerProcessLauncher, @@ -5452,7 +5480,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { controlPlaneDirectory, "control-plane-state.json", ); - const localProvider = + const supportsWarmRecovery = this.options.provider === undefined || this.options.provider === "codex" || this.options.provider === "opencode" || @@ -5461,6 +5489,8 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { this.options.readRunnerState === undefined && this.options.runnerStateDirectory === undefined && this.options.runnerFilesystemRoot === undefined && !this.options.prepareLaunch; + const supportsColdRotation = supportsWarmRecovery || + (this.options.provider === "cursor_cloud" && localStateOwner); const localRunnerStatePath = resolve( this.#root, "runner", @@ -5480,7 +5510,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { ? readControlPlaneState(controlPlaneDirectory) : null; } catch (error) { - if (localProvider && localStateOwner && !hasRunnerWarmBoundary) { + if (supportsColdRotation && localStateOwner && !hasRunnerWarmBoundary) { quarantineLocalRuntimeState(this.#root, error); } throw error; @@ -5532,7 +5562,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { // No malformed or unsupported transition is reinterpreted as legacy. if ( (!localStateOwner && !this.options.readRunnerState) || - !localProvider || + !supportsWarmRecovery || !controlPlaneState || !candidateRunnerState || (this.options.controlPlaneRegistration !== undefined && @@ -5636,7 +5666,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { identity.itemId === desiredIdentity.itemId; let rotatedAuthority = false; if (controlPlaneState === null) { - if (!localProvider) { + if (!supportsColdRotation) { throw new Error("PRP provider resume state is unavailable"); } const archivedState = latestArchivedControlPlaneState( @@ -5674,7 +5704,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { identity = desiredIdentity; rotatedAuthority = true; } else if (!exactAuthority && warmRecovery === null) { - if (!localProvider || controlPlaneState === null) { + if (!supportsColdRotation || controlPlaneState === null) { throw new Error("native_runner_prp_run_rotation_unavailable"); } if (localStateOwner) { @@ -5760,6 +5790,15 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { )); const providerNodeCommand = this.options.providerNodeCommand ?? process.execPath; + const cursorCloudProxyPath = provider === "cursor_cloud" + ? this.options.cursorCloudProxyPath ?? resolveBuildOwnedCliArtifact("cursor-cloud-app-server-proxy.cjs") : undefined; + const runnerCursorCloudLaunchProfile = cursorCloudProxyPath ? { + command: providerNodeCommand, + commandSha256: this.options.providerNodeCommandSha256 ?? `sha256:${createHash("sha256").update(readFileSync(providerNodeCommand)).digest("hex")}`, + proxyScript: cursorCloudProxyPath, + proxyScriptSha256: this.options.cursorCloudProxySha256 ?? `sha256:${createHash("sha256").update(readFileSync(cursorCloudProxyPath)).digest("hex")}`, + } : undefined; + const opencodeExecutable = provider === "opencode" && preparesProviderLaunch ? resolveRunnerOpenCodeExecutable(this.options) @@ -6139,6 +6178,7 @@ class DurablePrpCodexTransport implements CodexAppServerTransport { runnerDigest: runnerArtifact.digest, acpxLaunchProfile: runnerAcpxLaunchProfile, opencodeLaunchProfile: runnerOpenCodeLaunchProfile, + cursorCloudLaunchProfile: runnerCursorCloudLaunchProfile, environment: this.options.prepareLaunch ? {} : withRunnerdProviderTrace( createCapabilityRunnerdProviderEnvironment({ provider, @@ -7988,6 +8028,7 @@ function openedThreadModelProvider( model: unknown, ): string { if (provider === "opencode" && typeof model === "string") return model.split("/", 1)[0]!; + if (provider === "cursor_cloud") return "cursor"; if (provider === "claude_managed") return "anthropic"; if (provider === "aws_agentcore") return "aws"; if (provider === "acpx") { diff --git a/packages/paperclip-runner/src/native-session-runtime.test.ts b/packages/paperclip-runner/src/native-session-runtime.test.ts index e872c426e4b..11f665119dd 100644 --- a/packages/paperclip-runner/src/native-session-runtime.test.ts +++ b/packages/paperclip-runner/src/native-session-runtime.test.ts @@ -1,7 +1,9 @@ import { createHash } from "node:crypto"; +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; import { resolveQualifiedAcpxProfile } from "./drivers/acpx/qualified-profiles.js"; import { describe, expect, it, vi } from "vitest"; -import { createCodexNativeSessionBackend } from "./backends/codex-native-backend.js"; +import { createCodexNativeSessionBackend, createRunnerdNativeSessionBackend } from "./backends/codex-native-backend.js"; import { FakeCodexTransport, WORKSPACE } from "./drivers/codex/codex-app-server-driver.test-support.js"; import type { ControlPlanePort } from "./contracts/control-plane-port.js"; @@ -228,6 +230,56 @@ function highestContiguous(events: PrpEvent[]): number { } describe("executeNativeSession recovery", () => { + it("completes Cursor Cloud semantic planning through its default-only harness without losing the pinned revision", async () => { + await writeFile(join(WORKSPACE, "cloud-plan-instructions.md"), "Make the plan only. Do not implement it.\n"); + const prepared = preparedInput(); + const context = { ...prepared.runtimeContext, instructions: { ...prepared.runtimeContext.instructions, + entryPath: "cloud-plan-instructions.md", bundle: { ...prepared.runtimeContext.instructions.bundle, rootPath: WORKSPACE } } }; + const planningContext = { documentId: "plan-document", baseRevisionId: "plan-revision-3", baseRevisionNumber: 3, + markdown: "# Existing canonical plan", sha256: createHash("sha256").update("# Existing canonical plan").digest("hex"), reviewContext: { feedback: "Keep the requested scope" } }; + const executionInput: NativeExecutionInputV5 = { + ...prepared, executionMode: "plan", planningContext, + task: { ...prepared.task, workMode: "planning" }, + runtimeContext: { ...context, aggregateDigest: canonicalNativeRuntimeContextDigest(context) }, + workspace: { ...input.workspace, cwd: WORKSPACE }, + session: { ...input.session, driverKind: "cursor_cloud_api", lifecyclePolicy: { mode: "per_turn", idleTimeoutMs: null } }, + provider: { kind: "cursor_cloud", model: "explicit-cloud-model", cursorCloud: { schema: "paperclip.cursor-cloud.config.v1", repos: [{ url: "https://github.com/example/fixture" }] } }, + }; + const planResult: PrpStructuredRunResult = { ...result, summary: "The requested plan is ready.", artifacts: [{ kind: "native_provider_plan", ref: "Keep the requested scope." }] }; + const transport = new FakeCodexTransport(); + transport.confirmCollaborationMode = false; + const backend = createRunnerdNativeSessionBackend(executionInput, { runnerInstanceId: "runner-recovery", transportFactory: () => transport }); + const committed: PrpEvent[] = []; + const completeRun = vi.fn(async () => undefined); + const port: ControlPlanePort = { + async openRun() {}, async checkpointSession() {}, + async appendEvent(event) { committed.push(structuredClone(event)); return { cursor: event.sourceSeq, highestContiguousSourceSeq: event.sourceSeq, disposition: "committed" }; }, + async replayEvents(query) { const events = committed.filter(event => event.sourceInstanceId === query.sourceInstanceId); return { events: events.filter(event => event.sourceSeq > query.afterSourceSeq).slice(0, query.limit), highestContiguousSourceSeq: highestContiguous(events) }; }, + completeRun, + }; + const abort = new AbortController(); + const completion = executeNativeSession({ input: executionInput, backend, controlPlane: port, + runnerInstanceId: "runner-recovery", controlPlaneInstanceId: "control-recovery", signal: abort.signal }); + let failure: unknown; + void completion.catch(error => { failure = error; }); + try { + await vi.waitFor(() => expect(transport.calls.some(call => call.method === "turn/start") || failure).toBeTruthy()); + if (failure) await completion; + const started = transport.calls.find(call => call.method === "turn/start")!; + const envelope = JSON.parse((started.params.input as Array<{ text: string }>)[0]!.text); + expect(envelope).toMatchObject({ executionMode: "plan", task: { workMode: "planning" }, planningContext }); + expect(transport.calls.find(call => call.method === "thread/start")?.params.baseInstructions).toContain("Make the plan only. Do not implement it."); + expect(started.params).not.toHaveProperty("collaborationMode"); + transport.push("turn/started", { threadId: "thread-1", turn: { id: "turn-1", status: "inProgress" } }); + transport.push("paperclip/runResult", { threadId: "thread-1", turnId: "turn-1", result: planResult }); + transport.push("turn/completed", { threadId: "thread-1", turn: { id: "turn-1", status: "completed", items: [] } }); + await expect(completion).resolves.toMatchObject({ result: planResult, terminal: { runTerminalState: "succeeded" } }); + expect(completeRun).toHaveBeenCalledOnce(); + expect(committed.some(event => event.eventType === "run.result.accepted")).toBe(true); + expect(executionInput.planningContext).toEqual(planningContext); + } finally { abort.abort(); await completion.catch(() => undefined); } + }); + it.each([false, true].flatMap(recovered => [ { recovered, cwd: "/home/agent" }, { recovered, cwd: "/projects/repository/worktrees/task" }, @@ -8077,6 +8129,68 @@ describe("executeNativeSession recovery", () => { } finally { vi.useRealTimers(); } }); + it.each([ + { name: "default", bound: undefined, limit: 15_000 }, + { name: "not-finite", bound: Number.NaN, limit: 15_000 }, + { name: "infinite", bound: Infinity, limit: 15_000 }, + { name: "negative", bound: -1, limit: 15_000 }, + { name: "nonpositive", bound: 0, limit: 15_000 }, + { name: "oversized", bound: 30_001, limit: 15_000 }, + { name: "fractional", bound: 30_000.5, limit: 15_000 }, + { name: "extended-missing", bound: 30_000, limit: 30_000 }, + { name: "short-operation", bound: 30_000, limit: 250, operationMs: 1_000 }, + { name: "foreign-terminal", bound: 30_000, limit: 30_000, fault: "foreign" }, + { name: "unproven-terminal", bound: 30_000, limit: 0, fault: "unproven" }, + { name: "startup-abort", bound: 30_000, limit: 100, fault: "abort" }, + ])("bounds governed terminal observation without finalizing an unproven wait: $name", async ({ bound, limit, operationMs, fault }) => { + vi.useFakeTimers(); + try { + const trigger = { ...runnerEvent(1, "item.completed", { kind: "dynamicToolCall" }), turnId: "turn-waiting" }; + const history: PrpEvent[] = []; + let checkpoint: PersistedNativeSession | undefined; + let releaseStream!: () => void; + const streamClosed = new Promise(resolve => { releaseStream = resolve; }); + let cancelAt = 0; + const cancel = vi.fn(({ signal }: { signal: AbortSignal }) => { cancelAt = Date.now(); signal.addEventListener("abort", releaseStream, { once: true }); return { cleanup: Promise.resolve(), terminalDrainTimeoutMs: bound }; }); + const complete = vi.fn(async () => undefined); + const session: NativeSession = { + identity: () => identity, + async capabilities() { return { resume: true, typedEvents: true, steering: false, interruption: true, structuredResult: true }; }, + async startTurn() { if (fault === "abort") await new Promise((_, reject) => setTimeout(() => reject(new Error("controlled startup abort")), 100)); return { turnId: trigger.turnId }; }, cancel, + async snapshot() { return { backendKind: "mock", sessionId: identity.sessionId, identity, activeTurnId: trigger.turnId }; }, + async result() { return null; }, async close() { releaseStream(); }, + async *events() { + yield trigger; + if (fault === "foreign" || fault === "unproven") yield { ...runnerEvent(2, "turn.interrupted", { providerTerminalObserved: fault !== "unproven" }), turnId: fault === "foreign" ? "foreign-turn" : trigger.turnId }; + await streamClosed; + }, + }; + const backend: NativeSessionBackend = { async descriptor() { return { kind: "mock", name: "bounded-cancellation", version: "1", capabilities: await session.capabilities() }; }, async openSession() { return session; } }; + const port: ControlPlanePort = { + async openRun() {}, completeRun: complete, + async checkpointSession(value) { checkpoint = structuredClone(value); }, + async appendEvent(event) { history.push(event); return { cursor: history.length, highestContiguousSourceSeq: event.sourceSeq, disposition: "committed" }; }, + async replayEvents(request) { return { events: history.filter(row => row.sourceInstanceId === request.sourceInstanceId && row.sourceSeq > request.afterSourceSeq), highestContiguousSourceSeq: 0 }; }, + }; + const execution = executeNativeSession({ input, backend, controlPlane: port, timeoutMs: operationMs ?? 120_000, + runnerInstanceId: "runner-recovery", controlPlaneInstanceId: "control-recovery", resolveGovernedWait: () => yieldedResult }); + let settled = false; + void execution.then(() => { settled = true; }, () => { settled = true; }); + await vi.waitFor(() => expect(cancel).toHaveBeenCalledOnce()); + if (limit > 0) { + await vi.advanceTimersByTimeAsync(Math.max(0, limit - 1 - (Date.now() - cancelAt))); + expect(settled).toBe(false); + } + await vi.advanceTimersByTimeAsync(fault === "abort" ? 1_002 : 2); + if (fault === "abort") await expect(execution).rejects.toThrow("controlled startup abort"); + else await expect(execution).rejects.toMatchObject({ code: "native_provider_terminal_failed" }); + expect(checkpoint?.governedWait).toEqual({ sourceEvent: trigger, result: yieldedResult }); + expect(complete).not.toHaveBeenCalled(); + expect(history.some(event => event.eventType === "run.terminal")).toBe(false); + if (fault === "foreign") expect(history).toEqual([trigger]); + } finally { vi.useRealTimers(); } + }); + it.each(["interrupt_acknowledgement", "runtime_request.cancelled", "runtime_request.expired"])("retains %s in contiguous governed-wait history for recovery", async cancellationKind => { const trigger = { ...runnerEvent(1, "item.completed", { kind: "dynamicToolCall" }), turnId: "turn-waiting" }; const acknowledgement: PrpEvent = { ...runnerEvent(2, cancellationKind === "interrupt_acknowledgement" ? "item.completed" : cancellationKind as "runtime_request.cancelled" | "runtime_request.expired", diff --git a/packages/paperclip-runner/src/native-session-runtime.ts b/packages/paperclip-runner/src/native-session-runtime.ts index 2b8475c317e..fbbb6a98133 100644 --- a/packages/paperclip-runner/src/native-session-runtime.ts +++ b/packages/paperclip-runner/src/native-session-runtime.ts @@ -54,6 +54,7 @@ const REUSABLE_SESSION_CANCELLATION_SETTLEMENT_GRACE_MS = 10_000; // (1s). Allow that bounded settlement plus transport scheduling; never treat // elapsed time or a cancellation acknowledgement as usage/terminal evidence. const GOVERNED_ACCOUNTING_DRAIN_MS = 15_000; +const MAX_GOVERNED_ACCOUNTING_DRAIN_MS = 30_000; const DEFAULT_NATIVE_CHECKPOINT_TIMEOUT_MS = 30_000; type NativeSessionCleanupDomain = string; @@ -980,7 +981,11 @@ async function consumeTurn( const drainAbort = new AbortController(); const stopDrain = () => drainAbort.abort(appendAbort.signal.reason); appendAbort.signal.addEventListener("abort", stopDrain, { once: true }); - const drainMs = Math.min(GOVERNED_ACCOUNTING_DRAIN_MS, timeoutMs > 0 ? Math.max(1, Math.floor(timeoutMs / 4)) : GOVERNED_ACCOUNTING_DRAIN_MS); + const requestedDrainMs = cancellation.terminalDrainTimeoutMs; + const terminalDrainMs = typeof requestedDrainMs === "number" && Number.isSafeInteger(requestedDrainMs) + && requestedDrainMs > 0 && requestedDrainMs <= MAX_GOVERNED_ACCOUNTING_DRAIN_MS + ? requestedDrainMs : GOVERNED_ACCOUNTING_DRAIN_MS; + const drainMs = Math.min(terminalDrainMs, timeoutMs > 0 ? Math.max(1, Math.floor(timeoutMs / 4)) : terminalDrainMs); let drainTimer: ReturnType | undefined; const drained = (async () => { while (!drainAbort.signal.aborted) { @@ -2647,7 +2652,11 @@ export async function executeNativeSession( ...(recovered && modelEnvelope.schema === "paperclip.native-continuation.v1" ? { continuation: true as const } : {}), requestedCollaborationMode: - "executionMode" in input ? input.executionMode : "default", + // Paperclip planning remains in the envelope and tool authority. + // Cloud's qualified harness exposes only default collaboration. + input.provider.kind === "cursor_cloud" + ? "default" + : "executionMode" in input ? input.executionMode : "default", }); await checkpoint(); } diff --git a/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts b/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts index 92905627855..0bf009a2d14 100644 --- a/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts +++ b/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts @@ -1226,7 +1226,8 @@ export const providerDescriptorSchema = { "acpx", "openai_dot", "grok_bot", - "muse" + "muse", + "cursor_cloud" ] }, "driver": { @@ -1238,7 +1239,8 @@ export const providerDescriptorSchema = { "acpx_runtime", "openai_dot_mcp", "grok_bot_mcp", - "muse_external" + "muse_external", + "cursor_cloud_api" ] }, "model": { @@ -1534,6 +1536,19 @@ export const providerDescriptorSchema = { "const": "remote_service" } } + }, + { + "properties": { + "provider": { + "const": "cursor_cloud" + }, + "driver": { + "const": "cursor_cloud_api" + }, + "executionKind": { + "const": "local_process" + } + } } ] }, diff --git a/packages/paperclip-runner/test/fixtures/copilot-mainline-v22-identity.json b/packages/paperclip-runner/test/fixtures/copilot-mainline-v22-identity.json new file mode 100644 index 00000000000..0b7b75483fe --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-mainline-v22-identity.json @@ -0,0 +1,44 @@ +{ + "commandDigest": "sha256:9027ee2bdf9180e3267b7d05b56b0703943251a29713c393f7a3f2ef1072efd2", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 22, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "ddd98aabe20f4d40b04bb58126bda548a9d85b8234a3f9ea84b6db414e9b4814", + "semanticDirectDriverSourceSha256": "72d5134a9567ced685bc942adf14ec5dfba04bcd6b0eeabe77eac0cec5c434c3", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "5e957fe0f0ba164441d6a5b8a276e52cf6f2ffaf99741faca99cff05e539221c", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-mainline-v23-identity.json b/packages/paperclip-runner/test/fixtures/copilot-mainline-v23-identity.json new file mode 100644 index 00000000000..abf8d388cc9 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-mainline-v23-identity.json @@ -0,0 +1,44 @@ +{ + "commandDigest": "sha256:6ca1e2c9efa23887ba6f08d89980c91d13114640ac8a1a79f00f27aa8cd39d63", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 23, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "ddd98aabe20f4d40b04bb58126bda548a9d85b8234a3f9ea84b6db414e9b4814", + "semanticDirectDriverSourceSha256": "72d5134a9567ced685bc942adf14ec5dfba04bcd6b0eeabe77eac0cec5c434c3", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "5e957fe0f0ba164441d6a5b8a276e52cf6f2ffaf99741faca99cff05e539221c", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-mainline-v24-identity.json b/packages/paperclip-runner/test/fixtures/copilot-mainline-v24-identity.json new file mode 100644 index 00000000000..8fcbfae75f7 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-mainline-v24-identity.json @@ -0,0 +1,44 @@ +{ + "commandDigest": "sha256:87e275270e50b42290d10ecec9dfce86ffca2b7a7519cb60c584004adfc86437", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 24, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "6fc6ceb1222cec5586952cf51e2df045ecf751adfc937f5125550a311f5d3896", + "semanticDirectDriverSourceSha256": "72d5134a9567ced685bc942adf14ec5dfba04bcd6b0eeabe77eac0cec5c434c3", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "5e957fe0f0ba164441d6a5b8a276e52cf6f2ffaf99741faca99cff05e539221c", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v10-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v10-identity.json new file mode 100644 index 00000000000..a4fb2572016 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v10-identity.json @@ -0,0 +1,33 @@ +{ + "commandDigest": "sha256:c6741d7e49cd1af4ecad9e07181ef96305bde48b56dce2958547f2f066666231", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 10, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v1", + "semanticReceiptSourceSha256": "3d3d0fe5ce0e4dbfc78cf95b1bfcff4d4b3760c548e74c6c12db5bcacdd46ae2", + "semanticBridgeSourceSha256": "ab8f872344b2beb50e3f9970e0631c451a5493e66d259582ecc9a214624269b5", + "toolEvidenceSourceSha256": "f0a93aab9940051972028d6f2610b4018a5a0d6b2326b7c61b767b38442629ca" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v11-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v11-identity.json new file mode 100644 index 00000000000..12ddfd88caa --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v11-identity.json @@ -0,0 +1,42 @@ +{ + "commandDigest": "sha256:d56589c43437277b527ed61155de7d882e3ae5316d67502d8b98a0d435f69f99", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 11, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "a261497560840da66613a5f4a3dafeba05e53d3a8647c180c9604b3cf983dc23", + "semanticDirectDriverSourceSha256": "31e36917ee3592fa6d8f4b86632129fdffae20c45aed2e0e367ccf523e064f88", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "bb55e18c5563bf5ec226e301c3399229304f295e986865e96554f193535368f2", + "semanticSidecarProtocolSourceSha256": "165cad76f224d60f0dc7928736d47a16787eaa8ab9e4c2222488da5fc8ad632e" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v12-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v12-identity.json new file mode 100644 index 00000000000..82b2ad0f4d3 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v12-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:48cecd8dc77a5533240fcf2f29d19be05380da4a79f8e5061480f94241db75a8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 12, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "d58076d59ec23fe2261cba3aa0dca3e9f189105f0a5fa7ca3eeaac05cb338f31", + "semanticDirectDriverSourceSha256": "31e36917ee3592fa6d8f4b86632129fdffae20c45aed2e0e367ccf523e064f88", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "bb55e18c5563bf5ec226e301c3399229304f295e986865e96554f193535368f2", + "semanticSidecarProtocolSourceSha256": "165cad76f224d60f0dc7928736d47a16787eaa8ab9e4c2222488da5fc8ad632e", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v13-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v13-identity.json new file mode 100644 index 00000000000..3f443926d73 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v13-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:3ff08fbe76fe4549c9eb01e8794428d8909c65c151d775220f2ec111d9e6f7c1", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 13, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "560010031c58cf6d492784f62fadc96f33bec9c1d12e67fece48b4dfcee518ed", + "semanticDirectDriverSourceSha256": "2db465e56ba41f06b406e039e566d9e3aea0a014fc6a47a6a54d5bc682dabcab", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "72d9800603a652d6580084bb3b5dac4d4dd6d644324b0d15d293d7c198fd6b55", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v14-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-candidate-historical-identity.json new file mode 100644 index 00000000000..1b6e4d930cd --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-candidate-historical-identity.json @@ -0,0 +1,53 @@ +{ + "commandDigest": "sha256:9e11997fe602749000ebef97a9933c976afe1783be884871488c1e0d3e7d7b34", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 14, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "5cf0ad62e06071f59eb27cedd7aa5d5852826ab1dfb96dbda846adc1535a9eee", + "semanticDirectDriverSourceSha256": "0cb9b66ad41e643c9e018eeb6d6468eb306d0b1ad7d2776ffa9dd11d2b28abca", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "b74133bd72f92d6bd0652c1772a45227f6a549232554528fef2761b17b8f02e7", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "7dc408a9c5114e7eb28f46fbab5d4cac23789095ab2e37725a3e15518f88232a", + "runtimeSandboxSourceSha256": "d78b859d170b931b8fc310577e6d1d01a1c20f168ad48c5de84bca2ea325aad9", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "f5e825c368ebd739afa51711bfbbc72ac4d19a9d23bcafd9738ff0e337f55eaf" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v14-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-identity.json new file mode 100644 index 00000000000..74191266281 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:5e5955c57917a7e7c25703b3ed9e420cd72105eab033b611508dc37fdba3858b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 14, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b83898b2453d0f425275d3bc58140675fc8f14505703103079094093f16be43f", + "semanticDirectDriverSourceSha256": "2db465e56ba41f06b406e039e566d9e3aea0a014fc6a47a6a54d5bc682dabcab", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "72d9800603a652d6580084bb3b5dac4d4dd6d644324b0d15d293d7c198fd6b55", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v14-mainline-pi-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-mainline-pi-identity.json new file mode 100644 index 00000000000..74191266281 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v14-mainline-pi-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:5e5955c57917a7e7c25703b3ed9e420cd72105eab033b611508dc37fdba3858b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 14, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b83898b2453d0f425275d3bc58140675fc8f14505703103079094093f16be43f", + "semanticDirectDriverSourceSha256": "2db465e56ba41f06b406e039e566d9e3aea0a014fc6a47a6a54d5bc682dabcab", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "72d9800603a652d6580084bb3b5dac4d4dd6d644324b0d15d293d7c198fd6b55", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v15-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-candidate-historical-identity.json new file mode 100644 index 00000000000..a7dd74fc911 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-candidate-historical-identity.json @@ -0,0 +1,53 @@ +{ + "commandDigest": "sha256:3ad622b836afef0849a53ed4d9ae7b00dfd91d290bb8b62ce6390357f26c0456", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 15, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "5cf0ad62e06071f59eb27cedd7aa5d5852826ab1dfb96dbda846adc1535a9eee", + "semanticDirectDriverSourceSha256": "0cb9b66ad41e643c9e018eeb6d6468eb306d0b1ad7d2776ffa9dd11d2b28abca", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "7dc408a9c5114e7eb28f46fbab5d4cac23789095ab2e37725a3e15518f88232a", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "f5e825c368ebd739afa51711bfbbc72ac4d19a9d23bcafd9738ff0e337f55eaf" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v15-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-identity.json new file mode 100644 index 00000000000..12ef2b3780d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:8faf47520f156c62c79ea6ca7d1d90a85ddc9a6621f798bd14e87bc6c643bd04", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 15, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "c0139d0b3af085ec5272a7812c9f89aff0e8618d1d44d9c9e9a59525d1972436", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b83898b2453d0f425275d3bc58140675fc8f14505703103079094093f16be43f", + "semanticDirectDriverSourceSha256": "2db465e56ba41f06b406e039e566d9e3aea0a014fc6a47a6a54d5bc682dabcab", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "72d9800603a652d6580084bb3b5dac4d4dd6d644324b0d15d293d7c198fd6b55", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v15-mainline-pi-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-mainline-pi-identity.json new file mode 100644 index 00000000000..12ef2b3780d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v15-mainline-pi-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:8faf47520f156c62c79ea6ca7d1d90a85ddc9a6621f798bd14e87bc6c643bd04", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 15, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "c0139d0b3af085ec5272a7812c9f89aff0e8618d1d44d9c9e9a59525d1972436", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8a43ebafb7a85dd1714ed6945670472666dcb63e8af32b4a74644163fa0e370d", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b83898b2453d0f425275d3bc58140675fc8f14505703103079094093f16be43f", + "semanticDirectDriverSourceSha256": "2db465e56ba41f06b406e039e566d9e3aea0a014fc6a47a6a54d5bc682dabcab", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "00a684f9aea87f68eabf0974681c52461bc308631a1252a89c4ed087d7158b28", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "72d9800603a652d6580084bb3b5dac4d4dd6d644324b0d15d293d7c198fd6b55", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v16-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-candidate-historical-identity.json new file mode 100644 index 00000000000..5e4d1f54376 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-candidate-historical-identity.json @@ -0,0 +1,53 @@ +{ + "commandDigest": "sha256:2d826980ee935f9f32108ef3528657a9b0b658dfe9a8ff5bfd499f17aa908fb6", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 16, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "f5e825c368ebd739afa51711bfbbc72ac4d19a9d23bcafd9738ff0e337f55eaf" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v16-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-identity.json new file mode 100644 index 00000000000..710031028ab --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:8591f9a78a16aac4cf558733cd512f09def483fc11c673504bf93be7476d994c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 16, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "eec0e3740173ea377e73f54da1260a9063606e0dcbc3f08ddb01942a50085f56", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v16-mainline-pi-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-mainline-pi-identity.json new file mode 100644 index 00000000000..710031028ab --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v16-mainline-pi-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:8591f9a78a16aac4cf558733cd512f09def483fc11c673504bf93be7476d994c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 16, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "eec0e3740173ea377e73f54da1260a9063606e0dcbc3f08ddb01942a50085f56", + "semanticValidatorsSourceSha256": "950b49b233d8dd62ff858398becfc55f0a181160cb8a434d9221b5c17816867c", + "semanticSchemaBundleSourceSha256": "2974c75590f816fbdbc7806f531698fdc8d62a99601a17625b81de0f074d6383", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v17-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-candidate-historical-identity.json new file mode 100644 index 00000000000..a47b3b1241e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-candidate-historical-identity.json @@ -0,0 +1,54 @@ +{ + "commandDigest": "sha256:bb7c8cdd1ee01065015b0c88e32fac953d5fbe2b2bb224781df57ca87c820a47", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 17, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "nativeExecutionSourceSha256": "98aad5290e0ffef0628e5f6ef2e5e9589efc55b7fe29c5009681001f123c54f0", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "f5e825c368ebd739afa51711bfbbc72ac4d19a9d23bcafd9738ff0e337f55eaf" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v17-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-identity.json new file mode 100644 index 00000000000..a35bae20552 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:481d0852ae8272a90f9912723d540518a874a0da65a9070e33b52ea1a14cbd7f", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 17, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v17-mainline-pi-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-mainline-pi-identity.json new file mode 100644 index 00000000000..a35bae20552 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v17-mainline-pi-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:481d0852ae8272a90f9912723d540518a874a0da65a9070e33b52ea1a14cbd7f", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 17, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v18-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-candidate-historical-identity.json new file mode 100644 index 00000000000..19ce46572f5 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-candidate-historical-identity.json @@ -0,0 +1,55 @@ +{ + "commandDigest": "sha256:8fb78eb902e7b162045d887b21c4738a4cd18326015c523c762601fd45f9c8e7", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 18, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "guardedInstallationSourceSha256": "be0271e809639a4e6e0ecb21f3f04e6d7f17b2374682930a8b85798c1eb70e71", + "nativeExecutionSourceSha256": "f34b5e28109ed183d922fdd9d6c15acc4a1e57dcda118ca9a114c8905dd0a3d0", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v18-claude-qualification-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-claude-qualification-identity.json new file mode 100644 index 00000000000..eab746e74c7 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-claude-qualification-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:bc0827bd362d01b5595738515f0ca1adcd6961ec622034cbda4633b0f5ec4701", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 18, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "d2777bfc3e15ee7861ce57a069ffb55d3dc266364adf7915845bfbad5aa2e402", + "semanticDirectDriverSourceSha256": "187772a17e5d4f854ec10f37abfcd294cf4f1db58a91d18e7645f4a8c617f329", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fb4a232460dc9e6c7e7221cb4ddd66d7cb82fa0b35e1b3eb04f2d1ee5ee18c86", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v18-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-identity.json new file mode 100644 index 00000000000..a29dab9a1c8 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:2ec904f44218f51058fa83d7437b26c4551e1c65e6f2c55f5a6386fa4061e96d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 18, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "969c1c47bc538422210e3789bd53249ebf0f6be335a38c7997d201f0783dfd6b", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v18-muse-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-muse-historical-identity.json new file mode 100644 index 00000000000..4898bec9abb --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v18-muse-historical-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:5e79c2b1a42b98a545bafe9e93f8c6b6c423bec1c18dc1f0a3cf48477b757389", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 18, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "2232194f5da2efb3681a5727d93af5253fe7416fdea41bc4fc98ca5deeb0e4b8", + "semanticSchemaBundleSourceSha256": "1e2b5d573a929c34a7104efe6dea9621218fb7fe7eac3851a24c41d8284c8dd4", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v19-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-candidate-historical-identity.json new file mode 100644 index 00000000000..ba9aa9672d1 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-candidate-historical-identity.json @@ -0,0 +1,58 @@ +{ + "commandDigest": "sha256:c2825f706f839071ce5aa9ddc2a058d785a55644964ff9c2ba878ac9ccc66fef", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 19, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "runtimeRequestBridgeSourceSha256": "646c01cc073e62f577ecebb6554d785b08edb3fd6e2fcb4db402e17974edd25b", + "runtimeRequestFacadeSourceSha256": "773b860fb7a1444bc769569fbc8a3b67bd08d7ade3e7a843358e4c707f182b72", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "be0271e809639a4e6e0ecb21f3f04e6d7f17b2374682930a8b85798c1eb70e71", + "nativeExecutionSourceSha256": "f290d8307f57803aac861a1ba6f847774d38c89e62f32293d69effd289d5c0c4", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v19-claude-qualification-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-claude-qualification-identity.json new file mode 100644 index 00000000000..d7886e5a989 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-claude-qualification-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:a4c7e955df18bf2448224ecce2120b43ede8054fe00e7b33b4044b8bd284b321", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 19, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "d2777bfc3e15ee7861ce57a069ffb55d3dc266364adf7915845bfbad5aa2e402", + "semanticDirectDriverSourceSha256": "187772a17e5d4f854ec10f37abfcd294cf4f1db58a91d18e7645f4a8c617f329", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "e9ca8d1a7449fe28b63dcd0f858bfc233f1ec791e159cdd8436d6ea34a3089fe", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v19-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-identity.json new file mode 100644 index 00000000000..f4ae581c2f3 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:38abf359adeef43f1f19230245c6e2051c55fdd79571882ef6f00b7cb2958d93", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 19, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "0703401404effcd5d431b5178bde78e9f63f797a39389add22add7c33986f75c", + "semanticSchemaBundleSourceSha256": "95551282468ec16bec4c3ddd0a77a9b2b0e044d7ff018354d4229c3f26e3e228", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v19-muse-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-muse-historical-identity.json new file mode 100644 index 00000000000..67e3b59cdd2 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v19-muse-historical-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:2fec061f29f9cac4f6aa70f9329e1b27ce0c9cf4825030fdbb78979ced9bc201", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 19, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "2232194f5da2efb3681a5727d93af5253fe7416fdea41bc4fc98ca5deeb0e4b8", + "semanticSchemaBundleSourceSha256": "559bde5f5e6433080fc5afd54ea35dc51a378f395b2c45728261b328b7d4d3fc", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v20-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v20-candidate-historical-identity.json new file mode 100644 index 00000000000..5406d93c5dc --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v20-candidate-historical-identity.json @@ -0,0 +1,68 @@ +{ + "commandDigest": "sha256:6ab53285d7cb0eaf79fafec9e0bf0f1a42044761b4b0cf129e0159c8c2fad539", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 20, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "nativeSessionRuntimeSourceSha256": "882ca4304ff32077e0e16eb7366512d10f9c08d75d3f1204e6a7f6c60dbea03e", + "nativeRuntimeContextSourceSha256": "b61065b993d79a8cb6525fe6b398049150d8c9c19dac18dd1d0ce57ae38e1f99", + "nativeSessionContractSourceSha256": "0262d1bc0b43894473bde2f05064455ebf73fbb1cd1c0cfa5f42e19596ef80fb", + "harnessSessionContractSourceSha256": "ffc9e67b4e864ab310f22d94edc4e0898222a4e576ffc6baa422d505909a6868", + "harnessBackendSourceSha256": "31a1da9cb93fcf9eef65162217ef0e35199557b06d8d232b1265a2af3f3072d7", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "d0e7fd07ae41623ec19160b1e1c6895b1ebc3de53bb6aafc79efae6c1e32bcdb", + "nativeBackendSourceSha256": "b408aed94ed9125c62ca8cae030f79add2dc511f3c109063710eb978e7e4c65e", + "nativeBackendFactorySourceSha256": "4c8435dc9930b9823268625387e29e1a92d95696e9ebeb4a7127ec467909b283", + "nativeInstructionsSourceSha256": "e7c46e81cc9c93f9a4f805b5091ef08c59ea70c62f208cfda70d6edeed363898", + "runtimeRequestBridgeSourceSha256": "0d371a09048a592495ae5a0531ad9e9d619e26018318897fabb5b45a10c05837", + "runtimeRequestFacadeSourceSha256": "773b860fb7a1444bc769569fbc8a3b67bd08d7ade3e7a843358e4c707f182b72", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "be0271e809639a4e6e0ecb21f3f04e6d7f17b2374682930a8b85798c1eb70e71", + "nativeExecutionSourceSha256": "c55bdafb9a5ed97c09117c168ecd0e496ea8ae8b6e84200d90c375a143892fdc", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v20-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v20-identity.json new file mode 100644 index 00000000000..ae941843d3f --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v20-identity.json @@ -0,0 +1,43 @@ +{ + "commandDigest": "sha256:7fa710c697582b1b4d85cdf833178b1940656cb6efb44ac4d356b2f27e6b3d4b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 20, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "91629734a80f0d32295cbce2c573b32af9e345f45302ff4525c269f66811aa06", + "semanticDirectDriverSourceSha256": "2b7b7eaadee658312816ecdcbcb311ce491521fedf39e2ecb571036c36ff7b8e", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v21-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v21-identity.json new file mode 100644 index 00000000000..72e3254d6ea --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v21-identity.json @@ -0,0 +1,70 @@ +{ + "commandDigest": "sha256:3bd433d9835ab6998ee712da41cad724006bb85d444f0cf96550708565605b7d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 21, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "55a912125cd9cb71c80aafb7dc013aabf88002b7a8c95b3c74c3201ebc8ef527", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "6f872180254a747262c3b4a084012704676d7d0b9d9ceb9837709a0bd9c75f70", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "f65b3d667c7d2657384284aba14557e8ea736fef2ae458bacc98d64f280232dd", + "semanticDirectDriverSourceSha256": "5012d883c2dd192fff20308a87e0b4001fa4b258a774cec4751728bfe781185d", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "b1ce59251bf9c671f66e0e5173646190b9a2d1bfc5bdb7fb123824213986b92b", + "semanticCompletionContractSourceSha256": "bd4bb79d2be5c4ee3765df67dfb4da98ef95bc532cac872be40cb41a6bff6cda", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "66f717653936a80ef3897348adead666c842b6e56278521f4f2541d0a430b51b", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "nativeSessionRuntimeSourceSha256": "882ca4304ff32077e0e16eb7366512d10f9c08d75d3f1204e6a7f6c60dbea03e", + "nativeRuntimeContextSourceSha256": "b61065b993d79a8cb6525fe6b398049150d8c9c19dac18dd1d0ce57ae38e1f99", + "nativeSessionContractSourceSha256": "0262d1bc0b43894473bde2f05064455ebf73fbb1cd1c0cfa5f42e19596ef80fb", + "harnessSessionContractSourceSha256": "ffc9e67b4e864ab310f22d94edc4e0898222a4e576ffc6baa422d505909a6868", + "harnessBackendSourceSha256": "31a1da9cb93fcf9eef65162217ef0e35199557b06d8d232b1265a2af3f3072d7", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "d0e7fd07ae41623ec19160b1e1c6895b1ebc3de53bb6aafc79efae6c1e32bcdb", + "nativeBackendSourceSha256": "cf953a154f89e19597504e9426a390ca16c85b41630d5df3f0f28c145a0eafcf", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "bbdab79c5b1bd57c4ddbc44edfe745b40eb694aa28a465452964109aedd6104b", + "runtimeRequestBridgeSourceSha256": "0d371a09048a592495ae5a0531ad9e9d619e26018318897fabb5b45a10c05837", + "runtimeRequestFacadeSourceSha256": "773b860fb7a1444bc769569fbc8a3b67bd08d7ade3e7a843358e4c707f182b72", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "be0271e809639a4e6e0ecb21f3f04e6d7f17b2374682930a8b85798c1eb70e71", + "nativeExecutionSourceSha256": "60dd195863bc31b29e7da51be4b90bf84390d3c9da27efe71cd43b45db68d610", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "3c03535df58d6f8d746ce3513a7e1c195f0145e622448ebb10f7d19b6a603aca", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d54e5f125225921e8e69d83343c7457448ed79fb1543a50e5d8554f37d2207da", + "sidecarErrorSourceSha256": "bfc8da59815a8c31cb79d2560b04492ee93736188ac629009e69a4e0a7a1829c", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "runtimeHostSourceSha256": "7a43934ef7ff7ecd9c6f2da729c439efd636e3453022cd44ad035d0b596c4eeb", + "runtimeAdapterSourceSha256": "5a056b64e0c187bd74aa7d04265a9b1db20e2f0d9d93880e0d628b4d25a55fc7", + "runtimeSandboxSourceSha256": "e56b7afda01cd4d3b16559c3a76939a967ab2993aa73848588bc6ab3aa223c4b", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v21-mainline-monitor-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v21-mainline-monitor-identity.json new file mode 100644 index 00000000000..775b2c35671 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v21-mainline-monitor-identity.json @@ -0,0 +1,44 @@ +{ + "commandDigest": "sha256:1dad3d26d91e66c6f911dbfa43e7963f36c0bbf0d7709f4bbb568029a8b4b46a", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 21, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "49421a779c76e286ce65d75052026eab9630b1995af9ccf045a2d43d284633ce", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "permissionIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17371b10bef0acfe7a5980e20fd575165f3e28c91608d38590fdca67d58c4edf", + "semanticDirectDriverSourceSha256": "9c27a6ef55d65190af11b597ee2214ba836b4d992cb75d2eccf9c3ea3311d07c", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v22-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v22-identity.json new file mode 100644 index 00000000000..412c03b1344 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v22-identity.json @@ -0,0 +1,76 @@ +{ + "commandDigest": "sha256:23ab62a38a051c4ec3476fc8b268d0e9da75dae6664a263cb67d852639986958", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 22, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "eec0e3740173ea377e73f54da1260a9063606e0dcbc3f08ddb01942a50085f56", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "193d04140079d2669f53ef043bea6935bd20e1fba6693abf01a09d8c8fcb6d78", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "a49520b53273dd5608f59f22911d1b1484a64c52e3b43614348a9428a4f3b3be", + "nativeRuntimeContextSourceSha256": "b5750e673c50730af3823de22a2d9451074cd38788b6d75cfd69b26321389ec1", + "nativeSessionContractSourceSha256": "8cdf0ea723d58057f2425ed267a92a317c065c917c6236d323c0ed846b05c3d9", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "d529e67744a4cf8d0bb1aaa466b1df40fbab35765796da9c96c046204e194402", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "e76f9e761e1da5a02ed2f52e04669bdda25bfe34e0710bdfe9dff5a55800807b", + "nativeBackendSourceSha256": "a888e389874d2fae6e1f1d2074df0aab9abb6502f9afca9d15ff13708ee43753", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "1ac0c145dfc03ceca646267b74fa7b59d963189913768c46544579709e0914b6", + "runtimeRequestBridgeSourceSha256": "e958d18f331b2f99385136f9bda842237730739a7f870ecbf60f195cfcea7019", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "5733d411ddd3fe9efca4c44f9894c866579f5a0ee5fe74f92de3698482d00fdf", + "nativeExecutionSourceSha256": "cf4ac0008807bbd1852d4cbf8a964d3a2fca0b0573e5789dd3e902a70f952e82", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "124cf112f5279f698f62f9b79d8bae3a43933a6aa86174f74869edb4a63ba0b6", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "d760653024dc40e638d80f2030ee2f3af08a9138fddfd01db6932cc547f36708", + "runtimeAdapterSourceSha256": "db9667f1142e05dd23dbe6c2d82b53403428df249494eb45832590f630db7e0d", + "runtimeSandboxSourceSha256": "27f54e5af5d89d3cee06f9af549b9fb57b6f411079477a36b808146e758b79ab", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v23-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v23-identity.json new file mode 100644 index 00000000000..55aafdb3017 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v23-identity.json @@ -0,0 +1,77 @@ +{ + "commandDigest": "sha256:5eaed611f9cc611711d9df2dada864402a0a8fd01d980d36df9f0c47d2cfd0a3", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 23, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "eec0e3740173ea377e73f54da1260a9063606e0dcbc3f08ddb01942a50085f56", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "affc67a3b4fa38a1337c0779c55fdf0b32f46ea5c8dbbfe02c3359cb2ca26034", + "nativeRuntimeContextSourceSha256": "b5750e673c50730af3823de22a2d9451074cd38788b6d75cfd69b26321389ec1", + "nativeSessionContractSourceSha256": "8cdf0ea723d58057f2425ed267a92a317c065c917c6236d323c0ed846b05c3d9", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "d529e67744a4cf8d0bb1aaa466b1df40fbab35765796da9c96c046204e194402", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "e76f9e761e1da5a02ed2f52e04669bdda25bfe34e0710bdfe9dff5a55800807b", + "nativeBackendSourceSha256": "a888e389874d2fae6e1f1d2074df0aab9abb6502f9afca9d15ff13708ee43753", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "1ac0c145dfc03ceca646267b74fa7b59d963189913768c46544579709e0914b6", + "runtimeRequestBridgeSourceSha256": "8aa06dda1d672acb42604f96d32d56ea0ed407d688bae127dae6786ab2420fa5", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "5733d411ddd3fe9efca4c44f9894c866579f5a0ee5fe74f92de3698482d00fdf", + "nativeExecutionSourceSha256": "cf4ac0008807bbd1852d4cbf8a964d3a2fca0b0573e5789dd3e902a70f952e82", + "profileCompatibilitySourceSha256": "36b47dd253cb10453604268874bffc5ab95a42583bc06322d5d6b0a3a6df39dd", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "124cf112f5279f698f62f9b79d8bae3a43933a6aa86174f74869edb4a63ba0b6", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "d760653024dc40e638d80f2030ee2f3af08a9138fddfd01db6932cc547f36708", + "runtimeAdapterSourceSha256": "db9667f1142e05dd23dbe6c2d82b53403428df249494eb45832590f630db7e0d", + "runtimeSandboxSourceSha256": "27f54e5af5d89d3cee06f9af549b9fb57b6f411079477a36b808146e758b79ab", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v24-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v24-identity.json new file mode 100644 index 00000000000..8ecdb67c4a5 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v24-identity.json @@ -0,0 +1,79 @@ +{ + "commandDigest": "sha256:49eda44589442769ee327e82ecb8f97569c7f8e746e741c51bbc83b536921b73", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 24, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "affc67a3b4fa38a1337c0779c55fdf0b32f46ea5c8dbbfe02c3359cb2ca26034", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "8cdf0ea723d58057f2425ed267a92a317c065c917c6236d323c0ed846b05c3d9", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "d529e67744a4cf8d0bb1aaa466b1df40fbab35765796da9c96c046204e194402", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a888e389874d2fae6e1f1d2074df0aab9abb6502f9afca9d15ff13708ee43753", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "1ac0c145dfc03ceca646267b74fa7b59d963189913768c46544579709e0914b6", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "5733d411ddd3fe9efca4c44f9894c866579f5a0ee5fe74f92de3698482d00fdf", + "nativeExecutionSourceSha256": "cf4ac0008807bbd1852d4cbf8a964d3a2fca0b0573e5789dd3e902a70f952e82", + "profileCompatibilitySourceSha256": "b4baf41218ff7e62f86a536845f6eaa0eb5aff516f5af6ae5f8a544dfc55a5fb", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "d760653024dc40e638d80f2030ee2f3af08a9138fddfd01db6932cc547f36708", + "runtimeAdapterSourceSha256": "db9667f1142e05dd23dbe6c2d82b53403428df249494eb45832590f630db7e0d", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v25-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v25-identity.json new file mode 100644 index 00000000000..5398f630f92 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v25-identity.json @@ -0,0 +1,79 @@ +{ + "commandDigest": "sha256:0d46cf680680cca0cd0c71259a4893c812f121492706b9f26248cdfcf9d603fe", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 25, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "affc67a3b4fa38a1337c0779c55fdf0b32f46ea5c8dbbfe02c3359cb2ca26034", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "8cdf0ea723d58057f2425ed267a92a317c065c917c6236d323c0ed846b05c3d9", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "d529e67744a4cf8d0bb1aaa466b1df40fbab35765796da9c96c046204e194402", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a888e389874d2fae6e1f1d2074df0aab9abb6502f9afca9d15ff13708ee43753", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "1ac0c145dfc03ceca646267b74fa7b59d963189913768c46544579709e0914b6", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "cf4ac0008807bbd1852d4cbf8a964d3a2fca0b0573e5789dd3e902a70f952e82", + "profileCompatibilitySourceSha256": "658a06c27f9796177440481bb812dd104b36a6ac6ff9a8ad40184529d2063808", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "9d1767a4853768d4d03c2e50dc1f00a6f2b114faa2dfb19dd70e31422722dbdd", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v26-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v26-identity.json new file mode 100644 index 00000000000..7d4e04edc82 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v26-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:1a2a0c35764105e9a85112d05187fee0862af23eeb82a75569b5198e52eaba4f", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 26, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "039fca52266fe21ba74ca64660d21228314d8ed737b19ba67941bfb25086e4d5", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "c3e7328c0d27feb8ee2ca53b1e1c6963c204939ed22b875add748de77c99b52b", + "semanticSchemaBundleSourceSha256": "619f2149a89f952253f8e178645ce4bf986215884b04ce0b7c5ae2ac940849f7", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "affc67a3b4fa38a1337c0779c55fdf0b32f46ea5c8dbbfe02c3359cb2ca26034", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "8cdf0ea723d58057f2425ed267a92a317c065c917c6236d323c0ed846b05c3d9", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "d529e67744a4cf8d0bb1aaa466b1df40fbab35765796da9c96c046204e194402", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a888e389874d2fae6e1f1d2074df0aab9abb6502f9afca9d15ff13708ee43753", + "nativeBackendFactorySourceSha256": "ae91eaa54e2fb4bc58c445e41d6453ecc73864d07f1240dff5936af9987bcaef", + "nativeInstructionsSourceSha256": "1ac0c145dfc03ceca646267b74fa7b59d963189913768c46544579709e0914b6", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "cf4ac0008807bbd1852d4cbf8a964d3a2fca0b0573e5789dd3e902a70f952e82", + "profileCompatibilitySourceSha256": "37059f13f1cbb2a477d115eaf23e4ba686e6ee7aafdaead8512b268287ba0078", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "9d1767a4853768d4d03c2e50dc1f00a6f2b114faa2dfb19dd70e31422722dbdd", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v27-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v27-identity.json new file mode 100644 index 00000000000..8a8e0286e1a --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v27-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:9225b7454559569a08d732c747c1174085c7cccc3a5e387c10aff7b3aab1f6e8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 27, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "3f016a2017c6eaa6920709864256c727c6171645bd024cde24315235a1a21ea1", + "profileCompatibilitySourceSha256": "5dcfed3e783e1c1f4ffc7ef98b61096795c6af2b7a92b7b9fa6b8620300a41aa", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "1572b19f84410959ecccbfcb5ffc168ddd85d1a4f8238fabeaaf662f6289fe25", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "9d1767a4853768d4d03c2e50dc1f00a6f2b114faa2dfb19dd70e31422722dbdd", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v28-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v28-identity.json new file mode 100644 index 00000000000..eeda16cc1a9 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v28-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:077c7380a65906fb0bc0cfcd11f261490eafeda16d02b3d28c8dbdf9bce1ae22", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 28, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "3f016a2017c6eaa6920709864256c727c6171645bd024cde24315235a1a21ea1", + "profileCompatibilitySourceSha256": "1368fb7cc741ccd57ff661fd463dcebe6e80b1a1dc410ffbb2d1b0c7934d7a5a", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "9d1767a4853768d4d03c2e50dc1f00a6f2b114faa2dfb19dd70e31422722dbdd", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v29-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v29-identity.json new file mode 100644 index 00000000000..64057b48856 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v29-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:ce118b64cd7a50a93c3ff538b596327bd8e8d172a1bc0bda5d3334948d5d8eb7", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 29, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "3f016a2017c6eaa6920709864256c727c6171645bd024cde24315235a1a21ea1", + "profileCompatibilitySourceSha256": "4e4d098d776631bf8a7b377ae3f3b7ab0494195c441879838c1f1607c5bf6170", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "a1a8784f5883d2c93df6e3695d5499b83e226efb4f26e558639c4e7dbcc2d67a", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v30-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v30-identity.json new file mode 100644 index 00000000000..550b9c75eb5 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v30-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:e21c4a43a937ae84e94726ef93227e8b931fa5547876ff0c5ecff304656d81e9", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 30, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "afcadc9b78d42c598f6822c6da071abbca09024ab231f6b39a30e10e1d9bd38e", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "4cdd702c233bf0d086ff2aeea8f02c6db8817ba0c0bcb5e64e355ee7a1c2dd77", + "profileCompatibilitySourceSha256": "22f33067df484ccaf746544bf1c4641a1bc5fd9e78eeea809b02b5b3f9a930d3", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "e8bdefca57b9678d2b5d99b0bc604301d12993b9c9cc4ecb4b5d3df0b83cec3f", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "a1a8784f5883d2c93df6e3695d5499b83e226efb4f26e558639c4e7dbcc2d67a", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v32-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v32-identity.json new file mode 100644 index 00000000000..d60f7258708 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v32-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:3dcc8de3034e32001b0a819a614beca345d314266a70a09e0050a9f5f58275fc", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 32, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "af192af3fa511347045dfdb86d443be9aa046a4c56bdb48198668cf4d30581b8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "4cdd702c233bf0d086ff2aeea8f02c6db8817ba0c0bcb5e64e355ee7a1c2dd77", + "profileCompatibilitySourceSha256": "fe521686dbd9884eec96ba0963ec00b6b58f4d891aa0292e0dc18b0d84770646", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "a1a8784f5883d2c93df6e3695d5499b83e226efb4f26e558639c4e7dbcc2d67a", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v33-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v33-identity.json new file mode 100644 index 00000000000..e5313db602d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v33-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:482c4e997b4690c7e4a5375dd035560aaad69000f8f5291904d76f8c3a88284a", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 33, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "fedf1e498c1e19daf9c973d475234488aa9acabbf1b9de890245bfac7a534483", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "eebcc1ec9bc8caa8d1edf0cbda74bd69f5c55cf8d65a0503e95798b9979a19dc", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "4b517eed447615b3cc820af348ccc360978175149caa0bbc838d1f78332abe75", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "49f7cb882fa09dcf879a2234d3e7b43fe72895d2c0f1e9b72fcbe18f012423bb", + "semanticDirectDriverSourceSha256": "3cea77a03c8822d68f77f090457176a9190facbec7d88ddf8c583c0e42245f70", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "328436d29148e0b79ce36f36c764b3d780913bdb90d174d1ea03cf1f59b5ef13", + "semanticSchemaBundleSourceSha256": "d8cef4a9ebc136a3d37f3d0be7161986e6d65420e2ec734cfd0dfa468c665c97", + "semanticSidecarProtocolSourceSha256": "907b2cdc1a5291c6fb570855bbcc66cb196b5cf64195d5dc201148940678460a", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "0565d13d4064ed8c501d6ffda6d7bffca4493552de8aaa7fc12178dabb3ca435", + "profileInstallationSourceSha256": "7c26545922fc85db75a5db6bf3f6e21e381b6e189f4f51243b19ee237b93f8b1", + "attachmentPolicySourceSha256": "ce8027d1f8e2b7fd35df56a75ba162fd9696d1569c016b60bc9f0de1252cd958", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "af192af3fa511347045dfdb86d443be9aa046a4c56bdb48198668cf4d30581b8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "75ae4607312ec13466dd2f4ac87f000302b7b5a952cb6d4b51573fa8b7c35d82", + "harnessBackendSourceSha256": "3b11fd93b82ef13d5e6396217e3f102f900437f4d32efb00a9d75a9d2214e6ff", + "harnessSessionSourceSha256": "a9d748b8530544342bbc9f59968816664872782a0865db76ca15f28a1705697b", + "transportContractSourceSha256": "16f358c75dd4ae80af3ca921394c5899b15942b80b553e43ddfabb41c1bf31d3", + "nativeBackendSourceSha256": "a23afeab7e7094cb7e3df05e7a9eac822d0144d8c44893dbcc8a0e7b2bce0c85", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "c449568f8abf7e90d5ae7a83b49809d9166461398f8b3046e4fe5f3367f3b052", + "runtimeRequestFacadeSourceSha256": "3d70c6025169779f7886ddf363a1c6fda4add5d14fa3cd49aea46aa1f6a9d8ec", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "8afd25df307772e484e179e58bf54ce1510fe92be694482111d589f9f0ae6e77", + "nativeExecutionSourceSha256": "4cdd702c233bf0d086ff2aeea8f02c6db8817ba0c0bcb5e64e355ee7a1c2dd77", + "profileCompatibilitySourceSha256": "7e6afda2d2e5f1cdd09aaa75e4697905a40be175c6065b630b5dffa39c2c99a6", + "installationSourceSha256": "9934653d6983905930099b1691b1f0c05461e04e950bb27dd0f92e64fc8e28e1", + "assetOwnershipSourceSha256": "43005b7e896e0546c1f44cbe4ff3f34ad6d71f275f4b9a8113f73a71e77930c4", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "d5c200bea2e8ab730eb56e32ce2070c8a1b5407e5907108640f76a463d9b9c9c", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "83a5ae07c19681ab195f76363661c2381494b243343270ba363d4db2088932a5", + "runtimeAdapterSourceSha256": "a1a8784f5883d2c93df6e3695d5499b83e226efb4f26e558639c4e7dbcc2d67a", + "runtimeSandboxSourceSha256": "4acec4c9757fe5ef5f2788ce20ced8ca4fde8edcfb63b59d0effcfd4316c048d", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "9bbe8329064ee88418528394f8e1cdc716a0b2b35092dc70729b8850e46b7a68" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v34-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v34-identity.json new file mode 100644 index 00000000000..e65d6be0e4a --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v34-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:6dde98a9dbadf22f17ca28f133dbe2a65fa199827741190f569704e44bdc20ed", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 34, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "a66ee14f858ccf75c69dfbce132900a30724fe1e6baffc26b02d58a6bc5924ac", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "20f8aaa363496a4cbede0f33aeacf869fb50171eaee2d63a892c65b3bda4c6a1", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "baf0b64371fada6c92331f9f88e915292b2761c029fd86452f6de32e26dc7fd6", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "cd825fe44b1d142aff2d293c3fc8a64d55e42a98bdea48e4d4b90f3a3163d232", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "b68686298054da576baa5544fe1364d9febe3f5d6aab5c49f9c69f011764afd3", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v35-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v35-identity.json new file mode 100644 index 00000000000..504c2d251cc --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v35-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:6ecb42102c9440e5c8fe5b462b894f9457f255b29f8c584d8b713057cffe4327", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 35, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "a66ee14f858ccf75c69dfbce132900a30724fe1e6baffc26b02d58a6bc5924ac", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "20f8aaa363496a4cbede0f33aeacf869fb50171eaee2d63a892c65b3bda4c6a1", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v36-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v36-identity.json new file mode 100644 index 00000000000..2a4730b4f87 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v36-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:c5e4f986ed0d0ee3634881e1c3dd4765c6d405f8283f5f75c854ab387c869f94", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 36, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "b3807e33e2df080c7a1e4cd5ef208a7b926707af84fc7886acee1df1f70c9f2a", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "99a3f35521c03c71ba59808678c3a51f2aa1cdd65af96e18767c84c755b40803", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v37-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v37-identity.json new file mode 100644 index 00000000000..ebc37793db6 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v37-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:803ba47437e885985186cb8f287eb5e7ff7977039554fe758f783c716a4c6aba", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 37, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "49d7d09eb6957e596a173b0afd763544afe582f0c1f05cc0992fe51916a8fdb3", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "fd38053930531bcfd1f90e4eacacf3cabe545de94f49b6fb454ec89b7bab3b8c", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "99a3f35521c03c71ba59808678c3a51f2aa1cdd65af96e18767c84c755b40803", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v38-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v38-identity.json new file mode 100644 index 00000000000..e4d7f25901d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v38-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:cd6cf87479e65423a5d373483d0888a53efeda5cf0037a8ffe7acea17ed0dcc3", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 38, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "9abda419ccd6c4ed7c2a94cf341675f81164519fd0a8c955d5f47493655b8715", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "fd38053930531bcfd1f90e4eacacf3cabe545de94f49b6fb454ec89b7bab3b8c", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "99a3f35521c03c71ba59808678c3a51f2aa1cdd65af96e18767c84c755b40803", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v39-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v39-identity.json new file mode 100644 index 00000000000..dffc1f033ff --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v39-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:82878a8275c2f50be7dcb1b236c4cad17e162437970aba4b37a5ebc6eb279316", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 39, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "93251b1eadc686e9d8339d4dfc50b995a3d0a9e6ad8aedc6f2bdf7e30c16138d", + "harnessSessionContractSourceSha256": "9e3d62b712cae91168c96d11ff850b97a144809b5cddfe08ec9a91229e9bfc40", + "harnessBackendSourceSha256": "46fd6523f986d5406eca3b420fe920f1d51a6435fb7afc2acf4d21be13af447f", + "harnessSessionSourceSha256": "4dff9bb3370c5560cfc910a7ee814a27725b469c3b1b5dc021e3c0b158ebe746", + "transportContractSourceSha256": "5cd208fe11c3bedd476494b0609fb32efbabe4a1170e2c5854d0aa5e429bd6f4", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "ea85be2aca8dfbd6b4042dcd7b1ed9db9a57baf8c379649a3f5d7d80ca54a6a2", + "runtimeRequestBridgeSourceSha256": "fd38053930531bcfd1f90e4eacacf3cabe545de94f49b6fb454ec89b7bab3b8c", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "99a3f35521c03c71ba59808678c3a51f2aa1cdd65af96e18767c84c755b40803", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v40-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v40-identity.json new file mode 100644 index 00000000000..280c227cb7e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v40-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:a63549478ffe915e6f06cd644869eed6d449f146ac17562703056db622acf561", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 40, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "3b0ac8d3f3cb92747d0bcea472ab0419a140e1cfdc43047e2c22542acc2d105f", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "4f0219ed00938c5d8bc1b11532ecab9c13230012b23bfd6b7dd6b992e58e98d5", + "semanticSchemaBundleSourceSha256": "fe82ac2cbf194d31ac801de6a3cacfb165cb34146c5c26557f283b8c87a5f01e", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "a03575b3a737dea60da94cf0fa1feed80719a9aaa7f09456eb57a845d9e8e087", + "configuredEnvironmentRustSourceSha256": "55d44e48e217385b5c64b1b7d8df16dda62319ca3fb524e452fd78c9ed804d3b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "aac818c1cf50a25899ae95cafc70f093c8cd8af37d19f88cbb7847b4d202d2b6", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "8d6e582655b87a292f043154c65d789a4164c33c41cbc4bc5960c4803f27d662", + "harnessSessionContractSourceSha256": "5a1d98247c3a8fb620cc51da31f8c316b14b97a7102b06b67c28d685d00f29eb", + "harnessBackendSourceSha256": "697093e76a78e9b1245b0eb60219d4aa23369260bd1465955e4726f741b4ebbe", + "harnessSessionSourceSha256": "49d59208990800d982065d76c3dd73e06ca9f9b2abd41b92b8a33bdc7364decc", + "transportContractSourceSha256": "e72c9b4ebe5871cfd25616c5df91a38bdd546747f228de539dc4002c19474e99", + "nativeBackendSourceSha256": "294b9d830bc58c05985087875523db133d32cf999703140fd927e843399424db", + "nativeBackendFactorySourceSha256": "ce22825a53669f8c2db5aaa890bae94af19ede22295bda4ed7987a31d804cd8a", + "nativeInstructionsSourceSha256": "b88e1ee4d23de2c731b55f85ada4c3a33104d1ed6cbcbb0f858c0a04cfdbf013", + "runtimeRequestBridgeSourceSha256": "fe7c75c8393e19b352ab020b23033a90c12641b52cf83e18dba738d94f494208", + "runtimeRequestFacadeSourceSha256": "e1993906ac9f47eb4ea04ae815db869ecde72f582af460cc0080308670612c8f", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "2881b655112f165320a73753385cd54286139a0273a5fa30c1b43fc3b5981a25", + "nativeExecutionSourceSha256": "9c702e518862c396ccfa12d84d11cb8dec1fc064c595359e31cc3e299a7378cc", + "profileCompatibilitySourceSha256": "99a3f35521c03c71ba59808678c3a51f2aa1cdd65af96e18767c84c755b40803", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "f8dc40ea1aa894bd44754a35a8f65fbcaa2f4c7ffc88cc5fdaa965e0d378d9bc", + "sidecarErrorSourceSha256": "23f3dbdc1ce488c690d218a854c820f4b4f3edd822bad574d67707314f8c512a", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "fd62912cdbaf76e73664024fcec835e899e967a4889fdfdccde7eb215c545f8a", + "runtimeAdapterSourceSha256": "3aea6448dc6474e465e5267b61798ad5449bdaec3f4a41bc4be831426893a9bb", + "runtimeSandboxSourceSha256": "1c1ddb0b24c3417250ce161cda897ba59b1adce7c7609ed553be298464e6c1c4", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v41-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v41-identity.json new file mode 100644 index 00000000000..9f6797eb42a --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v41-identity.json @@ -0,0 +1,81 @@ +{ + "commandDigest": "sha256:1fcb0d545bd1711b8871ff47dc4f0f3cc9933d4584f4da5355212189a14bc577", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 41, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7fd06053db98cc763c7205424069a5286c9d4cfefb3d197a4a765c693dccb7e6", + "semanticDirectDriverSourceSha256": "77882e21ad45b66a688fd1933dbd4fc89fad38e8c1f092805cb9485bdd5223c5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "fa2b0c81cb9a62965839c905db81b930794774d8d557a01bce077dae5830b594", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "d14744006e0d162f6a1597dd8e8fadd6dcf2a51a61fe0891cabfe3d2d678a5dc", + "runtimeRequestFacadeSourceSha256": "4a1cb9c9b2351b5370b1688ed7dabc2c3bdeba3f990877ec1332be90f7c13a2b", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "d542c82a41edfe28d92d1850e8d4439a1cd57d39b75f461c1a706d63678d4652", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c9c3650b6415430b045533eea2d7cddfe87302e03817f40ae83f7447ef0ae957", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v42-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v42-identity.json new file mode 100644 index 00000000000..788f7c08aee --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v42-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:c26839c0b2b1f66802d1a4c9561da82eb8b533355fda64fe6b771697782c72ed", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 42, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "2b24c094da0793888cdb5197b8961a69c410679dad85ab341f89bb812931e972", + "semanticDirectDriverSourceSha256": "4538023d8a2735505b194dee35628807796c2d6c8a77c3309648d2c8f1fca7d5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "d14744006e0d162f6a1597dd8e8fadd6dcf2a51a61fe0891cabfe3d2d678a5dc", + "runtimeRequestFacadeSourceSha256": "4a1cb9c9b2351b5370b1688ed7dabc2c3bdeba3f990877ec1332be90f7c13a2b", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "8d46a4d3dfa96d08ee2d5d6fd176e2fe6e102ff94d96494274adb730fc774296", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c9c3650b6415430b045533eea2d7cddfe87302e03817f40ae83f7447ef0ae957", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "826e74747a89b83a6f546ee1355de64ae5265eb920b50ae498a41dd561a493ee", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v43-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v43-identity.json new file mode 100644 index 00000000000..1b04c8c2d5e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v43-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:6ff8e40718abc0ce25e3013923e2435c86ef87a2cea9ca9d2c3f2a891828ce9c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 43, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "2b24c094da0793888cdb5197b8961a69c410679dad85ab341f89bb812931e972", + "semanticDirectDriverSourceSha256": "4538023d8a2735505b194dee35628807796c2d6c8a77c3309648d2c8f1fca7d5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "d14744006e0d162f6a1597dd8e8fadd6dcf2a51a61fe0891cabfe3d2d678a5dc", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "c843647818af25cf69907187f13ee140a45ca8512d28951975b39b285c4fe8d7", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c9c3650b6415430b045533eea2d7cddfe87302e03817f40ae83f7447ef0ae957", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v44-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v44-identity.json new file mode 100644 index 00000000000..429e7c86d03 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v44-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:eb3111dae64c506ccdeaab99c8fc42c64f9b46e757af404825fcd55f37e3d96c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 44, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "2b24c094da0793888cdb5197b8961a69c410679dad85ab341f89bb812931e972", + "semanticDirectDriverSourceSha256": "4538023d8a2735505b194dee35628807796c2d6c8a77c3309648d2c8f1fca7d5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "0ff157cf80a767e15312d42f54577a795e49b89298974d4872eb9ab299c3bb79", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "c843647818af25cf69907187f13ee140a45ca8512d28951975b39b285c4fe8d7", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c9c3650b6415430b045533eea2d7cddfe87302e03817f40ae83f7447ef0ae957", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v45-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v45-identity.json new file mode 100644 index 00000000000..50499618127 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v45-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:1ae000c7969e71cae818f9ee210b7b63f4f5336ab42b9be6680357f6a8010205", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 45, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "2b24c094da0793888cdb5197b8961a69c410679dad85ab341f89bb812931e972", + "semanticDirectDriverSourceSha256": "4538023d8a2735505b194dee35628807796c2d6c8a77c3309648d2c8f1fca7d5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "0ff157cf80a767e15312d42f54577a795e49b89298974d4872eb9ab299c3bb79", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "4e348b16eadf8095b3d4d45c22f528a42a53da4bcb7235df50c448f91e5ef648", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c9c3650b6415430b045533eea2d7cddfe87302e03817f40ae83f7447ef0ae957", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v46-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v46-identity.json new file mode 100644 index 00000000000..72635917c83 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v46-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:b93823e6fa44a9f9a8ed1b03f371d15db54ee4c4f3b1d2bbfeea97a634c23e91", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 46, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "cf136da18e2cdbefae8e01d23d2c93f64eb7aebccaec938e84c2887c888f87ee", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "2b24c094da0793888cdb5197b8961a69c410679dad85ab341f89bb812931e972", + "semanticDirectDriverSourceSha256": "4538023d8a2735505b194dee35628807796c2d6c8a77c3309648d2c8f1fca7d5", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "36ad8a83a17111167d3cc4ef4123b36fa648a1825acd59bd90b3f8b566a4d335", + "semanticSidecarProtocolSourceSha256": "334b67857bd81e9924186890258cb2ad41f92b1ef68ec60fa5c5d9fbb277673c", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "afc83fa093afa7a7458ffb46adda0ed9d766723c2d233d5262f9136ef2e4909f", + "configuredEnvironmentRustSourceSha256": "982ed1a1b917a43bd3ea741f9fe23a306c05aee53d633c081409534a18d1a07b", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "79ab6ab323d5b02b6f649bdc61703f8d53f26215fa3555ab72b21d80c9a61278", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "1cb1949a0a9db38a3ed61595533a5464fd8ee8c586ec1ad13700b9a28e9636eb", + "nativeBackendSourceSha256": "0c3791a8a9f7d632804215a0574cec480f6ba130a32ccafbcfce03d7ee5847a1", + "nativeBackendFactorySourceSha256": "02c5cd564029751c4569ff8960d0356d9da63a2e5d2fda958d787f98ee408794", + "nativeInstructionsSourceSha256": "9adf4ff11b5cdaccb312fa9b0343d83213aa071c4ea997d157fbcaa97249aa02", + "runtimeRequestBridgeSourceSha256": "0ff157cf80a767e15312d42f54577a795e49b89298974d4872eb9ab299c3bb79", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "4f6c49b0ca172ac8fcd8f8558a58bec560bbf778f4894b70b0ea4613efb20c70", + "nativeExecutionSourceSha256": "b2bf3ba87219c094e8eb659723d43e394d31bfdd1655999d82fb9c97af66c00f", + "profileCompatibilitySourceSha256": "3ef8ece4b0406f845da7682e4d5744450aaa85bbccc68c5633b440f26c3353ee", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "b29464dd2fcbd1bff3a9cdb4ba97a00d9c4a07a6cdd878f1baaa8a4948d020ca", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "687b96bf222b5f132a57668059df61f1cad8f0ef96189c504a7bbc8f990591cc", + "runtimeAdapterSourceSha256": "5bf35ecee5c3853a01f4b226b881af76e0785944189e37d5b891cc2b1cf1de34", + "runtimeSandboxSourceSha256": "4c0e8b3dca5ecaf60edbf5db26bb55a00bdf800f4523a072c69ed8a92d67f8ca", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v47-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v47-identity.json new file mode 100644 index 00000000000..a335e7ec203 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v47-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:55044aa235e88b3fe36ec8a556ee1e3382590870aab907e4462ef7d64af49cea", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 47, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "a104278d4d0e063a69bb464938db117dc27691b5bd4590c5a359e11f4917f623", + "semanticValidatorsSourceSha256": "38ae5379d47df633564730ec1359a16d21c0d0a68addb5e488b58c697f13362c", + "semanticSchemaBundleSourceSha256": "5e957fe0f0ba164441d6a5b8a276e52cf6f2ffaf99741faca99cff05e539221c", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "0b350f5f4044f342b974254738bab45a470c24db9352b04c92d785d26e7853c8", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "runtimeRequestBridgeSourceSha256": "e87de28ae7337642b545d95ae955ed1e09bdd23e9a0a9528c8009afd9be63ae0", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "2e81a115a20df53643a5adc81e95f10f8cce6c7a318d4910a95a5d51a6eea2c2", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v48-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v48-identity.json new file mode 100644 index 00000000000..499a97c4b6e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v48-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:49171cb881c43270e101a790a109752642870daedc38cd6e91aef08fd7aab038", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 48, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "c010aef271368b27fdbb0a923f6abd376233f2c9bba786f48cc7cf85d87722d4", + "nativeRuntimeContextSourceSha256": "28c28c850bceade8c72b3ea246485d2bc77bd6e1dab95b43e3b319e27ca944bf", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "runtimeRequestBridgeSourceSha256": "e87de28ae7337642b545d95ae955ed1e09bdd23e9a0a9528c8009afd9be63ae0", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "f2e50c76584fbc1603b663f7350a02ca4743b76798373dd4471ea1f45769c07a", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v49-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v49-identity.json new file mode 100644 index 00000000000..db29e67d5a8 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v49-identity.json @@ -0,0 +1,82 @@ +{ + "commandDigest": "sha256:37a8f6a540a7417bb12becbf283158df8cca925c5136ecc0db14597441fff702", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 49, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "28c28c850bceade8c72b3ea246485d2bc77bd6e1dab95b43e3b319e27ca944bf", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "runtimeRequestBridgeSourceSha256": "e87de28ae7337642b545d95ae955ed1e09bdd23e9a0a9528c8009afd9be63ae0", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "cb48e62e051b9120394f1f06282de95a4c95273976c5ed5e00be9f1ffff24a50", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v50-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v50-identity.json new file mode 100644 index 00000000000..808fadba4e4 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v50-identity.json @@ -0,0 +1,83 @@ +{ + "commandDigest": "sha256:d8f89c8e75883a793122ed908016b7730ededa6c3df741f23298c2445d7e6fc4", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 50, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "28c28c850bceade8c72b3ea246485d2bc77bd6e1dab95b43e3b319e27ca944bf", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "2bd265438b88897ab57c73a180009d9f78c382c1576b8d9c16e4bae3dd01c45a", + "runtimeRequestBridgeSourceSha256": "ba198ea55c177906d1de215d119466805452b87abefa1db47a1ffabc205d7a73", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "afbc27f9dcd824d14fc71552f0244614aaa7260a5b9b2cb9d148974c68a42ce6", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v51-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v51-identity.json new file mode 100644 index 00000000000..60e55bd79fc --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v51-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:8c1cddce201eb0e3f2792cc5a8c79edf36b0ce823e728255c1897f95c74a3866", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 51, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "df93bc8bcfa9dfdcf26ad6a69ea0bd3e56ef186c5e962b243fb2288f7074584b", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "291b73a9f62793c41eb269bcbcf463140ee7d2d8dc841c6ea2474a46843d1f47", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "8b52128857f6f5aee77735c14454b0563e8d5b062238235b374b0a27393df659", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v52-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v52-identity.json new file mode 100644 index 00000000000..bd0eee666ff --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v52-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:3614db52d3ddcbc0153c79361a0db2c4324249475d3be490f152b64f916bdd53", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 52, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "df93bc8bcfa9dfdcf26ad6a69ea0bd3e56ef186c5e962b243fb2288f7074584b", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "ec09328c11bb6688269b251a40f84e6c810f32afcb0f31cb79a26ca48be68e73", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "70efe0fe7fa40c96925ce4b699e77597b22097dfc41c04a1ff17af6d194a9605", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "eb877719ef32a935afa4ec93f0f1c43d58d55bc4e1042965febcac4c45ed851c", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v53-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v53-identity.json new file mode 100644 index 00000000000..9d071eed586 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v53-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:6441ff7f3fc664064bff9e7ae80252ddec7a39236f9a4b9d402785eb8b03b2c9", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 53, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f8b381e1ac2a880558f3e81968f0f8f05de3ded573d044fafc89f198f2ec0433", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "df93bc8bcfa9dfdcf26ad6a69ea0bd3e56ef186c5e962b243fb2288f7074584b", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "ec09328c11bb6688269b251a40f84e6c810f32afcb0f31cb79a26ca48be68e73", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "48f589d87ef1459d02134c03c768457fa35123b685573ae29f49d73ff593d817", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "1154778050a39178b09e9fe835173592691f6b679348814f30eaae509d84db0e", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v54-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v54-identity.json new file mode 100644 index 00000000000..1dcef7569af --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v54-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:171d865b9b6ff2eda3926dc957caf2993cd7e1fa1b4359e8b60b83f589bd67fa", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 54, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "b4af7c243a7be3570689fe5506d26b6f093fc893a81a3b5a481f7ee4efd65756", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "df93bc8bcfa9dfdcf26ad6a69ea0bd3e56ef186c5e962b243fb2288f7074584b", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "ec09328c11bb6688269b251a40f84e6c810f32afcb0f31cb79a26ca48be68e73", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "0f16a260a2db3fe8ae6a1962269a475ac64d9b0ad49700ebee0baa4fa3f9acd8", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "1154778050a39178b09e9fe835173592691f6b679348814f30eaae509d84db0e", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v55-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v55-identity.json new file mode 100644 index 00000000000..2e9a43ec690 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v55-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:2c9e7f0fee36d2f7f0b253a86f3587b7bf2d9406f774b3b91e13678881ee7d48", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 55, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "df93bc8bcfa9dfdcf26ad6a69ea0bd3e56ef186c5e962b243fb2288f7074584b", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "fb2e91e9a7f4b10ae0d936e1e1c74ac9095733ef67fe816491be45791048efa1", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "d4edec781031a44f7e96a1e4ef398af4675529b7ec0f9c56c4915d9ec81a20cf", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v56-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v56-identity.json new file mode 100644 index 00000000000..0f0a09fd665 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v56-identity.json @@ -0,0 +1,84 @@ +{ + "commandDigest": "sha256:5a05f59ee74e4e3793d5cdd3428c4c0663af2d4cbebc00f804b8780b149990bb", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 56, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "d7410c57e75e06c39c4686747b2c7311a4089ba3fe1a09e9c98f6e635ff6ce71", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "fb2e91e9a7f4b10ae0d936e1e1c74ac9095733ef67fe816491be45791048efa1", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "ea8783586481c50ba45cd941c0e384b7c122a5ced13f74d0300643b784a9b6cc", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v57-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v57-identity.json new file mode 100644 index 00000000000..d809bb80c70 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v57-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:c643eb4def4a0c9a5c3bf13be42ce653343c61c5d84cda33a989018fe4af3b68", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 57, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "89e3dde25ff35bfd4d7f520fd9d14af3cb9027f182a2d51431d298f1015be580", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "cc90b59bdfe6a82f7fa3e819e8671f71f7b14047e68942e8086618ffbaacf59f", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "e4aacb08015fa9104dce2b0c7d150cc432231c8a3e07d2cec2a325b388f7f382", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "2406483fd35a564971c22e10fc2bad26bae16ff5a3fb6c65690fcf156522ab6d", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "cba71368f82ae8d300123efa09f23744e19e82142788fa9ad238338fefec9624", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "fb2e91e9a7f4b10ae0d936e1e1c74ac9095733ef67fe816491be45791048efa1", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "f6d0c33de38259efefa0f4e0f9737cd30cfd3996a8e875e3fbdb8c72dc133dca", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "4d4db016634fd73c5db4feeabfe58de9ee2fd9a34ca9d54d80c3c33a62124258", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "60e5454f030e87f2afa8b1fb120b26adb126b6b17d0e5e82f49c77f76f466cbb", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v58-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v58-identity.json new file mode 100644 index 00000000000..1ed66328669 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v58-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:d490dacdab02051d24c84aae49ac6fb12b8226cf8a47b014ec53f3d3a8410a94", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 58, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8823475a90f5da3477e86eb2d4d5a221733f1dda7117d0f6ff00e3b6bebabf6b", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "6165e9c3e544c6991b2703ba406f83617d3a939d988355da9d46eded09c4679a", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "e8a3bee66a1ff1c6f251b5ae57453ffb908336da9c4a6d98f41f94f7ee94a8e8", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "4fa9593226ff3280bc12140bfcbc2c0986e4cc8d4733381c334138dd03b08f46", + "nativeBackendSourceSha256": "972c08e6e320d1384221e180391fe817ea1ba632db687201e457d64e68ef4360", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "ee8df5d85b263d5d2d0dc9ede8602cb7daf6388687108fe05e2371f5f56c3492", + "providerLaunchSourceSha256": "d4f4a69baeeb2f3b2f350840f81f711e40f08588c28ea28039748dde90302a51", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "538027aae6e7dcbd6bcad044b1c5996c1d8d4702966524e8189129960cf858fc", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "a3c6e361726e6cf12174c7d89d0c9ad128a8c7b719297deae383f21345469145", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "54fd09ad430dac04df98d829061f6701e73b5bf2a0f4de836d2ac36ee511009f", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v59-hot-upgrade-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v59-hot-upgrade-candidate-historical-identity.json new file mode 100644 index 00000000000..a623aa0d80c --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v59-hot-upgrade-candidate-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:4418740ed8d2ada631094e37b25df5e2fa374fda3c7b66d5045c35fd79ca19b1", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 59, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "972c08e6e320d1384221e180391fe817ea1ba632db687201e457d64e68ef4360", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fb6305de1473a51efa25eff83dcea2ab124dd60cfb8036e5ba56ad6785fc1929", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2e940cf2d55211a46e08fb8575cf6157c438d5acd5e0a46cb72d8dd0ad8951c4", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "6a26b102b78f282137ff93b0f75eb8788c603fc177802c58715c5ad7b2f3b9e3", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v59-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v59-identity.json new file mode 100644 index 00000000000..b087d433186 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v59-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:2f39ffe54a6af832d044b5098c31df9e08d4d27aee0ac675ba4b0c9da7445c40", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 59, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "972c08e6e320d1384221e180391fe817ea1ba632db687201e457d64e68ef4360", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "d4f4a69baeeb2f3b2f350840f81f711e40f08588c28ea28039748dde90302a51", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "7497083b6cf1fc0268187aff948352f3bce6e054ac6e845005846473efdaff15", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "fc7c6568feb0d8d709e9baa51839420c9b90336b4865a9b8405aba06e4d1e9c4", + "profileCompatibilitySourceSha256": "6a26b102b78f282137ff93b0f75eb8788c603fc177802c58715c5ad7b2f3b9e3", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v60-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v60-identity.json new file mode 100644 index 00000000000..82b95ed7321 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v60-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:ca3c2b38ed5f6e25cf1c96c1f73781a86cc90c1c0add93f64716c66f28b3f3aa", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 60, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "8ddd5d26854f4a153a9559ea8105aef95a3ec94f03209e9a797c95932c162e2a", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "8503e7f2f8175e413b42e85a9ff259a00f2278cd966bbeafc9e9e85417cf7dbb", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v61-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v61-identity.json new file mode 100644 index 00000000000..6a641986fce --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v61-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:956276ebee59f880249fa6955adc224af9ca7b6a9da59bcc5da4a8667550c5b3", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 61, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "e6c98128d98a4177c42d68a04c1f749554fd5ec844da1bbbdb3f682670189445", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "f9670b63d68e8b84cb79ab18425028f1ff781adb398cb9955ca80b8e0c9264c7", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v62-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-candidate-historical-identity.json new file mode 100644 index 00000000000..7266c5e13ca --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-candidate-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:1251b53cb4716273c74e5839eb112ef8ca639e0967eb90a9f1a5f5ddafdb642c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 62, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "e6c98128d98a4177c42d68a04c1f749554fd5ec844da1bbbdb3f682670189445", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "be60656e66d7f61a290f8d1c9a3c9ec511fb13b6541825a087b470e971ccc020", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v62-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-identity.json new file mode 100644 index 00000000000..705f0157d7e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:aeeb80bc186569c78911aeaa445c1fdf5e81420cfeadb563d5620497c58dd0f4", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 62, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "9be35e006ffffcca48205f9e53548dd453ec6a8cbcf0aa4dd735194e9619dfc7", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "be60656e66d7f61a290f8d1c9a3c9ec511fb13b6541825a087b470e971ccc020", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v62-sleep-maintenance-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-sleep-maintenance-historical-identity.json new file mode 100644 index 00000000000..504c1c450b4 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v62-sleep-maintenance-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:4c5b7cd84ddbb5375ae044012a87391156633e309f60aba3a99acc80edaee2e0", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 62, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "cd23577bfee9ab95bb8a177d1948917e96a7bf6245f320263fb6526ebf5a76cf", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "be60656e66d7f61a290f8d1c9a3c9ec511fb13b6541825a087b470e971ccc020", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v63-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v63-identity.json new file mode 100644 index 00000000000..10ea2c41afc --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v63-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:1412842a36a7211d84b6b98a3d1f69e3388bc4814e5825da890a774ae0e3460e", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 63, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "9be35e006ffffcca48205f9e53548dd453ec6a8cbcf0aa4dd735194e9619dfc7", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "5b00c3f78ad12321d48e66a90338af2d53d59dd17bb4b72b10ccdb4240b5a150", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v63-reconnect-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v63-reconnect-candidate-historical-identity.json new file mode 100644 index 00000000000..0a6c463f55e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v63-reconnect-candidate-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:3ca9ffc81abda9733eadfcf61ed37cdc6fe80251de744f33bdc8be73ab3e9170", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 63, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "3343df6362252d44d12b079ff78c8f6539d1544f3ce5ec36ff36db70ab0fac31", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "b8c0c38d45f7625c051387136f60fdc2ca1b83e7e58e92fc08360d057b97f95a", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "5b00c3f78ad12321d48e66a90338af2d53d59dd17bb4b72b10ccdb4240b5a150", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "d248e47a0fe7f2536d1e64cea0b0b410f34104800cd643d995b4473104ecc8e0", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v64-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v64-identity.json new file mode 100644 index 00000000000..6b9f3a737ab --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v64-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:22e31f95ef972bcead98a4a707c9f33433558fd111e390e027a2bbb4346e112a", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 64, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "9be35e006ffffcca48205f9e53548dd453ec6a8cbcf0aa4dd735194e9619dfc7", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "2f875a2f39f4e99a3d03ffce9f325ce2461c51c6b8cb70218ce89ec008eaa5b8", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v64-sleep-maintenance-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v64-sleep-maintenance-historical-identity.json new file mode 100644 index 00000000000..c765291d15f --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v64-sleep-maintenance-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:83f8a5bfc7a619c72a2b7bee9e2ce15a0f779f4b483253186b590386186ac76d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 64, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "103b83066da72434602e9e461e6278dfb40bb993d2f3b49b2e93df81bbb08b72", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "ccb98a1696366c67518a6be33d69c9e5e00324a74dee294193a6ba5d536ed53f", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "2f875a2f39f4e99a3d03ffce9f325ce2461c51c6b8cb70218ce89ec008eaa5b8", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v65-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v65-identity.json new file mode 100644 index 00000000000..084c61a32b0 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v65-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:277894e850e07e6801cc24299c237513f58b41eb93c24f751d984fc4ddb04c47", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 65, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "b8c0c38d45f7625c051387136f60fdc2ca1b83e7e58e92fc08360d057b97f95a", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "c89ee3a3831170e044d715b2c26d1b5deb05f4e56481ba971284a7fddbf117a6", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v66-hot-upgrade-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-hot-upgrade-candidate-historical-identity.json new file mode 100644 index 00000000000..d6b3c24d98d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-hot-upgrade-candidate-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:5e9c2d1ca9c1a915ab449871eabd679bc6ac7b62afd96109073b9bbcd8183351", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 66, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "63c14082a11f9b02dea9563408bf22fff9f73b8cec0f9f78e6147572190fd2b4", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "99295623f20124617ba96a2ae9f10a39771de1c6afd540c05e82d6b8a3c6def1", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "d96c3b809d083f9d43936af05e6bc14b1755c55f255c8e5967b8c16661f34ffa", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v66-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-identity.json new file mode 100644 index 00000000000..72cafbda261 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:0cddc219af25b741b7138f38faa7514dd5ee3427b1d3168e8a4bfbe5180983e8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 66, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "4c1abd77bbed9723e669009a78dab6fe024837718ced9f22c159f9e22ce1f26c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "9584d9801b87f67e60b0007beafa909fc5b05dc6adac71409db1c7f80a2f7916", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "121214465210f235bebf096a2ff80b093373d84f08b89902e694e6fedbe6ea94", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "976fef21ec9f3ae9dd5eabb133a55ae578f1c0729c657c30e42562a80db237d8", + "runtimeAdapterSourceSha256": "e2dd18de4b134a5492de93c88b4add479f63fb650c655d60a17c04af722c7563", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v66-sleep-maintenance-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-sleep-maintenance-historical-identity.json new file mode 100644 index 00000000000..423589c1057 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v66-sleep-maintenance-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:ee0e229a3db5849b5f5528489a44e4450939d9854d6ef98d29a48611acf250f5", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 66, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "fa8db1c42c378898287c141d8cea9069166981e369c9b9c51422cb6177de5a2c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "cda99b35c428c4189c116c62b34349fc92e6f2de951d58847197b2d17bdb57de", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "d96c3b809d083f9d43936af05e6bc14b1755c55f255c8e5967b8c16661f34ffa", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v67-grok-native-effort-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v67-grok-native-effort-candidate-historical-identity.json new file mode 100644 index 00000000000..7805e82d794 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v67-grok-native-effort-candidate-historical-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:2c0854674e3d00fd00cb0659b5ddb9788f47fb2b11f771901f338cb384926318", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 67, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "4c1abd77bbed9723e669009a78dab6fe024837718ced9f22c159f9e22ce1f26c", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "9584d9801b87f67e60b0007beafa909fc5b05dc6adac71409db1c7f80a2f7916", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "4b0f14e8e2a34e1b6795a5be63265451e36c7583d99a246c5471e01f26f6e170", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "976fef21ec9f3ae9dd5eabb133a55ae578f1c0729c657c30e42562a80db237d8", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v67-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v67-identity.json new file mode 100644 index 00000000000..d105cf07a6e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v67-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:7f5897a354d5cd8bdcd165d3e3bab4d6908aaca3981af384f4dfeb4bc0838fd8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 67, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "17361d1782c0dcebb2b7972635f45c890f2a4081f8bc0ef2d2276550e0b91629", + "semanticDirectDriverSourceSha256": "ff572638f2cb5d9f8249ff8e2f412311c1e3af209ef0bf7e5ea9f10a21d91103", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "016391a087cc217aafed4ba1f4efafc6e4881a7525952dce824b7f4d24530603", + "semanticSidecarProtocolSourceSha256": "03c0c95b900f9dc18f29f6be27b8c79bc0bcab29780190d46a74e95328081236", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "03f4cd7f76f34f6d82e009b66aa51f18f6e23dc235b660778060e35b6ea07412", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "e7b12d4418c7a71f5f2474b046697d3009eae3613b284bec381df5e9965a1c37", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "9173ebccf09cb56a781d2bf5c7eb27fdafb13d3450d99342c6aff86b42d6b43a", + "providerLaunchSourceSha256": "63c14082a11f9b02dea9563408bf22fff9f73b8cec0f9f78e6147572190fd2b4", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "5f2255933fb9974063c9f0cf312333f2d283cc3ec879a217834759c7d00c37b0", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "3a30d52bffad68c7f02349193be84761050eb99039fc0556c2b449891a36e918", + "profileCompatibilitySourceSha256": "94aaea13c8a6957097cfcf5794a6fd5035a00a3f5c7aabee1019a1ca6b9a1670", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "94a73749267f5a80b5df19413a65b4b9263c00a9bf7e98fda00f00b8f9fd32ec", + "runtimeAdapterSourceSha256": "e4c764c2c3c7dd655a965b39472bd1ad8d577d1e7258b25594b171c9429752b8", + "runtimeSandboxSourceSha256": "92dfa53f5a3ed0062913ae417eeccec243b430d444495efde2a8e9c4c02e78ea", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v68-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v68-identity.json new file mode 100644 index 00000000000..397ee98de59 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v68-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:1ce8bb0e00df81fa9eb71cff5063ce769637f5db7b3aa0ada9ade651db089c63", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 68, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "7b4706f8af55f0359b28d2f941a7774f2932bd8ca4f0aa883559f7aa9e781253", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "976fef21ec9f3ae9dd5eabb133a55ae578f1c0729c657c30e42562a80db237d8", + "runtimeAdapterSourceSha256": "e2dd18de4b134a5492de93c88b4add479f63fb650c655d60a17c04af722c7563", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v69-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v69-identity.json new file mode 100644 index 00000000000..1b84327a954 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v69-identity.json @@ -0,0 +1,85 @@ +{ + "commandDigest": "sha256:5444547ca83543bc899ae5a8a2e895c19a86559339e60a1970786ce900742719", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 69, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "3513d4b0c57a17b125f7d83e3a844be4b88de7475577dac99132aef00cbdca63", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "sidecarErrorSourceSha256": "b09af4577f8bf42eee7036b2ad9842202cfc763e72b53c3287f82c6090cdad80", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "976fef21ec9f3ae9dd5eabb133a55ae578f1c0729c657c30e42562a80db237d8", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v7-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v7-identity.json new file mode 100644 index 00000000000..9385e88e31d --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v7-identity.json @@ -0,0 +1,22 @@ +{ + "commandDigest": "sha256:b11721382293b39c1d6dd363eae547b5eae0ccca2cd5dcafc9127cc060ee9526", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 7, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "79aad2d688b03362e8cfcbf7a08f78a8383869f6882a9c9ed66f1d18efb94f2b", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json new file mode 100644 index 00000000000..8908e2f0fb1 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v70-identity.json @@ -0,0 +1,87 @@ +{ + "commandDigest": "sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 70, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "0832086e776ae28048f78ce87664bd196b73349899168746833d943e399bed76", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v71-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v71-identity.json new file mode 100644 index 00000000000..b63939866db --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v71-identity.json @@ -0,0 +1,87 @@ +{ + "commandDigest": "sha256:b7a25fe627daf3857ac8097d9a374b1ba15355176389b92457838bf19e9d91bd", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 71, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "8a79f4b6f38e4781a056a2e9a7a07cc609c72638993ae16a68853a6189f575fe", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v72-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v72-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..cac7c1b62f8 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v72-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,87 @@ +{ + "commandDigest": "sha256:dc746f2f41a58f0f6af1aff15bbbd647fb0c9320b4d6302c90608429b80f61ac", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 72, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "9155967097d5fc3abc2c4c56c7189cd57985ce1a2f398be323fe73cddbd97d3d", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "9dd16ebb4b62c3f74fa8a5968ea527126b25d7c13ffc63bd11648ad662b47ca2", + "configuredEnvironmentRustSourceSha256": "f58af4bbb1b36b91b3b32a62e02eb85280e17472805861a8bdab650041799a68", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "666ef3fbd8ea2244da7422ca4d0a56df263f1047ec48d4ccbfde14e60f3358f6", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "48d7baa54960a47d6012079093ab88343b975ce85df88cd9b2211647b27e4f71", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "2035b9866db328f0394e6d65f49d64e7fee0737ecf4d16a00634027a0c2b78f7", + "profileCompatibilitySourceSha256": "8bde7482f64726613788008a7c5c59117040e5f7026033dd1bddb11065fe3b3d", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v72-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v72-identity.json new file mode 100644 index 00000000000..9ba3286f97e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v72-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:a6a8b2ed778571abc8f61e497b59387887a1b7bb78ebce6fda663f38fc008bf4", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 72, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "93f4c3ffc4e56f13daaf0ee4e1dfe86e06cca16422ca94b2201f968e355d93ee", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c82c0e586d9b10868887a8805e8e52295f8ba610c40014b6ae9562b3c3b44cc9", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "c4edb57b63c01c7c8a07dcd25d625cb2528fddd7e0126fe12bd934edf1339a5c", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v73-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v73-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..9b942dc08d5 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v73-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,87 @@ +{ + "commandDigest": "sha256:c17e9a5daa0af5a2e15f4236989ebd8285a134e8a23b8c8e3b4b434089251e13", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 73, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "9155967097d5fc3abc2c4c56c7189cd57985ce1a2f398be323fe73cddbd97d3d", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "9dd16ebb4b62c3f74fa8a5968ea527126b25d7c13ffc63bd11648ad662b47ca2", + "configuredEnvironmentRustSourceSha256": "f58af4bbb1b36b91b3b32a62e02eb85280e17472805861a8bdab650041799a68", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "3163e952ab0e33a75139a7c72a96d1d2d8ac18c03540d63cf0b3fb4265c19f0b", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "48d7baa54960a47d6012079093ab88343b975ce85df88cd9b2211647b27e4f71", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "2035b9866db328f0394e6d65f49d64e7fee0737ecf4d16a00634027a0c2b78f7", + "profileCompatibilitySourceSha256": "e84b39fc6698af7eca5ffb810551c1fde9a06475fafe5dc7d77ca2bbf4ea752d", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v73-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v73-identity.json new file mode 100644 index 00000000000..d046871edd2 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v73-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:53d6b53ecbad96175acf39a075bf5fd7041c485b5da2bc19765e32ba53806542", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 73, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "2310792c31444a110138a70185a9532bc9f3f2e5f9909cb37a26c9a334ee374e", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "c82c0e586d9b10868887a8805e8e52295f8ba610c40014b6ae9562b3c3b44cc9", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "c4edb57b63c01c7c8a07dcd25d625cb2528fddd7e0126fe12bd934edf1339a5c", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v74-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v74-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..ce02368e098 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v74-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,87 @@ +{ + "commandDigest": "sha256:0a0430cf135aa1b795913e612a261274ee3a711ff061971c6677629da3258dcc", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 74, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "9155967097d5fc3abc2c4c56c7189cd57985ce1a2f398be323fe73cddbd97d3d", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "9dd16ebb4b62c3f74fa8a5968ea527126b25d7c13ffc63bd11648ad662b47ca2", + "configuredEnvironmentRustSourceSha256": "f58af4bbb1b36b91b3b32a62e02eb85280e17472805861a8bdab650041799a68", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "3163e952ab0e33a75139a7c72a96d1d2d8ac18c03540d63cf0b3fb4265c19f0b", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "295ecfbf4b219a10ff6638b1dce0c306eeb63fcebe91f14e403f0cbd76d8e3e2", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "2035b9866db328f0394e6d65f49d64e7fee0737ecf4d16a00634027a0c2b78f7", + "profileCompatibilitySourceSha256": "05a449c32b17b044eee4c49694e90f09bb4b224c442dc53fbcc0ac4f51f9d08b", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "7586d44b47c83395498dc8806287cd3538ef58177ba7c5949f5766ed105a0161", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v74-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v74-identity.json new file mode 100644 index 00000000000..c48091572be --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v74-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:c3e059a6c68afa2216f0315d85be084126c91d9bdbe21c2e65790fb2fc577fcd", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 74, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "f22d9caf2035b600abc1a6625ae23ca97f1409d7e29ed5b7264bb8f9784c7dc9", + "semanticSchemaBundleSourceSha256": "4cae579aac836762fdbf92c5447425d8b756e87a5766bc0c7a1885a90541c8d6", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "bd03a2fa110051e5a9ac6de5092f2fb67b5f7eed2b5e5b2448dc699821ae5dd3", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v75-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v75-identity.json new file mode 100644 index 00000000000..57e2f9bd757 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v75-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:b7448f79ddca7d4177f0b2094dd3ec211057ee991ae31f3a1f4681bad69ec6e6", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 75, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "74887ee00c428a8a7f5060d3402cdb16caca3583b9decf58d5a7a147a95b6c68", + "semanticSchemaBundleSourceSha256": "af254e5115d9dbedfc6be1b6b52b41516ec3900001aa16b592712e463364a934", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "054ce778765690c35a4bbb4e73d923d7dd181226865b7a2e76e7952b4a0f44a3", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "43013f5942b1436ddbc171ecb8af1b5d332400d03ed0cc773b18f86f3efe4c90", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "fbc9fc037dab8134d090ac7c3eb23f80026cd84085d56a9704fcf9ceb0478926", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v76-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v76-identity.json new file mode 100644 index 00000000000..29f99780801 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v76-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:e596375ec1bccfb15d89d69a8358ed4c2ef95e7c8c0982440bc98d5995eab70e", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 76, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "74887ee00c428a8a7f5060d3402cdb16caca3583b9decf58d5a7a147a95b6c68", + "semanticSchemaBundleSourceSha256": "af254e5115d9dbedfc6be1b6b52b41516ec3900001aa16b592712e463364a934", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "5337f35800935b17c3b49e92e454b1f799646a42bc96baeee6cc135193d9e272", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v77-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v77-identity.json new file mode 100644 index 00000000000..c4f25c91afd --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v77-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:6739ae80201a9bfd3739ad03707c22302251d9fe14092c1fc412b9bde2b49712", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 77, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "74887ee00c428a8a7f5060d3402cdb16caca3583b9decf58d5a7a147a95b6c68", + "semanticSchemaBundleSourceSha256": "af254e5115d9dbedfc6be1b6b52b41516ec3900001aa16b592712e463364a934", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "054ce778765690c35a4bbb4e73d923d7dd181226865b7a2e76e7952b4a0f44a3", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "6e942ecc5998853ceaa1879933568167b3c9d3fbaabf07559017a7cfd028e457", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "fbc9fc037dab8134d090ac7c3eb23f80026cd84085d56a9704fcf9ceb0478926", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v78-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v78-identity.json new file mode 100644 index 00000000000..a61883b709c --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v78-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:f7e7cff356db4b1b37458bd62fd76e9d81aa1cc46795e54b168755fb68bcee8c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 78, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "afc4134817386e1c1dd5fe4725aca46b5bc7d6b7a115932daf70db18f36838a0", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v79-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v79-identity.json new file mode 100644 index 00000000000..27835e067e9 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v79-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:a0e9f339935f6ee616fee644c45cb09353e9aed1d1f22215739f9504153ceca1", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 79, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "93a631b8439df1590b0cf442cf84a9b05f004f12bfee90291651ccfc0861effe", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "aa36385c5ed723b7f2bd5c96ff70db4587a040151f1ee70f5669b7f46f408713", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v79-sleep-maintenance-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v79-sleep-maintenance-historical-identity.json new file mode 100644 index 00000000000..8c23ab768f7 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v79-sleep-maintenance-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:9934065aaee959a19f05e102d9cf6fc41288c15be18f2769f62af6d7cc8a25b7", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 79, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2d167741defe23d6b2b0647a54405331ae4457d298936f0796733628ad79d7bc", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "9000cf5a7f4191cf28699d4deb23e17cd02507a3b2f12c12a7051a0fea782496", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v8-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v8-identity.json new file mode 100644 index 00000000000..b1bc2462085 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v8-identity.json @@ -0,0 +1,22 @@ +{ + "commandDigest": "sha256:3b97dac7020396a84997040ee2864a47af615d69aaf1c951de391e850038157a", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 8, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v80-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v80-identity.json new file mode 100644 index 00000000000..60861aa2a95 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v80-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:7b8a6a31925256d225ea3d72fdcfd81b70a45c4b67d3eb0ee5073efff9ac8f8b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 80, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "5c9008d121979a3a8987e6b8a5752172eafdc4a2b5d725a73f3bbb8fb83be8ff", + "configuredEnvironmentRustSourceSha256": "85c87fae62b8a9377e4f0a4c00302c7519fae4397b1c48253f8f2b7ba7faf994", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2d167741defe23d6b2b0647a54405331ae4457d298936f0796733628ad79d7bc", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "c3bde2939555d6826b983928735d5a2e3d2949e4235d5910de16a1abf80ad7e9", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "3a93267146bfc3c489f43262386d6dcb05ec4e3a8b1765414cd43d80d0c64d4a", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v81-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v81-identity.json new file mode 100644 index 00000000000..964803b212e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v81-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:a51bdf77bba778c4d0265bbfd92a0e6c146f9de5debc3b4a2a268c34e5576e0c", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 81, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "054ce778765690c35a4bbb4e73d923d7dd181226865b7a2e76e7952b4a0f44a3", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2d167741defe23d6b2b0647a54405331ae4457d298936f0796733628ad79d7bc", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "d60b8ea63bad975c0144f0702b2749d7db9a7da50680a6147f20d4d11f2d5297", + "profileCompatibilitySourceSha256": "a9fca95a16c45b92fbe7d7f19d9a5b97602530580901afdb46ec3999729692b0", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "fbc9fc037dab8134d090ac7c3eb23f80026cd84085d56a9704fcf9ceb0478926", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v82-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v82-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..fc4e721bfd9 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v82-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:6a3b94bc014c0d36d301dfcf139dc5bf0c0e3813bcfca8b634c40482f2e31563", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 82, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "3163e952ab0e33a75139a7c72a96d1d2d8ac18c03540d63cf0b3fb4265c19f0b", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "51d48d395b672c785f184f4231640e5d0ac65093ff707ededb187b147c60f28a", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "2035b9866db328f0394e6d65f49d64e7fee0737ecf4d16a00634027a0c2b78f7", + "profileCompatibilitySourceSha256": "b6da08c482dddaa8b291c90bd013e531d6fdade248b19f9a503287b9f5f40dcf", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "fbc9fc037dab8134d090ac7c3eb23f80026cd84085d56a9704fcf9ceb0478926", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v82-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v82-identity.json new file mode 100644 index 00000000000..99ff69ea406 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v82-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:99d3a7f3853bc3f518c1579cbe165f38fd4764c020a688814d3adfd7e3d7b1a8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 82, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "8442088daf04fc7f09bca2fbb32bf5e9b550be6a4606f8c2ff3a23a268fa0564", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "d3bd56d7c2d924c0ed623e4b92aea9b858020a3e4a6245e20c91476079e1bbf8", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v83-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v83-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..adeeb04b00a --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v83-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:78b90dd019886c37c22418988697a9afd2c1b84fcfb55492533ab51fb01b722a", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 83, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "semanticDirectDriverSourceSha256": "d683429427dd8a1a5efe50952018ea486f808bdbf0a92fc5946ee267fe2c72ee", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "3e61c4cdd4b78e38fcb16eaadae4f1fd65ce3c7127184ea7a80948c8e5d77f88", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "087a8292fcab900d5a2682cf680411a0b549882c9a8ae53e00b7fc26fd88c192", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "03fca93d36a89b0cc0917335e293ad097fdf04356d21b307827bb0ea4c13f523", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "51d48d395b672c785f184f4231640e5d0ac65093ff707ededb187b147c60f28a", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "56a177d3e702914818dca4ca50e061f0d25f988bfc4c0582c36ce23c1696d82f", + "nativeExecutionSourceSha256": "f550154acb0cd343de61424618d67b2889caec50e98415120ca933c4ff91a2e4", + "profileCompatibilitySourceSha256": "f8eb4a7fe02ce86d7084a38b67cb9b631d5ec642922d89556555a558c53d3cac", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "1785e3f31e5dad5a13b53e25d8cf9482a9bd89a27b6c127830aed6b81acc605c", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "fbc9fc037dab8134d090ac7c3eb23f80026cd84085d56a9704fcf9ceb0478926", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "runtimeSandboxSourceSha256": "04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v83-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v83-identity.json new file mode 100644 index 00000000000..8a3faad53b1 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v83-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:56361a790c38c59633ad4a5adad2d3b4a9098974f15264e4b506d69807902bea", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 83, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "f9b5a400a449f36de123bb511b21c4cb4564b50081f9958b92e6b7f0c6891d47", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "d3bd56d7c2d924c0ed623e4b92aea9b858020a3e4a6245e20c91476079e1bbf8", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v84-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v84-identity.json new file mode 100644 index 00000000000..5a612af2798 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v84-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:a95f1d8e4d0a18d0c2cbc3bffdf998a2c5b8a582bdf51a72085b01d948d0a04e", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 84, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "f9b5a400a449f36de123bb511b21c4cb4564b50081f9958b92e6b7f0c6891d47", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "eecf2c4e42b451df811e08c1ea25d37619eaf67ad255c5dd742e9232aada35ac", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v85-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v85-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..4e2e3680190 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v85-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:110c50d8edf6942919dfcaa74c4f0ddd63601d29a119272dd84dd9e81a03503b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 85, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "7df87afdded6b4605fc3ed8c8d88937c035cc87b9be5762da084cb355161c81f", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "087a8292fcab900d5a2682cf680411a0b549882c9a8ae53e00b7fc26fd88c192", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2af04f3cf85245b5e0421f25172a34ccf1e3eb2b4dc097f41f8faa19528c09e6", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "f23df7ed573c58c495a480827efa6cc5004aa9d4b106ba7f929a928f35607d72", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v85-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v85-identity.json new file mode 100644 index 00000000000..5d0c78a3b24 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v85-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:267e04ce9335f7641f665d9b952bc4637056ee1cfeac23715b7aefbc3a8df3c9", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 85, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "1fe6fa9e6b96d84d70432b85a57c473f833606d4a521563d5022b4d3c41576ce", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "68dad92a921ff15feba4cb3fab3b13df4c72aae9260a4d7eb121e8945c603b79", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "f23df7ed573c58c495a480827efa6cc5004aa9d4b106ba7f929a928f35607d72", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v86-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v86-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..d43e0063c5e --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v86-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:0923c8b23c7b6d022bb3043d6b6734d45df85e61ac119442f6a2885468766bf8", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 86, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "c1e8cd004ded03c5f0dafc9f9fe6ff04672f7a23dc9fa22524fcfaa60699df7e", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "087a8292fcab900d5a2682cf680411a0b549882c9a8ae53e00b7fc26fd88c192", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2af04f3cf85245b5e0421f25172a34ccf1e3eb2b4dc097f41f8faa19528c09e6", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "79740568b1cf863c87b31d5236b96858f0f5c3b42883f639cefc82c80d2ea2a7", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v86-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v86-identity.json new file mode 100644 index 00000000000..e2d0da77d18 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v86-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:8d0eb9ed39fe7faabc7c2943738177e96a9a8c80a116ef76d9c1995faa8bf328", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 86, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "cbcefbceb0b2a24b0909cbb8361df6b8853b4f50b21d66328bc483951a8246ea", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "8bf5c2ed6d6223144f7eb777e97973655301f5be10d9734f025cfc2b0bdff431", + "runtimeRequestFacadeSourceSha256": "553914b022d4735228c69619c9d209cd4684c4b57649be32d11054859903ba91", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "79740568b1cf863c87b31d5236b96858f0f5c3b42883f639cefc82c80d2ea2a7", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..d58def0b4f6 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v87-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:29af65cc05ce23bcbde7e69f96e857cb5f68a58e4fca18b91b93ed9b31cc5a6d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 87, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "c1e8cd004ded03c5f0dafc9f9fe6ff04672f7a23dc9fa22524fcfaa60699df7e", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "72018ba4ceffe6c6dcab6f09701177b5b3a296c81c3f42b69ed2b21306ad2976", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "2af04f3cf85245b5e0421f25172a34ccf1e3eb2b4dc097f41f8faa19528c09e6", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "a924a9accec7708823acdd6b7ad0725b5cd9a6ce8d924671d1075907bf0fc8a9", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v87-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v87-identity.json new file mode 100644 index 00000000000..d6d6e4ac299 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v87-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 87, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "cbcefbceb0b2a24b0909cbb8361df6b8853b4f50b21d66328bc483951a8246ea", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "bb9bb3daac53ce5955ddf8f56839c7a57ae60c74ea3cdd08895ab6912fcf7851", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "8bf5c2ed6d6223144f7eb777e97973655301f5be10d9734f025cfc2b0bdff431", + "runtimeRequestFacadeSourceSha256": "23361d25e660ef7919bfb54f21727b899e7d6f8865307604ee15eca7488afeaa", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "a924a9accec7708823acdd6b7ad0725b5cd9a6ce8d924671d1075907bf0fc8a9", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..1a96d18633f --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v88-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:f3bf015153e6ea86780d5ce1c02f0c0fde66309769c74964fafa90cccd5f60d2", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 88, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "c1e8cd004ded03c5f0dafc9f9fe6ff04672f7a23dc9fa22524fcfaa60699df7e", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "72018ba4ceffe6c6dcab6f09701177b5b3a296c81c3f42b69ed2b21306ad2976", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "acd489b70ed67f4c3bc498982e3c2402e82b2d0bac0c2b7da5054035be8409f6", + "runtimeRequestFacadeSourceSha256": "d0ed28e0c5ddad34db8f437e704c8a755eb0b47f27e08e44185f66d1d2205295", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "331d9c8b7ad164d96a6533c422141181461315b547635b5e43f399cadc4994cc", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v88-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v88-identity.json new file mode 100644 index 00000000000..1f0e4fcecd3 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v88-identity.json @@ -0,0 +1,89 @@ +{ + "commandDigest": "sha256:b9c13b83628be07086a88394ae671997291b77bbdbf45b0bd1c4e91b7121bc9d", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 88, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "b60e4b924e827e122860d2a4cc13b465ba748ee521620887c88f3c58c0df6081", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "a5b81494bdae7c100b71c3a8024f04287c458c2e549eb094e3501168b54fa536", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a", + "configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "cbcefbceb0b2a24b0909cbb8361df6b8853b4f50b21d66328bc483951a8246ea", + "nativeRuntimeContextSourceSha256": "152d7187ce1dc91a15377d368776555c9897d6e018b65f0f59a92dcdbd6497d9", + "nativeRuntimeContextFieldsSourceSha256": "069f4bc3c4dc95888f30d3fea331adb0ee0a164d09f4f70ec9c132f24f69c7dd", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249", + "harnessSessionSourceSha256": "bb9bb3daac53ce5955ddf8f56839c7a57ae60c74ea3cdd08895ab6912fcf7851", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "8bf5c2ed6d6223144f7eb777e97973655301f5be10d9734f025cfc2b0bdff431", + "runtimeRequestFacadeSourceSha256": "23361d25e660ef7919bfb54f21727b899e7d6f8865307604ee15eca7488afeaa", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be", + "profileCompatibilitySourceSha256": "331d9c8b7ad164d96a6533c422141181461315b547635b5e43f399cadc4994cc", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..1daf22a9a84 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,88 @@ +{ + "commandDigest": "sha256:4502feb20b925f88c3317f637962d38f8b8df7f1425a485c0f8e3526213fe52b", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 89, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "c1e8cd004ded03c5f0dafc9f9fe6ff04672f7a23dc9fa22524fcfaa60699df7e", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "72018ba4ceffe6c6dcab6f09701177b5b3a296c81c3f42b69ed2b21306ad2976", + "nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "bb9bb3daac53ce5955ddf8f56839c7a57ae60c74ea3cdd08895ab6912fcf7851", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "1a6d9a05b96a4d2aad3eeb92980719e0604f06e34235211a3ed1396f95580cf8", + "runtimeRequestFacadeSourceSha256": "23361d25e660ef7919bfb54f21727b899e7d6f8865307604ee15eca7488afeaa", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "3619ee2ed5b45595ecd337cf903e0378f4b7867979f2f57db139ad1a238183fd", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v9-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v9-identity.json new file mode 100644 index 00000000000..88aea29da29 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v9-identity.json @@ -0,0 +1,28 @@ +{ + "commandDigest": "sha256:98936d763497bd6f0e5605f52831a344f456357de58c457e440e69a1a468a2f4", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 9, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "bd5393058a218040d217fa85449d59a6f30507de54cd645bf0ef21422823f85e", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "fe1bb611bea289d81b1c7c973fbb01b93de133a7caa8fe78b7ff4ee1f485b224", + "permissionAdapterSourceSha256": "2bc34ac7899ac2729909459321e5a8a3668342cc61921e8c95e672719c6d91f2", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "687270d7bbe3dccce6c2fed8664e76cda724b43e545cb153b9f54b018de52927", + "permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4" + } +} diff --git a/packages/paperclip-runner/test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..3638f17a9c2 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,89 @@ +{ + "commandDigest": "sha256:33ea3458bc7c190aa314f495c02c868df9bcaddba40a3b53d11a792b7a243a80", + "declaration": { + "schema": "paperclip.acpx_profile_declaration.v1", + "agent": "copilot", + "agentProfileVersion": 90, + "acpxVersion": "0.13.1", + "agentServerVersion": "1.0.88", + "protocolPolicyRevision": "copilot-agent-manual-v1", + "acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3", + "distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107", + "agentFilesBinding": "registered-runtime-context-v1", + "systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1", + "sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1", + "innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a", + "upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0", + "patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679", + "messageIdentityContract": "copilot-native-message-id-v1", + "ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1", + "permissionContextContract": "copilot-edit-permission-context-v1", + "permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b", + "permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668", + "permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9", + "permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f", + "permissionClassifierSourceSha256": "b60e4b924e827e122860d2a4cc13b465ba748ee521620887c88f3c58c0df6081", + "semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2", + "semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791", + "semanticBridgeSourceSha256": "c1e8cd004ded03c5f0dafc9f9fe6ff04672f7a23dc9fa22524fcfaa60699df7e", + "toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706", + "semanticNormalizedInputContract": "validated-forwarded-input-commit-v1", + "semanticSidecarSourceSha256": "a5b81494bdae7c100b71c3a8024f04287c458c2e549eb094e3501168b54fa536", + "semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d", + "semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975", + "semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e", + "semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59", + "semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb", + "semanticSchemaBundleSourceSha256": "1670646ef3bd158e1f108492d4e56dd5e3a5b5c7760a689a02589b66a9628112", + "semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1", + "displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877", + "displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e", + "configuredEnvironmentSourceSha256": "56105be2aec6df871aca8f71cbe8386362d8be57ac79474421c29772e7de0efc", + "configuredEnvironmentRustSourceSha256": "1ce841c0994ad8344a3b4899346771ac38dee2787f6a4af6b4b92d7b50dcc7b4", + "profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282", + "profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571", + "profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6", + "attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2", + "singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f", + "nativeSessionRuntimeSourceSha256": "72018ba4ceffe6c6dcab6f09701177b5b3a296c81c3f42b69ed2b21306ad2976", + "nativeRuntimeContextSourceSha256": "152d7187ce1dc91a15377d368776555c9897d6e018b65f0f59a92dcdbd6497d9", + "nativeRuntimeContextFieldsSourceSha256": "069f4bc3c4dc95888f30d3fea331adb0ee0a164d09f4f70ec9c132f24f69c7dd", + "nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1", + "nativeSessionContractSourceSha256": "d5ca3dc47300a5d2d52496c007a2f31f6fa95b82b77a46a28b8dca03ab77ae7a", + "harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5", + "harnessBackendSourceSha256": "0b8e95ce0b98faa4532779b3f0e2ae1e3f06b87666d4642a06b1bdfc652df96f", + "harnessSessionSourceSha256": "bb9bb3daac53ce5955ddf8f56839c7a57ae60c74ea3cdd08895ab6912fcf7851", + "transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e", + "nativeBackendSourceSha256": "b0af399e9c7d0af5c103cd57ccacb4a4f528c90266eee7245f14db2222c0f74a", + "nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44", + "nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b", + "providerLaunchSourceSha256": "ec0af2fec19366192eca3418dbc6b8b20926be2d3a8f70a28823a02ba84dadf8", + "launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296", + "runtimeRequestBridgeSourceSha256": "1a6d9a05b96a4d2aad3eeb92980719e0604f06e34235211a3ed1396f95580cf8", + "runtimeRequestFacadeSourceSha256": "23361d25e660ef7919bfb54f21727b899e7d6f8865307604ee15eca7488afeaa", + "runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211", + "guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6", + "nativeExecutionSourceSha256": "22fdc26b5bb4f097a8b18d2dc93d42c74f588fa15ef9db009ffc98ee7e3b3573", + "profileCompatibilitySourceSha256": "19a53491c6842a2d5f5f093075cb876e68460013236c64a3b1571b5eda557e1b", + "installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d", + "assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5", + "assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f", + "credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe", + "admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456", + "metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727", + "permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1", + "semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811", + "preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca", + "agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba", + "nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b" + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v10-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v10-identity.json new file mode 100644 index 00000000000..db77da0e46c --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v10-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:2dccee3800dada11b65692e5cf591e3667a123cba2fbf5629a937f731043b423", + "sourceDigest": "sha256:1fec0323461ed2e0b1d0172d205237ba23316a7e6a89c325b6eb3be907e373e3", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 10, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:0ef591ee98a5bb72eb2deae8b5f620fe87deab9b721cd776f18d101f308fb462", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:f711428ec3bb9bcf723a5fd1382a3d266ed14e7ed5340b8a32eafe7357940144" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v11-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v11-identity.json new file mode 100644 index 00000000000..78206d5b3f1 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v11-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:f43a6f5a583972cdcb422784969cd6a97654655b0f135f1cf178317909c404f8", + "sourceDigest": "sha256:c5a4628adcdd9190c45558f42014b0055698b8f8c7eb301417238f38d913f503", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 11, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:326deadb929e7c134da407bd3fa4d0853732e37d407c92d404979e7625c6c7cf", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:f711428ec3bb9bcf723a5fd1382a3d266ed14e7ed5340b8a32eafe7357940144" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v12-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v12-identity.json new file mode 100644 index 00000000000..0292406d0b6 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v12-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:3dc83b2c3493913748cacb09025a8c97b74f3b5bbb1dc204072d1a773fa9af3a", + "sourceDigest": "sha256:79188d089f3f6b575726af77fe055a58449144a373a0745dcad4be414cba8cd0", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 12, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:cdba0cbca6ea0e28928cae4817055dc38c527308570c6a03f0736fef0210fe9e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:f711428ec3bb9bcf723a5fd1382a3d266ed14e7ed5340b8a32eafe7357940144" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v13-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v13-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..7c698718c18 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v13-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:6d0d1b4a4af7209df3102c48289d320eae518f0a02fc8b4ccd52a19a6c1c91b8", + "sourceDigest": "sha256:a4100e2690bbf5f0f64dd62aea4004040dfbe75add52455d5e354e436678629c", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 13, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:5d11b9d205e9ee7096f30564dc8d9a66f2eaa9bd03cf1858f06304f42c314d3c", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:f711428ec3bb9bcf723a5fd1382a3d266ed14e7ed5340b8a32eafe7357940144" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v13-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v13-identity.json new file mode 100644 index 00000000000..62e144b5bdb --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v13-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:e311f8111dd12f0c49bf12a80345cfe5f31a1222e0189209adeabf2f9bd0e1b0", + "sourceDigest": "sha256:9d778ec8c5987e304d3121787806f546c7c9f545cf5e0628ce0035c59a559907", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 13, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:a1002d0d7fa8ce6b8287ad0397f7b9d93fe123aecc3dcbe5981b4efb41685736", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:09be94877a11ff526f4351b36471ed9685828a3ee4f8e6d329031e88c713afcb", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v14-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v14-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..b07232b39b7 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v14-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:baf1038946fff30e29f2964072ee6c64631404ed875514170aafd13d3464fae5", + "sourceDigest": "sha256:0b37da6cc68f3b1655414ad8bb3e00ebe3097d2ea6d001fe632203e73c945b7d", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 14, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:abe3e6c718e8e0fed154526affc94e34b46d96f7bdaed5d88e2b00a21a5b84db", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:bc72cad8f86ea15a85c59a5a3bdbb6c951a9a57e7292a5e37fec906ec5b47014", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:09be94877a11ff526f4351b36471ed9685828a3ee4f8e6d329031e88c713afcb", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v14-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v14-identity.json new file mode 100644 index 00000000000..428385e99ee --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v14-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:ca59edc7f416cc1e86ac7d7d1e288d3d91065b7ab59e79bcb62bae5f0cc5cf49", + "sourceDigest": "sha256:b70868731d297017152e4675aebe0c5435b70468695f8c5cdf225faba8ced795", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 14, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:eed57e3ba2ab2f12c2e6abba7b683e64adfc0e281e9e8a63c854b8eabdfb5183", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:fc8d7cce62e0c02efddece8696e8d24f6a9fe19e5288a5e67a01ffbf931a3f6e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v15-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v15-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..9be832273bb --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v15-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:e6b403b765b25c9b1591472a31d046da76d4f2e711b6020e7c862e9e6474ab96", + "sourceDigest": "sha256:8c1a78a75770089e7a92285ce9ffbda227c3f01d0626a452de7fe663e0f5f306", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 15, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:bc8187d29d7cd91bdb9eb4b46d80f02a3ddc76519723ce4d64c6948527f105ee", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:fc8d7cce62e0c02efddece8696e8d24f6a9fe19e5288a5e67a01ffbf931a3f6e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v15-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v15-identity.json new file mode 100644 index 00000000000..c0d67912bcf --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v15-identity.json @@ -0,0 +1,36 @@ +{ + "commandDigest": "sha256:658e6d41ce6fc7080aa6655d7a97121b3cae6214f2d4c074284d958b95bbe769", + "sourceDigest": "sha256:7dfa4769aab33e8625b009b4f3efe59e0c6180dba43ebb486179638b9fbaa216", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 15, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:a5b81494bdae7c100b71c3a8024f04287c458c2e549eb094e3501168b54fa536", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/generated-sidecar-contract.ts": "sha256:b60e4b924e827e122860d2a4cc13b465ba748ee521620887c88f3c58c0df6081", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:eed57e3ba2ab2f12c2e6abba7b683e64adfc0e281e9e8a63c854b8eabdfb5183", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:fc8d7cce62e0c02efddece8696e8d24f6a9fe19e5288a5e67a01ffbf931a3f6e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v16-cursor-cloud-qualification-historical-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v16-cursor-cloud-qualification-historical-identity.json new file mode 100644 index 00000000000..b6f9febffe4 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v16-cursor-cloud-qualification-historical-identity.json @@ -0,0 +1,36 @@ +{ + "commandDigest": "sha256:b7b300d0dc72006ae0017aaf8957c780180c6db9c2bfef54cba4bed6461a0c50", + "sourceDigest": "sha256:bd1b694b1f753b188915e0eff039243c00e5c9d43ca8b93625ad1a336b58d4e1", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 16, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:a5b81494bdae7c100b71c3a8024f04287c458c2e549eb094e3501168b54fa536", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab", + "packages/paperclip-runner/src/drivers/acpx/generated-sidecar-contract.ts": "sha256:b60e4b924e827e122860d2a4cc13b465ba748ee521620887c88f3c58c0df6081", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:bc8187d29d7cd91bdb9eb4b46d80f02a3ddc76519723ce4d64c6948527f105ee", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:fc8d7cce62e0c02efddece8696e8d24f6a9fe19e5288a5e67a01ffbf931a3f6e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:839cb1d2ac19462f2bcef94d014e528e56beb7a1a1cbf6c3b10906d0ab7eb10c" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v6-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v6-identity.json new file mode 100644 index 00000000000..75ce63342eb --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v6-identity.json @@ -0,0 +1,33 @@ +{ + "commandDigest": "sha256:93004d5a7647235e53ab741ba5639e8f20186ebaaccef8b9a7834593a1f5febe", + "sourceDigest": "sha256:f1d43562ca126e027147b73d1abf04849130dc4dfddb71b7a233a6c21c32539a", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 6, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:43d09d1a7cb081e26dd3cad228577cf72f8b0d28c4076cdea722bb9c01044778" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v7-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v7-identity.json new file mode 100644 index 00000000000..9b3af98bae5 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v7-identity.json @@ -0,0 +1,34 @@ +{ + "commandDigest": "sha256:6fcf754bf85aaca0b35ba6bad9926f11c60bdda5f7b180158c8f8b1be5e57d36", + "sourceDigest": "sha256:d7cf13acdb5cb424e8023729fa46d07764de06893db23694fc9780334b0aed9e", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 7, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:fbfd9c2d51915dbb5590b2caf291092ae83024479c322422ef2b56e23a02a217", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:43d09d1a7cb081e26dd3cad228577cf72f8b0d28c4076cdea722bb9c01044778" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v8-cursor-cloud-candidate-historical-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v8-cursor-cloud-candidate-historical-identity.json new file mode 100644 index 00000000000..7b755d9a638 --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v8-cursor-cloud-candidate-historical-identity.json @@ -0,0 +1,34 @@ +{ + "commandDigest": "sha256:ab17a3e5cb0f9859487d9494d91b7a2f95c2bb2b0c652e5b2b5bd04294f14bf6", + "sourceDigest": "sha256:b13fecb395e1f269fc0f5efefa1ddf821f7ef2041a12e89389e5b5e407915fef", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 8, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:80a47b34c6266fcdeed4420dee28ad733d9a85a6d2f86f97c1fbfa2c1c539213", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:43d09d1a7cb081e26dd3cad228577cf72f8b0d28c4076cdea722bb9c01044778" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v8-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v8-identity.json new file mode 100644 index 00000000000..6c515df7eab --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v8-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:647d4628f3c9502814895f927a0c9bf0b856fbbca155c9bdd4247e10da97c01b", + "sourceDigest": "sha256:e0a4d6fed41df459cdb2e5d06f8574e62898c67b73721e619384a3d136f91129", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 8, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:c4edb57b63c01c7c8a07dcd25d625cb2528fddd7e0126fe12bd934edf1339a5c", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:fbfd9c2d51915dbb5590b2caf291092ae83024479c322422ef2b56e23a02a217", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:3ea66957494a8746aeec099c076251e6e5004bce9f9ec837bceb346195e602f7" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/grok-profile-v9-identity.json b/packages/paperclip-runner/test/fixtures/grok-profile-v9-identity.json new file mode 100644 index 00000000000..940873b506a --- /dev/null +++ b/packages/paperclip-runner/test/fixtures/grok-profile-v9-identity.json @@ -0,0 +1,35 @@ +{ + "commandDigest": "sha256:7b777fa603809ff2efa9c69bd2105a980dbf9c71967f76460dca047ecd9612f3", + "sourceDigest": "sha256:789149ddd2fed127d8fb1e91998d6a5c94d989ef4642b24b9d932c59179313b8", + "declaration": { + "schema": "paperclip.grok-profile-identity.v1", + "agent": "grok", + "agentProfileVersion": 9, + "agentServerPackage": "builtin:grok-acp", + "agentServerVersion": "1", + "agentRuntimePackage": "native:grok", + "agentRuntimeVersion": "1.0.13", + "requiresProviderPolicy": false, + "acpxVersion": "0.13.1", + "sources": { + "patches/acpx@0.13.1.patch": "sha256:00d6af17216cb0cad902b48633eb19bf0ec6b05837a984cb24661fca593f09c1", + "packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts": "sha256:7d6e948b7cff4df52a9afc916db46ace0f42b4b2d3134ba0c21ee0a928857e62", + "packages/paperclip-runner/src/cli/acpx-sidecar-input.ts": "sha256:17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c", + "packages/paperclip-runner/src/drivers/acpx/admission-diagnostics.ts": "sha256:df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af", + "packages/paperclip-runner/src/drivers/acpx/grok-effort.ts": "sha256:f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777", + "packages/paperclip-runner/src/drivers/acpx/grok-web-search.ts": "sha256:754b5ca2345c045421f6007f34999508d996e1cea035f0f1952b3d5f00072b9c", + "packages/paperclip-runner/src/drivers/acpx/grok-credentials.ts": "sha256:1c4ff0be6da798b6fcc604d20a9198dcc8523a3806d563b5b5345b7260549f73", + "packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts": "sha256:7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2", + "packages/paperclip-runner/src/drivers/acpx/runtime-host.ts": "sha256:13f9ac382a279a67adb8974c36bbed38fe43d9b93b87bd7a05e879ead7f03d63", + "packages/paperclip-runner/src/drivers/preconfigured-home.ts": "sha256:c4edb57b63c01c7c8a07dcd25d625cb2528fddd7e0126fe12bd934edf1339a5c", + "packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts": "sha256:04a49a24e3828ce8fca908de15e31ae932b8b1b4f7ecec0308627f6a8da9ba20", + "packages/paperclip-runner/src/drivers/acpx/sidecar-protocol.ts": "sha256:26dd0cfbef8b2b401de6b7862a4af7f243fb703e23678a1a5ed8fa68d4784d42", + "packages/paperclip-runner/src/drivers/acpx/native-distribution-integrity.ts": "sha256:aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b", + "packages/paperclip-runner/src/providers/grok/launcher.cjs": "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55", + "packages/paperclip-runner/src/providers/grok/platforms.json": "sha256:931eed3abbf2bf041e6c72e6e9486d976f4352613cf069b216ddf010c9a8e704", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_backend.rs": "sha256:86149617372ea3ebc8752862f873e550c3a732278f32ba1d937f84f73525de4d", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_provider_session.rs": "sha256:e97a7c4d2cf9be9c6e0ada78076a5551b01401518597ab81cb6fbd5a1faf4a5e", + "packages/paperclip-runner/runner/crates/runner-core/src/acpx_sidecar_transport.rs": "sha256:3ea66957494a8746aeec099c076251e6e5004bce9f9ec837bceb346195e602f7" + } + } +} diff --git a/packages/paperclip-runner/test/fixtures/profile-history-lineage.json b/packages/paperclip-runner/test/fixtures/profile-history-lineage.json index 837651fb9d0..fcd49a393c6 100644 --- a/packages/paperclip-runner/test/fixtures/profile-history-lineage.json +++ b/packages/paperclip-runner/test/fixtures/profile-history-lineage.json @@ -152,6 +152,66 @@ "version": 17, "commandDigest": "sha256:e3da3859ef3fe4904d2b917c2cbdde6181f4dbeb6480eba43d37614fb29ddd70", "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/copilot-profile-v89-identity.json", + "originRevision": "59da15066acd2077b1161b06217acfbd11f8da04", + "originPath": "packages/paperclip-runner/test/fixtures/copilot-profile-v89-identity.json", + "sha256": "655db7f684b2f001f4fca974fe3bcae2dd3e08c36b60d2d82169c6fc72580cee", + "agent": "copilot", + "version": 89, + "commandDigest": "sha256:995381b2cec7a0faf3f5cefbe2421eae7936a2bfa50bb153645f57341f968db3", + "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/copilot-profile-v89-cursor-cloud-qualification-historical-identity.json", + "originRevision": "42e9d3d710a2ef5b387f9bb29bf615973b4adba9", + "originPath": "packages/paperclip-runner/test/fixtures/copilot-profile-v89-identity.json", + "sha256": "9990fd9cdd23df111a180984160a11db7a2f972a60787e8ddea9793678cc268e", + "agent": "copilot", + "version": 89, + "commandDigest": "sha256:4502feb20b925f88c3317f637962d38f8b8df7f1425a485c0f8e3526213fe52b", + "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/copilot-profile-v90-identity.json", + "originRevision": "59da15066acd2077b1161b06217acfbd11f8da04", + "originPath": "packages/paperclip-runner/test/fixtures/copilot-profile-v90-identity.json", + "sha256": "b51e3191380900b74ead659f1b8416e5c9ac8cd111eacdc3d89941c8ea80c5f0", + "agent": "copilot", + "version": 90, + "commandDigest": "sha256:8922d3d41dae0a7b7f7e2de69d50b272b58283232fefb22ffdb6c9b34fa26a6b", + "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/copilot-profile-v90-cursor-cloud-qualification-historical-identity.json", + "originRevision": "42e9d3d710a2ef5b387f9bb29bf615973b4adba9", + "originPath": "packages/paperclip-runner/test/fixtures/copilot-profile-v90-identity.json", + "sha256": "44eba85a0102b72cbdbdf685188e473ba9651a6e45a959499135a0d92ed70d32", + "agent": "copilot", + "version": 90, + "commandDigest": "sha256:33ea3458bc7c190aa314f495c02c868df9bcaddba40a3b53d11a792b7a243a80", + "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/grok-profile-v16-identity.json", + "originRevision": "59da15066acd2077b1161b06217acfbd11f8da04", + "originPath": "packages/paperclip-runner/test/fixtures/grok-profile-v16-identity.json", + "sha256": "407f336abf6b8b19478047e12458d4edc1c92ccc98bc4764042c8362dc40758c", + "agent": "grok", + "version": 16, + "commandDigest": "sha256:4d6b4c857ba6e63a3eb8c5c406280e4bd0164d3109c940918392c52868bb4263", + "launchAuthority": false + }, + { + "path": "packages/paperclip-runner/test/fixtures/grok-profile-v16-cursor-cloud-qualification-historical-identity.json", + "originRevision": "42e9d3d710a2ef5b387f9bb29bf615973b4adba9", + "originPath": "packages/paperclip-runner/test/fixtures/grok-profile-v16-identity.json", + "sha256": "15a56a2e69b4862b68f5a767d2b3cb5b93a884b814df55c089344a9d040a5163", + "agent": "grok", + "version": 16, + "commandDigest": "sha256:b7b300d0dc72006ae0017aaf8957c780180c6db9c2bfef54cba4bed6461a0c50", + "launchAuthority": false } ] } diff --git a/scripts/ci/cache.integration.test.mjs b/scripts/ci/cache.integration.test.mjs index 8aebc6d92e3..8e502511c7d 100644 --- a/scripts/ci/cache.integration.test.mjs +++ b/scripts/ci/cache.integration.test.mjs @@ -186,3 +186,54 @@ test("the task launcher bypasses cache reads and writes when execution is forced assert.deepEqual(cacheFiles(), retainedCache); } finally { rmSync(directory, { recursive: true, force: true }); } }); + +test("CI launcher executes forced and uncacheable lanes after a cached result", () => { + const directory = mkdtempSync(path.join(tmpdir(), "ci-launcher-")); + const write = (name, content) => writeFileSync(path.join(directory, name), content); + const json = (name, value) => write(name, JSON.stringify(value)); + try { + execFileSync("git", ["init", "-q"], { cwd: directory }); + write(".gitignore", ".turbo/\nnode_modules/\nresult.txt\ncalls.txt\n"); + mkdirSync(path.join(directory, "node_modules"), { recursive: true }); + symlinkSync(path.dirname(turbo), path.join(directory, "node_modules/.bin"), "dir"); + mkdirSync(path.join(directory, "packages/fixture"), { recursive: true }); + json("packages/fixture/package.json", { name: "fixture", private: true }); + json("package.json", { + name: "launcher-proof", private: true, + packageManager: JSON.parse(readFileSync(new URL("package.json", repositoryRoot), "utf8")).packageManager, + scripts: { "test:run:general": "node check.cjs" }, + }); + write("pnpm-workspace.yaml", "packages: ['packages/*']\n"); + write("pnpm-lock.yaml", "lockfileVersion: '9.0'\nsettings:\n autoInstallPeers: true\n excludeLinksFromLockfile: false\nimporters:\n .: {}\n packages/fixture: {}\n"); + json("turbo.json", { + globalEnv: ["CI_TASK_CACHE_SCOPE"], + globalDependencies: ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"], + tasks: { "//#ci:server": { + inputs: ["input.txt", "check.cjs"], outputs: ["result.txt"], cache: true, + } }, + }); + write("input.txt", "input"); + write("check.cjs", "const fs = require('node:fs'); if (!process.argv.includes('general-server-without-chat')) process.exit(2); fs.appendFileSync('calls.txt', 'call\\n'); fs.writeFileSync('result.txt', 'passed');"); + const run = (extra = {}) => { + const result = spawnSync(process.execPath, [new URL("run-task.mjs", import.meta.url).pathname], { + cwd: directory, encoding: "utf8", env: { + ...process.env, CI_TASK: "ci:server", CI_TASK_ARGS: "[]", + CI_FORCE_TASKS: "false", CI_TASK_DRY_RUN: "false", ...extra, + }, + }); + assert.equal(result.status, 0, result.stdout + result.stderr); + }; + const calls = () => readFileSync(path.join(directory, "calls.txt"), "utf8").trim().split("\n").length; + run(); + assert.equal(calls(), 1); + rmSync(path.join(directory, "result.txt")); + run(); + assert.equal(calls(), 1, "the normal launcher must reuse its cached result"); + assert.equal(readFileSync(path.join(directory, "result.txt"), "utf8"), "passed"); + run({ CI_FORCE_TASKS: "true" }); + assert.equal(calls(), 2, "an explicitly forced lane must execute despite a cached result"); + symlinkSync("input.txt", path.join(directory, "unclassified-link")); + run(); + assert.equal(calls(), 3, "an uncacheable source entry must execute despite a cached result"); + } finally { rmSync(directory, { recursive: true, force: true }); } +}); diff --git a/server/src/__tests__/managed-skill-content.test.ts b/server/src/__tests__/managed-skill-content.test.ts index d617f8cdb0e..0fb3ebcdc49 100644 --- a/server/src/__tests__/managed-skill-content.test.ts +++ b/server/src/__tests__/managed-skill-content.test.ts @@ -177,13 +177,14 @@ describe.skipIf(!support.supported)("managed skills use committed versions", () const local = await skillInstallationMaintenance(db).verifyVersions({ companyId, limit: 50 }); expect(local.results).toEqual([expect.objectContaining({ versionId: skill.currentVersionId, status: "local_storage" })]); const key = "cloud-runtime-config:v1"; - const run = (phase: string) => promisify(execFile)(process.execPath, [ + const run = (phase: string, storageProvider?: "s3" | "local_disk") => promisify(execFile)(process.execPath, [ "--import", fileURLToPath(import.meta.resolve("tsx")), fileURLToPath(new URL("../../scripts/migrate-skill-packages.ts", import.meta.url)), `--phase=${phase}`, `--company=${companyId}`, "--limit=50", ], { env: { ...process.env, DATABASE_URL: database.connectionString, PAPERCLIP_CLOUD_TENANT_SERVER_TOKEN: "disposable-cloud-cli-fixture", - PAPERCLIP_STORAGE_LOCAL_DIR: path.join(root, "objects"), ...env }, + PAPERCLIP_STORAGE_LOCAL_DIR: path.join(root, "objects"), ...env, + ...(storageProvider === undefined ? {} : { PAPERCLIP_STORAGE_PROVIDER: storageProvider }) }, timeout: 60_000, maxBuffer: 1024 * 1024 }); await expect(run("eligibility")).rejects.toThrow("Initialize Cloud runtime configuration"); expect(await db.select().from(instanceSettings).where(eq(instanceSettings.singletonKey, key))).toHaveLength(0); @@ -193,6 +194,10 @@ describe.skipIf(!support.supported)("managed skills use committed versions", () expect(eligibility.results).toEqual([expect.objectContaining({ versionId: skill.currentVersionId, status: "version_backed" })]); const verification = JSON.parse((await run("verification")).stdout.trim().split("\n").at(-1)!); expect(verification.results).toEqual([expect.objectContaining({ versionId: skill.currentVersionId, status: expectedStatus })]); + if (env.PAPERCLIP_STORAGE_PROVIDER === "s3") { + const legacyVerification = JSON.parse((await run("verification", "local_disk")).stdout.trim().split("\n").at(-1)!); + expect(legacyVerification.results).toEqual([expect.objectContaining({ versionId: skill.currentVersionId, status: "local_storage" })]); + } expect(await db.select().from(instanceSettings).where(eq(instanceSettings.singletonKey, key))).toEqual([persisted]); } finally { await db.delete(instanceSettings).where(eq(instanceSettings.singletonKey, key)); diff --git a/server/src/services/heartbeat/run-log.test.ts b/server/src/services/heartbeat/run-log.test.ts index 87fa5cf9439..27430bb5283 100644 --- a/server/src/services/heartbeat/run-log.test.ts +++ b/server/src/services/heartbeat/run-log.test.ts @@ -1,8 +1,10 @@ import { describe, expect, it } from "vitest"; +import { createAgentIdentityRedactor } from "../agent-identity-redaction.js"; import { appendExcerpt, boundHeartbeatRunEventPayloadForStorage, compactRunLogChunk, + redactCanonicalNativeRunLogChunk, } from "./run-log.js"; describe("heartbeat run-log excerpts", () => { @@ -173,3 +175,40 @@ describe("heartbeat run-log chunk formatting", () => { expect(compacted).not.toContain("[paperclip truncated"); }); }); + +describe("complete canonical native log privacy", () => { + it.each([false, true])("keeps structured bytes and applies complete-value secrets, images, and username masking: %s", enabled => { + const identity = createAgentIdentityRedactor("fixture-configured-private-canary"); + const envelope = { type: "paperclip.prp.event", event: { + schema: "paperclip.prp.event.v1", schemaVersion: 1, eventType: "item.delta", + payload: { header: 'Authorization: Bearer fixture-bearer-canary', api_key: "fixture-api-canary", + text: 'quoted "fixture-configured-private-canary" by fixture-operator', + image: { source: { data: "A".repeat(70000), type: "base64" }, type: "image" }, + parts: Array.from({ length: 20 }, () => "full content ".repeat(400)), + }, + } }; + const chunk = redactCanonicalNativeRunLogChunk(JSON.stringify(envelope), { + redactIdentity: identity.redact, currentUser: { enabled, userNames: ["fixture-operator"], homeDirs: [] }, + }); + const result = JSON.parse(chunk).event; + expect(result.schema).toBe(envelope.event.schema); + expect(result.payload.header).toBe("Authorization: ***REDACTED***"); + expect(result.payload.api_key).toBe("***REDACTED***"); + expect(result.payload.text).toContain('quoted "***REDACTED***" by '); + expect(result.payload.text.includes("fixture-operator")).toBe(!enabled); + expect(result.payload.parts).toEqual(envelope.event.payload.parts); + expect(result.payload.image.source.data).toBe("[omitted base64 image data: 70000 chars]"); + for (const secret of ["fixture-configured-private-canary", "fixture-bearer-canary", "fixture-api-canary"]) + expect(chunk).not.toContain(secret); + expect(chunk).not.toContain("data:image"); + expect(chunk.length).toBeGreaterThan(64 * 1024); + expect(chunk).not.toContain("[paperclip truncated"); + }); + + it("rejects malformed owned envelopes instead of treating them as coverage-preserving diagnostics", () => { + const options = { redactIdentity: (value: T) => value, currentUser: { enabled: false } }; + for (const chunk of ['{"type":"paperclip.prp.event",', '{"type":"diagnostic","event":{}}', + '{"type":"paperclip.prp.event","event":[]}']) + expect(() => redactCanonicalNativeRunLogChunk(chunk, options)).toThrow(); + }); +}); diff --git a/server/src/services/heartbeat/run-log.ts b/server/src/services/heartbeat/run-log.ts index cbdd54e074b..022c3edc7f6 100644 --- a/server/src/services/heartbeat/run-log.ts +++ b/server/src/services/heartbeat/run-log.ts @@ -1,5 +1,6 @@ import { appendWithByteCap, MAX_EXCERPT_BYTES, parseObject } from "../../adapters/utils.js"; -import { redactSensitiveText } from "../../redaction.js"; +import { redactSensitiveText, sanitizeRecord } from "../../redaction.js"; +import { redactCurrentUserText, redactCurrentUserValue, type CurrentUserRedactionOptions } from "../../log-redaction.js"; const MAX_PERSISTED_LOG_CHUNK_CHARS = 64 * 1024; const MAX_RUN_EVENT_PAYLOAD_STRING_CHARS = 16 * 1024; @@ -118,3 +119,53 @@ export function compactRunLogChunk( return `${normalized.slice(0, headChars)}${marker}${normalized.slice(normalized.length - tailChars)}`; } + +interface CanonicalNativeLogRedaction { + redactIdentity: (value: T) => T; + currentUser: CurrentUserRedactionOptions; +} + +function omitCanonicalImageData(value: unknown): unknown { + if (Array.isArray(value)) return value.map(omitCanonicalImageData); + if (!value || typeof value !== "object") return value; + const object = value as Record; + const result = Object.fromEntries(Object.entries(object).map(([key, child]) => + [key, omitCanonicalImageData(child)])); + const source = object.source as Record | undefined; + if (object.type === "image" && source?.type === "base64" && + typeof source.data === "string" && /^[A-Za-z0-9+/=]{1024,}$/.test(source.data)) { + result.source = { ...(result.source as Record), + data: `[omitted base64 image data: ${source.data.length} chars]` }; + } + return result; +} + +/** Only complete envelopes supplied by the durable native exporter use this path. + * Redact complete JSON values before encoding so quoted secrets cannot damage + * the record's structure. Image omission uses the existing field/length policy. + * The object writer separately bounds the complete encoded outer record. + */ +export function redactCanonicalNativeRunLogChunk(chunk: string, options: CanonicalNativeLogRedaction) { + const envelope = JSON.parse(chunk); + if (envelope?.type !== "paperclip.prp.event" || !envelope.event || + typeof envelope.event !== "object" || Array.isArray(envelope.event)) + throw new Error("invalid_canonical_native_run_log_envelope"); + const projected = redactCurrentUserValue( + options.redactIdentity(omitCanonicalImageData(envelope)), options.currentUser, + ); + return `${JSON.stringify(sanitizeRecord(projected as Record))}\n`; +} + +/** New complete-value forms first; old text projections are computed only when + * an archive needs them. An old malformed projection never repairs evidence. + */ +export function* canonicalNativeRunLogRedactionForms(chunk: string, options: CanonicalNativeLogRedaction) { + for (const enabled of [false, true]) + yield redactCanonicalNativeRunLogChunk(chunk, { + ...options, currentUser: { ...options.currentUser, enabled }, + }); + for (const enabled of [false, true]) + yield compactRunLogChunk(redactCurrentUserText(options.redactIdentity(chunk), { + ...options.currentUser, enabled, + }), Number.MAX_SAFE_INTEGER); +} diff --git a/server/src/services/heartbeat/run-output.test.ts b/server/src/services/heartbeat/run-output.test.ts index 91f130d040d..84b9d2170db 100644 --- a/server/src/services/heartbeat/run-output.test.ts +++ b/server/src/services/heartbeat/run-output.test.ts @@ -156,11 +156,11 @@ describe("heartbeat run output log recovery", () => { }); describe("object-backed diagnostic recording", () => { - it("applies identity redaction to a native key-bearing event before S3 admission", async () => { + it.each(["legacy", "native"])("applies identity redaction before S3 admission when output begins in %s mode", async (runtimeMode) => { const privateKeyPem = generateKeyPairSync("ed25519") .privateKey.export({ type: "pkcs8", format: "pem" }) .toString(); - const row = { ...newRunRow, runtimeMode: "native" } as Run; + const row = { ...newRunRow, runtimeMode } as Run; const db = createRunRowDb(row) as Db & { select: () => unknown }; db.select = (() => ({ from: () => ({ where: () => ({ orderBy: () => ({ limit: async () => [] }) }) }), diff --git a/server/src/services/heartbeat/run-output.ts b/server/src/services/heartbeat/run-output.ts index 24a607297bf..33e91bc078a 100644 --- a/server/src/services/heartbeat/run-output.ts +++ b/server/src/services/heartbeat/run-output.ts @@ -7,8 +7,8 @@ import type { createAgentIdentityRedactor } from "../agent-identity-redaction.js import { touchHeartbeatRunRuntimeStatus } from "../heartbeat-run-runtime-status.js"; import { publishLiveEvent } from "../live-events.js"; import { isRunLogStoreType, type RunLogHandle, type RunLogStore } from "../run-log-store.js"; -import { appendExcerpt, compactRunLogChunk } from "./run-log.js"; -import { createNativeRunLogExporter } from "../native-runtime/native-run-log-export.js"; +import { appendExcerpt, canonicalNativeRunLogRedactionForms, compactRunLogChunk, redactCanonicalNativeRunLogChunk } from "./run-log.js"; +import { createNativeRunLogExporter, nativeRunLogPrefixCursor } from "../native-runtime/native-run-log-export.js"; import { createRunSecretRedactionRegistry } from "../run-secret-redaction.js"; import { isHeartbeatRunRuntimeStatusActive, @@ -21,12 +21,13 @@ export const ACTIVE_RUN_OUTPUT_PROGRESS_FLUSH_INTERVAL_MS = 60 * 1000; export const ACTIVE_RUN_LOG_RUNTIME_STATUS_REFRESH_INTERVAL_MS = 5 * 1000; type Run = typeof heartbeatRuns.$inferSelect; +type CanonicalNativeLog = { kind: "canonical_native"; sourceCursor: number }; export interface HeartbeatRunOutputInput { run: Run; runId: string; issueId: string | null; - runLogStore: Pick; + runLogStore: Pick & Partial>; identityRedactor: Pick, "chunk" | "redact">; secretKeys: Set; appendRunEvent: ReturnType["appendRunEvent"]; @@ -145,15 +146,6 @@ export function createHeartbeatRunOutput(db: Db, input: HeartbeatRunOutputInput) .where(eq(heartbeatRuns.id, runId)); const currentUserRedactionOptions = await getCurrentUserRedactionOptions(); - if ( - handle.store === "s3_segments" && - run.runtimeMode === "native" && - input.runtimeLogSecretValues?.length - ) { - const registry = createRunSecretRedactionRegistry(db); - for (const value of new Set(input.runtimeLogSecretValues)) - await registry.register(run.companyId, runId, value); - } const reportRecordingFailure = async () => { if (recordingFailureReported) return; recordingFailureReported = true; @@ -169,11 +161,15 @@ export function createHeartbeatRunOutput(db: Db, input: HeartbeatRunOutputInput) stream: "stdout" | "stderr", chunk: string, waitForCommit = true, - sourceCursor?: number, + source?: CanonicalNativeLog, ) => { - const sanitizedChunk = compactRunLogChunk( - redactCurrentUserText(chunk, currentUserRedactionOptions), - ); + const sourceCursor = source?.sourceCursor; + const sanitizedChunk = source?.kind === "canonical_native" + ? redactCanonicalNativeRunLogChunk(chunk, { + redactIdentity: identityRedactor.redact, + currentUser: currentUserRedactionOptions, + }) + : compactRunLogChunk(redactCurrentUserText(chunk, currentUserRedactionOptions)); if (stream === "stdout") stdoutExcerpt = appendExcerpt(stdoutExcerpt, sanitizedChunk); if (stream === "stderr") stderrExcerpt = appendExcerpt(stderrExcerpt, sanitizedChunk); const ts = new Date().toISOString(); @@ -182,12 +178,15 @@ export function createHeartbeatRunOutput(db: Db, input: HeartbeatRunOutputInput) const chunkSeq = outputSeq; let committed: Promise = Promise.resolve(0); if (handle) { + let nativeLooking = chunk.includes('"paperclip.prp.event"'); + try { nativeLooking ||= JSON.parse(chunk)?.type === "paperclip.prp.event"; } catch { /* Diagnostics need not be JSON. */ } const event = { stream, chunk: sanitizedChunk, ts, seq: chunkSeq, sourceCursor, + preservesSourceCoverage: source?.kind === "canonical_native" || !nativeLooking, }; committed = runLogStore.enqueue ? (await runLogStore.enqueue(handle, event)).committed @@ -259,27 +258,44 @@ export function createHeartbeatRunOutput(db: Db, input: HeartbeatRunOutputInput) ); return external ? recorded.catch(reportRecordingFailure) : recorded; }; - const nativeExporter = - handle.store === "s3_segments" && run.runtimeMode === "native" - ? createNativeRunLogExporter({ - db, - companyId: run.companyId, - runId, - afterCursor: handle.initialSourceCursor ?? 0, - enqueue: (cursor, chunk) => - appendIdentityRedactedLog( - "stdout", - identityRedactor.chunk("stdout", chunk), - false, - cursor, - ), - flush: () => runLogStore.flush!(handle!), - }) - : undefined; - if (nativeExporter) await nativeExporter.recover(); - const onPersistedNativeLog = nativeExporter + let nativeExporter: Promise> | undefined; + const getNativeExporter = () => nativeExporter ??= (async () => { + if (input.runtimeLogSecretValues?.length) { + const registry = createRunSecretRedactionRegistry(db); + for (const value of new Set(input.runtimeLogSecretValues)) + await registry.register(run.companyId, runId, value); + } + const afterCursor = await nativeRunLogPrefixCursor({ + db, companyId: run.companyId, runId, store: runLogStore, handle: handle!, + // Verify the two supported historical username-masking settings. Keep + // the full private-data projection here; compaction is proved separately. + redactChunks: (chunk) => canonicalNativeRunLogRedactionForms(chunk, { + redactIdentity: identityRedactor.redact, currentUser: currentUserRedactionOptions, + }), + }); + return createNativeRunLogExporter({ + db, + companyId: run.companyId, + runId, + afterCursor, + enqueue: (cursor, chunk) => + appendIdentityRedactedLog( + "stdout", + chunk, + false, + { kind: "canonical_native", sourceCursor: cursor }, + ), + flush: () => runLogStore.flush!(handle!), + }); + })(); + if (handle.store === "s3_segments" && run.runtimeMode === "native") + await (await getNativeExporter()).recover(); + // Output begins before runtime selection persists native mode. Keep the + // source-aware callback available without querying native sources for + // ordinary legacy output. + const onPersistedNativeLog = handle.store === "s3_segments" ? (cursor: number, chunk: string) => - nativeExporter.record(cursor, chunk).catch(reportRecordingFailure) + getNativeExporter().then((exporter) => exporter.record(cursor, chunk)).catch(reportRecordingFailure) : undefined; const onAdapterMeta = async (meta: AdapterInvocationMeta) => { meta = identityRedactor.redact(meta); diff --git a/server/src/services/native-runtime/native-run-log-export.ts b/server/src/services/native-runtime/native-run-log-export.ts index d8693c56d64..ec588fc4153 100644 --- a/server/src/services/native-runtime/native-run-log-export.ts +++ b/server/src/services/native-runtime/native-run-log-export.ts @@ -3,6 +3,9 @@ import { StringDecoder } from "node:string_decoder"; import { heartbeatRunEvents, type Db } from "@paperclipai/db"; import { validatePrpEvent, type PrpEvent } from "../../vendor/paperclip-runner/index.js"; import { nativeSha256 } from "./canonical.js"; +import type { RunLogHandle, RunLogStore } from "../run-log-store.js"; +import { compactRunLogChunk } from "../heartbeat/run-log.js"; +import { MAX_RUN_LOG_RECORD_BYTES } from "../run-log-record-limits.js"; export function formatNativeRunLogEvent(event: PrpEvent) { return `${JSON.stringify({ type: "paperclip.prp.event", event })}\n`; @@ -77,35 +80,144 @@ async function sourcePage( }); } -export function createNativeRunLogCoverageVerifier(db: Db, companyId: string, runId: string) { +function matchPublishedImageOmissions(source: unknown, published: unknown): unknown { + if (Array.isArray(source)) + return source.map((value, index) => matchPublishedImageOmissions(value, + Array.isArray(published) ? published[index] : undefined)); + if (!source || typeof source !== "object") return source; + const original = source as Record; + const existing = published && typeof published === "object" + ? published as Record : {}; + const result = Object.fromEntries(Object.entries(original).map(([key, value]) => + [key, matchPublishedImageOmissions(value, existing[key])])); + const imageSource = original.source as Record | undefined; + const publishedSource = existing.source as Record | undefined; + if (original.type === "image" && imageSource?.type === "base64" && + typeof imageSource.data === "string" && typeof publishedSource?.data === "string") { + const marker = /^\[omitted base64 image data: ([0-9]+) chars\]$/.exec(publishedSource.data); + if (marker && marker[1] === String(imageSource.data.length) && imageSource.data.length >= 1024 && + /^[A-Za-z0-9+/=]+$/.test(imageSource.data)) { + // The existing scrubber depends on serialized key order, which JSONB + // does not retain. Honor only an omission already present at this path; + // published raw data still has to match the source exactly. + result.source = { ...(result.source as Record), data: publishedSource.data }; + } + } + return result; +} + +function matchesPublishedEvent(source: unknown, published: unknown) { + return nativeSha256(published) === nativeSha256(matchPublishedImageOmissions(source, published)); +} + +/** Recover a compactor omission contained within one source-backed JSON string. + * Retained properties may have any order: JSONB does not retain writer ordering. + * Reconstruct the complete envelope, prove the exact compactor output, and then + * compare every field semantically. A marker or matching substring alone is not proof. + */ +function restoreCompactedEvent(chunk: string, source: unknown): unknown { + const marker = /\n\[paperclip truncated run log chunk: omitted ([1-9][0-9]*) chars\]\n/g; + const found = marker.exec(chunk); + if (!found || marker.exec(chunk)) return; + const omitted = Number(found[1]); + if (!Number.isSafeInteger(omitted)) return; + const head = chunk.slice(0, found.index), tail = chunk.slice(found.index + found[0].length); + let quoted = false, escaped = false, start = -1; + for (let index = 0; index < head.length; index++) { + const character = head[index]; + if (!quoted) { + if (character === '"') { quoted = true; start = index; } + } else if (escaped) escaped = false; + else if (character === "\\") escaped = true; + else if (character === '"') quoted = false; + } + if (!quoted) return; + const leading = head.slice(start); + function* strings(value: unknown): Generator { + if (typeof value === "string") yield value; + else if (Array.isArray(value)) for (const child of value) yield* strings(child); + else if (value && typeof value === "object") + for (const child of Object.values(value)) yield* strings(child); + } + for (const value of strings(source)) { + const encoded = JSON.stringify(value), end = leading.length + omitted; + if (end >= encoded.length || !encoded.startsWith(leading) || !tail.startsWith(encoded.slice(end))) continue; + const restored = head + encoded.slice(leading.length, end) + tail; + if (compactRunLogChunk(restored) !== chunk) continue; + try { + const envelope = JSON.parse(restored); + if (envelope.type === "paperclip.prp.event" && matchesPublishedEvent(source, envelope.event)) + return envelope; + } catch { /* Another candidate cannot make malformed evidence authoritative. */ } + } +} + +export function createNativeRunLogCoverageVerifier( + db: Db, + companyId: string, + runId: string, + options?: { + allowSourceSuffix?: boolean; + redactChunks?: (chunk: string) => Iterable; + signal?: AbortSignal; + }, +) { const decoder = new StringDecoder("utf8"); let text = "", cursor = 0; let page: Awaited> = []; const unproven = () => new Error("native_log_source_coverage_unproven"); async function next() { - if (!page.length) page = await sourcePage(db, companyId, runId, cursor); + if (!page.length) page = await sourcePage(db, companyId, runId, cursor, undefined, options?.signal); return page[0]; } - async function line(value: string) { + async function line(value: string, newlineBytes = 1) { if (!value.trim()) return; - if (Buffer.byteLength(value) > 1024 * 1024) throw unproven(); + if (Buffer.byteLength(value) + newlineBytes > MAX_RUN_LOG_RECORD_BYTES) throw unproven(); let chunk: unknown; try { chunk = JSON.parse(value).chunk; } catch { throw unproven(); } - if (typeof chunk !== "string" || !chunk.startsWith('{"type":"paperclip.prp.event"')) return; + if (typeof chunk !== "string") throw unproven(); + let expected: Awaited>; + async function* sourceForms() { + expected ??= await next(); + if (!expected) throw unproven(); + if (!options?.redactChunks) { yield expected.event; return; } + for (const form of options.redactChunks(formatNativeRunLogEvent(expected.event))) { + let candidate; + try { candidate = JSON.parse(form); } + catch { continue; } // A malformed historical privacy projection proves nothing. + if (candidate?.type === "paperclip.prp.event" && candidate.event && + typeof candidate.event === "object" && !Array.isArray(candidate.event)) + yield candidate.event; + } + } + let envelope: { type?: unknown; event?: unknown }; + try { + envelope = JSON.parse(chunk); + } catch { + if (!chunk.includes('"paperclip.prp.event"')) return; + let restored; + for await (const form of sourceForms()) { + restored = restoreCompactedEvent(chunk, form); + if (restored) break; + } + if (!restored) throw unproven(); + envelope = restored; + } + if (envelope?.type !== "paperclip.prp.event") return; let event: PrpEvent; try { - const parsed = validatePrpEvent(JSON.parse(chunk).event); + const parsed = validatePrpEvent(envelope.event); if (!parsed.ok) throw unproven(); event = parsed.event; } catch { throw unproven(); } - const expected = await next(); + expected ??= await next(); if ( !expected || event.runId !== runId || @@ -117,6 +229,19 @@ export function createNativeRunLogCoverageVerifier(db: Db, companyId: string, ru event.eventType !== expected.event.eventType ) throw unproven(); + if (options?.redactChunks) { + // JSONB reorders object keys. Compare the complete redacted event + // semantically while retaining the original published bytes. + try { + let matched = false; + for await (const form of sourceForms()) { + if (matchesPublishedEvent(form, event)) { matched = true; break; } + } + if (!matched) throw unproven(); + } catch { + throw unproven(); + } + } cursor = expected.cursor; page.shift(); } @@ -128,17 +253,75 @@ export function createNativeRunLogCoverageVerifier(db: Db, companyId: string, ru await line(text.slice(0, boundary)); text = text.slice(boundary + 1); } - if (Buffer.byteLength(text) > 1024 * 1024) throw unproven(); + if (Buffer.byteLength(text) > MAX_RUN_LOG_RECORD_BYTES) throw unproven(); }, async finish() { text += decoder.end(); - if (text) await line(text); - if (await next()) throw unproven(); + if (text) await line(text, 0); + if (!options?.allowSourceSuffix && await next()) throw unproven(); return cursor; }, }; } +/** Validate committed provenance, or prove an older unwatermarked source prefix. */ +export async function nativeRunLogPrefixCursor(input: { + db: Db; + companyId: string; + runId: string; + store: Partial>; + handle: RunLogHandle; + redactChunks: (chunk: string) => Iterable; + signal?: AbortSignal; +}) { + const bytes = input.handle.initialBytes ?? 0; + const watermark = input.handle.initialSourceCursor ?? 0; + const unproven = () => new Error("native_log_source_coverage_unproven"); + if (!Number.isSafeInteger(bytes) || bytes < 0 || !Number.isSafeInteger(watermark) || watermark < 0) + throw unproven(); + if (!bytes && !watermark) { + await input.store.recordVerifiedSourcePrefix?.(input.handle, 0); + return 0; + } + if (input.handle.initialSourcePrefixVerified) { + const sequence = input.handle.initialSequence ?? 0; + const [company, , run, extra] = input.handle.logRef.split("/"); + if (input.handle.store !== "s3_segments" || company !== input.companyId || run !== input.runId || extra || + !bytes || !Number.isSafeInteger(sequence) || sequence < 1) throw unproven(); + // A separate immutable proof binds this exact journal index/end/sequence/cursor. + // Legacy maximum-cursor metadata alone never establishes ordered coverage. + // Only explicitly coverage-preserving appends can carry the proof forward; + // an older writer's changed prefix gets no matching proof and must scan once. + if (watermark) { + const [source] = await sourcePage(input.db, input.companyId, input.runId, + watermark - 1, watermark, input.signal); + if (!source || source.cursor !== watermark) throw unproven(); + } + return watermark; + } + if (!input.store.read) throw unproven(); + const verifier = createNativeRunLogCoverageVerifier(input.db, input.companyId, input.runId, { + allowSourceSuffix: true, + redactChunks: input.redactChunks, + signal: input.signal, + }); + let offset = 0; + while (offset < bytes) { + input.signal?.throwIfAborted(); + const page = await input.store.read(input.handle, { + offset, limitBytes: Math.min(256_000, bytes - offset), signal: input.signal, + }); + const content = Buffer.from(page.content); + if (!content.length || offset + content.length > bytes) throw unproven(); + await verifier.write(content); + offset += content.length; + } + const cursor = await verifier.finish(); + if (watermark > cursor) throw unproven(); + await input.store.recordVerifiedSourcePrefix?.(input.handle, cursor); + return cursor; +} + export function createNativeRunLogExporter(input: { db: Db; companyId: string; @@ -188,7 +371,7 @@ export function createNativeRunLogExporter(input: { if (!Number.isSafeInteger(sourceCursor) || sourceCursor < 1) throw new Error("invalid_native_run_log_cursor"); const bytes = Buffer.byteLength(chunk); - if (queuedRecords >= 32 || queuedBytes + bytes > 8 * 1024 * 1024) + if (queuedRecords >= 32 || queuedBytes + bytes > MAX_RUN_LOG_RECORD_BYTES) throw new Error("native_run_log_admission_capacity_exceeded"); queuedRecords++; queuedBytes += bytes; diff --git a/server/src/services/native-runtime/native-run-log-recovery.ts b/server/src/services/native-runtime/native-run-log-recovery.ts index b3fd0c36aaf..388f17ae389 100644 --- a/server/src/services/native-runtime/native-run-log-recovery.ts +++ b/server/src/services/native-runtime/native-run-log-recovery.ts @@ -5,16 +5,16 @@ import { nativeRunFinalizations, type Db, } from "@paperclipai/db"; -import { redactCurrentUserText, type CurrentUserRedactionOptions } from "../../log-redaction.js"; +import type { CurrentUserRedactionOptions } from "../../log-redaction.js"; import type { RunLogHandle, RunLogReadOptions, RunLogStore } from "../run-log-store.js"; import { instanceSettingsService } from "../instance-settings.js"; -import { compactRunLogChunk } from "../heartbeat/run-log.js"; +import { canonicalNativeRunLogRedactionForms, redactCanonicalNativeRunLogChunk } from "../heartbeat/run-log.js"; import { beginIdleTrackedWork } from "../task-admission.js"; import { agentIdentityService } from "../agent-identity.js"; import { createRunSecretRedactionRegistry } from "../run-secret-redaction.js"; import { createAgentIdentityRedactor } from "../agent-identity-redaction.js"; import { logger } from "../../middleware/logger.js"; -import { createNativeRunLogExporter, nativeRunLogSourceWhere } from "./native-run-log-export.js"; +import { createNativeRunLogExporter, nativeRunLogPrefixCursor, nativeRunLogSourceWhere } from "./native-run-log-export.js"; interface Recovery { work: Promise; @@ -148,37 +148,44 @@ export async function recoverSettledNativeRunLog( let lastSourceCursor = handle.initialSourceCursor ?? 0; const receipts: Promise[] = []; let failure: unknown; - const exporter = createNativeRunLogExporter({ - db, - companyId, - runId, - afterCursor: handle.initialSourceCursor ?? 0, - signal, - enqueue: async (sourceCursor, chunk) => { - const receipt = await store.enqueue!(handle, { - stream: "stdout", - ts: new Date().toISOString(), - seq: ++sequence, - sourceCursor, - chunk: compactRunLogChunk( - redactCurrentUserText(identityRedactor.chunk("stdout", chunk), redaction), - ), - }); - receipts.push( - receipt.committed.catch((error) => { - failure ??= error; - return 0; - }), - ); - lastSourceCursor = sourceCursor; - }, - flush: async () => { - await store.flush!(handle); - await Promise.all(receipts.splice(0)); - if (failure) throw failure; - }, - }); try { + lastSourceCursor = await nativeRunLogPrefixCursor({ + db, companyId, runId, store, handle, signal, + redactChunks: (chunk) => canonicalNativeRunLogRedactionForms(chunk, { + redactIdentity: identityRedactor.redact, currentUser: redaction, + }), + }); + const exporter = createNativeRunLogExporter({ + db, + companyId, + runId, + afterCursor: lastSourceCursor, + signal, + enqueue: async (sourceCursor, chunk) => { + const receipt = await store.enqueue!(handle, { + stream: "stdout", + ts: new Date().toISOString(), + seq: ++sequence, + sourceCursor, + preservesSourceCoverage: true, + chunk: redactCanonicalNativeRunLogChunk(chunk, { + redactIdentity: identityRedactor.redact, currentUser: redaction, + }), + }); + receipts.push( + receipt.committed.catch((error) => { + failure ??= error; + return 0; + }), + ); + lastSourceCursor = sourceCursor; + }, + flush: async () => { + await store.flush!(handle); + await Promise.all(receipts.splice(0)); + if (failure) throw failure; + }, + }); await exporter.recover(); } catch (error) { failure ??= error; diff --git a/server/src/services/native-runtime/native-run-log-watermark.test.ts b/server/src/services/native-runtime/native-run-log-watermark.test.ts new file mode 100644 index 00000000000..392bbb7658b --- /dev/null +++ b/server/src/services/native-runtime/native-run-log-watermark.test.ts @@ -0,0 +1,610 @@ +import { createHash, randomUUID } from "node:crypto"; +import { Readable } from "node:stream"; +import { eq, sql } from "drizzle-orm"; +import { closeRegisteredClients, createDb, heartbeatRunEvents, heartbeatRuns, EMBEDDED_POSTGRES_TEST_TIMEOUT_MS, type Db } from "@paperclipai/db"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { resolveExternalTestDatabaseUrl } from "../../__tests__/helpers/external-test-database.js"; +import { createNativeRunLogTestTables } from "../../__tests__/helpers/native-run-log-database.js"; +import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase } from "../../__tests__/helpers/embedded-postgres.js"; +import { canonicalProviderEventsFromCodex } from "@paperclipai/paperclip-runner"; +import type { RunLogHandle, RunLogStore } from "../run-log-store.js"; +import type { StorageProvider } from "../../storage/types.js"; +import { validatePrpEvent, type PrpEvent } from "../../vendor/paperclip-runner/index.js"; +import { instanceSettingsService } from "../instance-settings.js"; +import type { CurrentUserRedactionOptions } from "../../log-redaction.js"; +import { createHeartbeatRunOutput } from "../heartbeat/run-output.js"; +import { compactRunLogChunk } from "../heartbeat/run-log.js"; +import { createObjectRunLogStore } from "../object-run-log-store.js"; +import { nativeSha256 } from "./canonical.js"; +import { createNativeRunLogCoverageVerifier, formatNativeRunLogEvent } from "./native-run-log-export.js"; +import { readRecoverableRunLog, recoverSettledNativeRunLog } from "./native-run-log-recovery.js"; + +// Use an explicit guarded test database or a new owned embedded fixture. +const externalUrl = resolveExternalTestDatabaseUrl("PAPERCLIP_NATIVE_LOG_WATERMARK_DATABASE_URL"); +const support = externalUrl ? { supported: true } : await getEmbeddedPostgresTestSupport(); + +function memoryProvider(): StorageProvider { + const objects = new Map(); + const etag = (bytes: Buffer) => createHash("sha256").update(bytes).digest("hex"); + return { + id: "s3", + async putObject() { throw new Error("unconditional object write"); }, + async putObjectConditional(input) { + const old = objects.get(input.objectKey); + if (input.ifNoneMatch ? old : !old || etag(old) !== input.ifMatch) + throw Object.assign(new Error("conflict"), { name: "PreconditionFailed" }); + const chunks: Buffer[] = []; + for await (const chunk of Readable.from(input.body)) chunks.push(Buffer.from(chunk)); + const bytes = Buffer.concat(chunks); + objects.set(input.objectKey, bytes); + return { etag: etag(bytes) }; + }, + async getObject(input) { + const bytes = objects.get(input.objectKey); + if (!bytes) throw Object.assign(new Error("missing"), { name: "NoSuchKey" }); + return { stream: Readable.from([bytes]), etag: etag(bytes) }; + }, + async headObject(input) { return { exists: objects.has(input.objectKey) }; }, + async deleteObject(input) { objects.delete(input.objectKey); }, + async listObjects(input) { + return { keys: [...objects.keys()].filter((key) => key.startsWith(input.prefix)) }; + }, + }; +} + +describe.skipIf(!support.supported)("native run log source watermarks", () => { + const schema = `native_watermark_${randomUUID().replaceAll("-", "")}`; + let db: Db; + let database: Awaited>; + beforeAll(async () => { + database = externalUrl ? { connectionString: externalUrl, cleanup: async () => {} } + : await startEmbeddedPostgresTestDatabase("native-log-watermark-"); + db = createDb(database.connectionString, { maxConnections: 1, idleTimeoutSeconds: 0 }); + await db.execute(sql.raw(`create schema ${schema}`)); + await db.execute(sql.raw(`set search_path=${schema}`)); + await createNativeRunLogTestTables(db); + await db.execute(sql`create table instance_settings(id uuid primary key default gen_random_uuid(), + singleton_key text unique default 'default', default_environment_id uuid, + general jsonb not null default '{}', experimental jsonb not null default '{}', + created_at timestamptz default now(), updated_at timestamptz default now())`); + // Match the production queued-run default instead of the older native fixture default. + await db.execute(sql`alter table heartbeat_runs alter column runtime_mode set default 'legacy'`); + }, EMBEDDED_POSTGRES_TEST_TIMEOUT_MS); + afterAll(async () => { + try { + if (db) await db.execute(sql.raw(`drop schema ${schema} cascade`)); + } finally { + if (database) { + await closeRegisteredClients(database.connectionString, { scope: "database" }); + await database.cleanup(); + } + } + }); + + async function fixture() { + const binding = { companyId: randomUUID(), agentId: randomUUID(), runId: randomUUID() }; + await db.execute(sql`insert into heartbeat_runs(id,company_id,agent_id,status) + values(${binding.runId},${binding.companyId},${binding.agentId},'running')`); + const provider = memoryProvider(); + const store = () => createObjectRunLogStore({ + provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async (input) => { await input.assertWriterAuthority?.(); }, + }); + const event = (seq: number): PrpEvent => ({ + schema: "paperclip.prp.event.v1", schemaVersion: 1, + runId: binding.runId, sourceInstanceId: "fixture-source", sourceEventId: `source:${seq}`, + sourceSeq: seq, sourceKind: "runner", normalizedSessionId: "fixture-session", + eventType: seq === 2 ? "turn.interrupted" : "item.delta", priority: 2, + emittedAt: "2026-10-31T00:00:00.000Z", payload: { text: `step ${seq} 再開` }, + }); + const persist = async (value: PrpEvent, cursor: number) => { + expect(validatePrpEvent(value).ok).toBe(true); + await db.execute(sql`insert into heartbeat_run_events(company_id,run_id,agent_id,seq,event_type, + payload,source_instance_id,source_event_id,source_seq,source_payload_sha256,protocol_schema_version) + values(${binding.companyId},${binding.runId},${binding.agentId},${cursor},${value.eventType}, + ${JSON.stringify({ prpEvent: value })}::jsonb,${value.sourceInstanceId},${value.sourceEventId}, + ${value.sourceSeq},${nativeSha256(value)},${value.schemaVersion})`); + }; + const settle = async (logRef: string) => { + await db.update(heartbeatRuns).set({ runtimeMode: "native", status: "cancelled", + logStore: "s3_segments", logRef, logBytes: null }).where(eq(heartbeatRuns.id, binding.runId)); + }; + return { binding, store, event, persist, settle, provider }; + } + + function toolEvent(f: Awaited>, output: string): PrpEvent { + return { ...f.event(1), itemId: "tool-1", priority: 1, eventType: "tool.execution.completed", payload: { + schema: "paperclip.tool.execution.v1", executionId: "tool-1", transport: "process", + operation: "execute", status: "completed", output, + outputBytes: Buffer.byteLength(output), outputTruncated: false, outputDigest: null, exitCode: 0, + } }; + } + + async function readAll(store: Pick, handle: RunLogHandle) { + let offset = 0, content = ""; + for (let page = 0; page < 16; page++) { + const result = await store.read(handle, { offset, limitBytes: 4 * 1024 * 1024 }); + content += result.content; + if (result.nextOffset === undefined) return content; + expect(result.nextOffset).toBeGreaterThan(offset); + offset = result.nextOffset; + } + throw new Error("fixture log exceeded bounded read pages"); + } + + function planEvent(f: Awaited>, count: number, text: string, seq = 1): PrpEvent { + const [mapped] = canonicalProviderEventsFromCodex("turn/plan/updated", { turnId: "fixture-plan-turn", + revision: seq, plan: Array.from({ length: count }, () => ({ step: text, status: "pending" })) }); + expect(mapped?.eventType).toBe("plan.updated"); + return { ...f.event(seq), ...mapped! }; + } + + function failPublishedPrefixProof(f: Awaited>) { + const put = f.provider.putObjectConditional!.bind(f.provider); + let initialProof: string | undefined, enabled = true, failures = 0; + f.provider.putObjectConditional = async input => { + if (input.objectKey.includes("/objects/source-prefix-proof-v1-")) { + initialProof ??= input.objectKey; + if (enabled && input.objectKey !== initialProof) { + failures++; + throw Object.assign(new Error("proof storage unavailable"), { $metadata: { httpStatusCode: 503 } }); + } + } + return put(input); + }; + return { failures: () => failures, restore: () => { enabled = false; } }; + } + + async function publishProductionPrefix( + f: Awaited>, event: PrpEvent, + options: { watermark?: boolean; redaction?: () => Promise; diagnostic?: string } = {}, + ) { + const [saved] = await db.select({ runtimeMode: heartbeatRuns.runtimeMode }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + const row = { id: f.binding.runId, companyId: f.binding.companyId, agentId: f.binding.agentId, + status: "running", runtimeMode: saved!.runtimeMode, logStore: null, logRef: null, + logBytes: null, lastOutputSeq: 0, lastOutputAt: null } as typeof heartbeatRuns.$inferSelect; + const store = f.store(); + const output = createHeartbeatRunOutput(db, { + run: row!, runId: row!.id, issueId: null, runLogStore: store, + identityRedactor: { chunk: (_stream, chunk) => chunk, redact: value => value }, + secretKeys: new Set(), appendRunEvent: async () => undefined, + getCurrentUserRedactionOptions: options.redaction ?? (async () => ({ enabled: false })), + }); + const handlers = await output.begin(row!); + await db.update(heartbeatRuns).set({ runtimeMode: "native" }).where(eq(heartbeatRuns.id, row!.id)); + await f.persist(event, 2); + // Historical queued-run writers used onLog before source cursors were retained. + if (options.watermark === false) await handlers.onLog("stdout", formatNativeRunLogEvent(event)); + else await handlers.onPersistedNativeLog!(2, formatNativeRunLogEvent(event)); + if (options.diagnostic) await handlers.onLog("stderr", options.diagnostic); + await store.finalize(output.handle!); + return { store, handle: output.handle!, prefix: await readAll(store, output.handle!) }; + } + + it.each([true, false])("cold-recovers an explicit legacy-compacted 64KiB tool event with committed cursor: %s", async (watermark) => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const event = toolEvent(f, "retained output 再開 ".repeat(4000).slice(0, 65_536)); + await f.persist(event, 2); + // Immutable old producer format, even when the current canonical writer becomes lossless. + await store.append(handle, { stream: "stdout", ts: "legacy", seq: 1, + ...(watermark ? { sourceCursor: 2 } : {}), chunk: compactRunLogChunk(formatNativeRunLogEvent(event)) }); + await store.finalize(handle); + const prefix = await readAll(store, handle); + const chunk = JSON.parse(prefix).chunk as string; + expect(chunk).toContain("[paperclip truncated run log chunk: omitted "); + expect(() => JSON.parse(chunk)).toThrow(); + const [durable] = await db.select({ payload: heartbeatRunEvents.payload }).from(heartbeatRunEvents) + .where(eq(heartbeatRunEvents.runId, f.binding.runId)); + expect(JSON.stringify(durable!.payload!.prpEvent)).not.toBe(JSON.stringify(event)); + await f.persist(f.event(2), 5); + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + const content = (await cold.read(handle)).content; + expect(content.startsWith(prefix)).toBe(true); + const lines = content.trim().split("\n").map(line => JSON.parse(line)); + expect(lines).toHaveLength(2); + expect(lines[0].chunk).toBe(chunk); + expect(JSON.parse(lines[1].chunk).event.sourceEventId).toBe("source:2"); + const [run] = await db.select({ bytes: heartbeatRuns.logBytes }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + expect(run!.bytes).toBe(Buffer.byteLength(content)); + }); + + it.each([[20, "A"], [256, "界"]] as const)("retains a current %i-step %s plan through proof outage and cold recovery", async (count, character) => { + const f = await fixture(), event = planEvent(f, count, character.repeat(4000)); + const outage = failPublishedPrefixProof(f); + const { store, handle, prefix } = await publishProductionPrefix(f, event, { diagnostic: "diagnostic ".repeat(10_000) }); + expect(outage.failures()).toBeGreaterThan(0); + outage.restore(); + const snapshot = await store.begin(f.binding); + expect(snapshot.initialSourceCursor).toBe(2); + expect(snapshot.initialSourcePrefixVerified).toBe(false); + await store.finalize(snapshot); + const suffix = planEvent(f, count, character.repeat(4000), 2); + await f.persist(suffix, 5); + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + const content = await readAll(cold, handle); + expect(content.startsWith(prefix)).toBe(true); + const entries = content.trim().split("\n").map(line => JSON.parse(line)); + expect(entries).toHaveLength(3); + expect(nativeSha256(JSON.parse(entries[0].chunk).event)).toBe(nativeSha256(event)); + expect(nativeSha256(JSON.parse(entries[2].chunk).event)).toBe(nativeSha256(suffix)); + expect(entries[0].chunk).not.toContain("[paperclip truncated"); + expect(entries[2].chunk).not.toContain("[paperclip truncated"); + expect(entries[1].chunk).toContain("[paperclip truncated run log chunk:"); + expect(entries[1].chunk.length).toBeLessThan(64 * 1024); + if (count === 256) expect(Buffer.byteLength(entries[0].chunk)).toBeGreaterThan(1024 * 1024); + expect(entries.map(entry => entry.seq)).toEqual([1, 2, 3]); + const resumed = await cold.begin(f.binding); + expect(resumed.initialSourceCursor).toBe(5); + expect(resumed.initialSourcePrefixVerified).toBe(true); + await cold.finalize(resumed); + }); + + it("scrubs private canaries and image data before lossless canonical publication and recovery", async () => { + const f = await fixture(), canary = "fixture-private-bearer-canary"; + const event = { ...f.event(1), payload: { header: `Authorization: Bearer ${canary}`, api_key: canary, + image: { type: "image", source: { type: "base64", data: "A".repeat(70000) } }, + parts: Array.from({ length: 20 }, () => "preserved ".repeat(400)), + } }; + const outage = failPublishedPrefixProof(f); + const { handle, prefix } = await publishProductionPrefix(f, event); + expect(outage.failures()).toBeGreaterThan(0); + outage.restore(); + expect(prefix).not.toContain(canary); + expect(prefix).toContain("[omitted base64 image data: 70000 chars]"); + const suffix: PrpEvent = { ...f.event(2), eventType: "item.delta", payload: event.payload }; + await f.persist(suffix, 5); + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + const content = await readAll(cold, handle); + expect(content.startsWith(prefix)).toBe(true); + expect(content).not.toContain(canary); + const entries = content.trim().split("\n").map(line => JSON.parse(JSON.parse(line).chunk).event); + expect(entries.map(event => event.sourceEventId)).toEqual(["source:1", "source:2"]); + for (const entry of entries) { + expect(entry.payload.parts).toEqual(event.payload.parts); + expect(entry.payload.image.source.data).toBe("[omitted base64 image data: 70000 chars]"); + expect(entry.payload.api_key).toBe("***REDACTED***"); + expect(entry.payload.header).toBe("Authorization: ***REDACTED***"); + } + }); + + it("leaves old unprovable multi-string compaction failed and byte-identical", async () => { + const f = await fixture(), event = planEvent(f, 20, "A".repeat(4000)); + await f.persist(event, 2); + await f.persist(f.event(2), 5); + const store = f.store(), handle = await store.begin(f.binding); + const chunk = compactRunLogChunk(formatNativeRunLogEvent(event)); + expect(chunk).toContain("[paperclip truncated run log chunk:"); + expect(() => JSON.parse(chunk)).toThrow(); + await store.append(handle, { stream: "stdout", ts: "immutable-old-format", seq: 1, sourceCursor: 2, chunk }); + await store.finalize(handle); + const prefix = await readAll(store, handle); + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect(await readAll(cold, handle)).toBe(prefix); + const [run] = await db.select({ bytes: heartbeatRuns.logBytes }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + expect(run!.bytes).toBeNull(); + }); + + it("leaves an old privacy-mangled canonical prefix failed and byte-identical", async () => { + const f = await fixture(); + const event = { ...f.event(1), payload: { header: "Authorization: Bearer fixture-old-bearer-canary" } }; + await f.persist(event, 2); + const store = f.store(), handle = await store.begin(f.binding); + const chunk = compactRunLogChunk(formatNativeRunLogEvent(event)); + expect(() => JSON.parse(chunk)).toThrow(); + await store.append(handle, { stream: "stdout", ts: "immutable-old-privacy-format", seq: 1, sourceCursor: 2, chunk }); + await store.finalize(handle); + const prefix = await readAll(store, handle); + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect(await readAll(cold, handle)).toBe(prefix); + const [run] = await db.select({ bytes: heartbeatRuns.logBytes }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + expect(run!.bytes).toBeNull(); + }); + + it("rejects a verifier record exceeding the accepted 8MiB writer bound", async () => { + const f = await fixture(); + const verifier = createNativeRunLogCoverageVerifier(db, f.binding.companyId, f.binding.runId); + const bytes = Buffer.from(`${JSON.stringify({ chunk: "x".repeat(8 * 1024 * 1024) })}\n`); + await expect(verifier.write(bytes)).rejects.toThrow("native_log_source_coverage_unproven"); + }); + + it.each([true, false])("retains a zero-watermark production prefix when username masking changes from %s", async (enabled) => { + const f = await fixture(); + const setMasking = async (value: boolean) => db.execute(sql`insert into instance_settings(general) + values(${JSON.stringify({ censorUsernameInLogs: value })}::jsonb) + on conflict(singleton_key) do update set general=excluded.general`); + const redaction = async () => ({ enabled: (await instanceSettingsService(db).getGeneral()).censorUsernameInLogs, + userNames: ["fixture-operator"], homeDirs: ["/home/fixture-operator"] }); + await setMasking(enabled); + const event = { ...f.event(1), payload: { text: "fixture-operator owns /home/fixture-operator/file.txt" } }; + const { handle, prefix } = await publishProductionPrefix(f, event, { watermark: false, redaction }); + expect(prefix.includes("fixture-operator")).toBe(!enabled); + await setMasking(!enabled); + await f.persist({ ...f.event(2), payload: event.payload }, 5); + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, redaction); + const content = (await cold.read(handle)).content; + expect(content.startsWith(prefix)).toBe(true); + const lines = content.trim().split("\n").map(line => JSON.parse(line)); + expect(lines).toHaveLength(2); + expect(lines[1].chunk.includes("fixture-operator")).toBe(enabled); + }); + + it("rejects a historical duplicate prefix even when the second copy advanced the journal cursor", async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const event = f.event(1), chunk = formatNativeRunLogEvent(event); + await f.persist(event, 2); + await f.persist(f.event(2), 5); + await store.append(handle, { stream: "stdout", ts: "old-unwatermarked", seq: 1, chunk }); + await store.append(handle, { stream: "stdout", ts: "old-repair", seq: 2, sourceCursor: 2, chunk }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + const oldHead = await store.begin(f.binding); + expect(oldHead.initialSourceCursor).toBe(2); + await store.finalize(oldHead); + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect((await cold.read(handle)).content).toBe(prefix); + const [run] = await db.select({ bytes: heartbeatRuns.logBytes }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + expect(run!.bytes).toBeNull(); + }); + + it("fully verifies a valid legacy nonzero prefix once, then resumes with bounded verified provenance", async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + await f.persist(f.event(1), 2); + await store.append(handle, { stream: "stdout", ts: "legacy", seq: 1, sourceCursor: 2, + chunk: formatNativeRunLogEvent(f.event(1)) }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.persist(f.event(2), 5); + await f.settle(handle.logRef); + const cold = f.store(), read = cold.read; + let bytesRead = 0; + cold.read = async (...args) => { + const result = await read(...args); bytesRead += Buffer.byteLength(result.content); return result; + }; + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + expect(bytesRead).toBeGreaterThanOrEqual(Buffer.byteLength(prefix)); + const repaired = (await read(handle)).content; + expect(repaired.startsWith(prefix)).toBe(true); + expect(repaired.trim().split("\n")).toHaveLength(2); + await f.settle(handle.logRef); + bytesRead = 0; + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + expect(bytesRead).toBe(0); + expect((await read(handle)).content).toBe(repaired); + }); + + it("uses bounded committed-cursor proof even after a long non-native diagnostic tail", async () => { + const f = await fixture(); + const { store, handle } = await publishProductionPrefix(f, f.event(1)); + const writer = await store.begin(f.binding); + for (let index = 0; index < 50; index++) await store.append(writer, { + stream: "stderr", ts: "diagnostic", seq: index + 2, chunk: "diagnostic ".repeat(3000), + preservesSourceCoverage: true, + }); + await store.finalize(writer); + const before = await store.begin(f.binding); + expect(before.initialBytes).toBeGreaterThan(1_000_000); + expect(before.initialSourceCursor).toBe(2); + await store.finalize(before); + await f.persist(f.event(2), 5); + await f.settle(handle.logRef); + const cold = f.store(), originalRead = cold.read; + let prefixBytesRead = 0; + cold.read = async (...args) => { + const result = await originalRead(...args); + prefixBytesRead += Buffer.byteLength(result.content); + return result; + }; + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + expect(prefixBytesRead).toBe(0); + const content = (await originalRead(handle, { limitBytes: 4 * 1024 * 1024 })).content; + const chunks = content.trim().split("\n").map(line => JSON.parse(line).chunk as string); + expect(chunks).toHaveLength(52); + expect(JSON.parse(chunks[0]!).event.sourceEventId).toBe("source:1"); + expect(chunks.slice(1, -1).every(chunk => chunk.startsWith("diagnostic "))).toBe(true); + expect(JSON.parse(chunks.at(-1)!).event.sourceEventId).toBe("source:2"); + }); + + it.each(["visible-content", "foreign", "order"] as const)("rejects a compacted zero-watermark prefix with %s corruption", async kind => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const event = toolEvent(f, "retained output ".repeat(5000).slice(0, 65_536)); + await f.persist(event, 2); + await f.persist(f.event(2), 5); + const published = kind === "foreign" ? { ...event, runId: randomUUID() } : event; + let chunk = compactRunLogChunk(formatNativeRunLogEvent(published)); + if (kind === "visible-content") chunk = chunk.replace("retained output", "changed! output"); + if (kind === "order") await store.append(handle, { stream: "stdout", ts: "original", seq: 1, + chunk: formatNativeRunLogEvent(f.event(2)) }); + await store.append(handle, { stream: "stdout", ts: "original", seq: kind === "order" ? 2 : 1, chunk }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect((await cold.read(handle)).content).toBe(prefix); + }); + + it("records native cursors when output begins with the queued legacy default, then cancels and cold-reads without replay", async () => { + const f = await fixture(); + const [persisted] = await db.select({ runtimeMode: heartbeatRuns.runtimeMode }) + .from(heartbeatRuns).where(eq(heartbeatRuns.id, f.binding.runId)); + expect(persisted!.runtimeMode).toBe("legacy"); + const initialRow: Partial = { + companyId: f.binding.companyId, agentId: f.binding.agentId, + id: f.binding.runId, status: "running", ...persisted, + logStore: null, logRef: null, logBytes: null, lastOutputSeq: 0, lastOutputAt: null, + }; + const run = initialRow as typeof heartbeatRuns.$inferSelect; + const store = f.store(); + const output = createHeartbeatRunOutput(db, { + run, runId: run.id, issueId: null, runLogStore: store, + identityRedactor: { chunk: (_stream, chunk) => chunk, redact: (value) => value }, + secretKeys: new Set(), appendRunEvent: async () => undefined, + getCurrentUserRedactionOptions: async () => ({ enabled: false }), + }); + const handlers = await output.begin(run); + // Runtime selection persists a new row; the output closure retains the earlier row. + await db.update(heartbeatRuns).set({ runtimeMode: "native" }).where(eq(heartbeatRuns.id, run.id)); + for (const cursor of [2, 5]) { + const event = f.event(cursor === 2 ? 1 : 2); + await f.persist(event, cursor); + // This is the executor's persisted-native callback/fallback dispatch. + const chunk = formatNativeRunLogEvent(event); + if (handlers.onPersistedNativeLog) await handlers.onPersistedNativeLog(cursor, chunk); + else await handlers.onLog("stdout", chunk); + } + await store.finalize(output.handle!); + const prefix = (await store.read(output.handle!)).content; + await f.settle(output.handle!.logRef); + const cold = f.store(); + const read = await readRecoverableRunLog(db, cold, output.handle!, undefined, + { runtimeMode: "native", status: "cancelled", logBytes: null }); + expect(read.content).toBe(prefix); + const entries = read.content.trim().split("\n").map(line => JSON.parse(JSON.parse(line).chunk).event); + expect(entries.map(event => event.sourceEventId)).toEqual(["source:1", "source:2"]); + const resumed = await cold.begin(f.binding); + expect(resumed.initialSourceCursor).toBe(5); + await cold.finalize(resumed); + }); + + it("proves a zero-watermark prefix across JSONB key order and appends only the missing suffix", async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const events = Array.from({ length: 50 }, (_, index) => ({ + ...f.event(index + 1), payload: { text: `${index + 1} ${"再開".repeat(1000)}` }, + })); + for (const [index, event] of events.entries()) await f.persist(event, (index + 1) * 2); + const [durable] = await db.select({ payload: heartbeatRunEvents.payload }).from(heartbeatRunEvents) + .where(eq(heartbeatRunEvents.runId, f.binding.runId)).limit(1); + expect(JSON.stringify(durable!.payload!.prpEvent)).not.toBe(JSON.stringify(events[0])); + await store.append(handle, { stream: "stdout", ts: "original", seq: 1, chunk: "preparation diagnostic\n" }); + for (const [index, event] of events.slice(0, 49).entries()) { + await store.append(handle, { stream: "stdout", ts: "original", seq: index + 2, + chunk: formatNativeRunLogEvent(event) }); + } + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + // The full prefix spans multiple byte pages and multiple 16-event source pages. + let prefixOffset = Buffer.byteLength(prefix); + let fullPrefix = prefix; + for (;;) { + const page = await store.read(handle, { offset: prefixOffset }); + fullPrefix += page.content; + if (page.nextOffset === undefined) break; + prefixOffset = page.nextOffset; + } + expect(Buffer.byteLength(fullPrefix)).toBeGreaterThan(256_000); + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + const content = (await cold.read(handle, { limitBytes: 1024 * 1024 })).content; + expect(content.startsWith(fullPrefix)).toBe(true); + const entries = content.trim().split("\n").map(line => JSON.parse(line)); + expect(entries.slice(1).map(entry => JSON.parse(entry.chunk).event.sourceSeq)) + .toEqual(Array.from({ length: 50 }, (_, index) => index + 1)); + expect(entries.map(entry => entry.seq)).toEqual(Array.from({ length: 51 }, (_, index) => index + 1)); + const resumed = await cold.begin(f.binding); + expect(resumed.initialSourceCursor).toBe(100); + await cold.finalize(resumed); + }); + + it.each([true, false])("preserves an existing image prefix when base64 was omitted: %s", async (omitted) => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const data = "A".repeat(1024); + const event = { ...f.event(1), payload: { image: { type: "image", + source: omitted ? { type: "base64", data } : { data, type: "base64" }, + } } }; + await f.persist(event, 1); + await f.persist(f.event(2), 2); + const chunk = compactRunLogChunk(formatNativeRunLogEvent(event)); + expect(chunk.includes("[omitted base64 image data: 1024 chars]")).toBe(omitted); + await store.append(handle, { stream: "stdout", ts: "original", seq: 1, chunk }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.settle(handle.logRef); + const cold = f.store(); + await recoverSettledNativeRunLog(db, cold, handle.logRef, async () => ({ enabled: false })); + const content = (await cold.read(handle)).content; + expect(content.startsWith(prefix)).toBe(true); + expect(content.trim().split("\n")).toHaveLength(2); + }); + + it("rejects conflicting raw image data even when the base64 length matches", async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const image = (data: string) => ({ ...f.event(1), payload: { image: { + type: "image", source: { data, type: "base64" }, + } } }); + await f.persist(image("A".repeat(1024)), 1); + await store.append(handle, { stream: "stdout", ts: "original", seq: 1, + chunk: compactRunLogChunk(formatNativeRunLogEvent(image("B".repeat(1024)))) }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect((await cold.read(handle)).content).toBe(prefix); + }); + + it("rejects an image omission marker in a non-image payload", async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + const event = (data: string) => ({ ...f.event(1), payload: { file: { + type: "file", source: { type: "base64", data }, + } } }); + await f.persist(event("A".repeat(1024)), 1); + await store.append(handle, { stream: "stdout", ts: "original", seq: 1, + chunk: formatNativeRunLogEvent(event("[omitted base64 image data: 1024 chars]")) }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect((await cold.read(handle)).content).toBe(prefix); + }); + + for (const kind of ["conflicting", "malformed", "duplicate"] as const) { + it(`leaves a ${kind} zero-watermark prefix unchanged and incomplete`, async () => { + const f = await fixture(), store = f.store(), handle = await store.begin(f.binding); + await f.persist(f.event(1), 1); + await f.persist(f.event(2), 2); + const chunk = kind === "conflicting" + ? formatNativeRunLogEvent({ ...f.event(1), payload: { text: "different" } }) + : kind === "malformed" ? '{"type":"paperclip.prp.event","event":broken\n' + : formatNativeRunLogEvent(f.event(1)); + await store.append(handle, { stream: "stdout", ts: "original", seq: 1, chunk }); + if (kind === "duplicate") await store.append(handle, { stream: "stdout", ts: "original", seq: 2, chunk }); + await store.finalize(handle); + const prefix = (await store.read(handle)).content; + await f.settle(handle.logRef); + const cold = f.store(); + await expect(recoverSettledNativeRunLog(db, cold, handle.logRef, + async () => ({ enabled: false }))).rejects.toThrow("native_log_source_coverage_unproven"); + expect((await cold.read(handle)).content).toBe(prefix); + const [row] = await db.select({ bytes: heartbeatRuns.logBytes }).from(heartbeatRuns) + .where(eq(heartbeatRuns.id, f.binding.runId)); + expect(row!.bytes).toBeNull(); + }); + } +}); diff --git a/server/src/services/native-runtime/native-session-executor.ts b/server/src/services/native-runtime/native-session-executor.ts index da9b2b858cf..5ff6c625147 100644 --- a/server/src/services/native-runtime/native-session-executor.ts +++ b/server/src/services/native-runtime/native-session-executor.ts @@ -6129,6 +6129,7 @@ function runnerProviderStateFilename(execution: NativeExecutionInput): string { case "grok_bot": case "openai_dot": return "dot-provider-state.json"; + case "cursor_cloud": case "codex": case "opencode": return "codex-provider-state.json"; @@ -6229,11 +6230,12 @@ export function providerSessionIdentityFromDurableProviderState(input: { providerSessionIdentity: structuredClone(identity), }; } + case "cursor_cloud": case "codex": case "opencode": { const config = record(state.config); const expectedDriver = - input.execution.provider.kind === "codex" + input.execution.provider.kind === "cursor_cloud" ? "cursor_cloud_api" : input.execution.provider.kind === "codex" ? "codex_app_server" : "opencode_server"; if ( diff --git a/server/src/services/object-byte-journal.ts b/server/src/services/object-byte-journal.ts index 67f28d0c604..3a2ece6f3d9 100644 --- a/server/src/services/object-byte-journal.ts +++ b/server/src/services/object-byte-journal.ts @@ -53,6 +53,14 @@ export class ObjectJournalConflictError extends Error { super("The output journal is owned by another writer"); } } +export class ObjectJournalSourcePrefixProofUnavailableError extends Error { + constructor(readonly writer: ObjectJournalWriter) { + super("The committed log prefix has no available source proof"); + } +} +class ObjectJournalSourcePrefixProofInvalidError extends Error { + constructor() { super("object_journal_source_prefix_proof_invalid"); } +} export function isObjectPreconditionFailure(error: unknown) { const e = error as { name?: string; $metadata?: { httpStatusCode?: number } }; return e?.name === "PreconditionFailed" || e?.$metadata?.httpStatusCode === 412; @@ -292,6 +300,69 @@ export function createObjectByteJournal(options: ObjectByteJournalOptions) { } return { head: value, etag: result.etag }; } + function sourcePrefixProof(snapshot: ObjectJournalHead) { + // Leave strict head v1 unchanged for older readers/rollback. Ownership and + // close/claim state may change without changing this immutable byte prefix. + const fingerprint = sha256(Buffer.from(JSON.stringify({ + end: snapshot.end, sequence: snapshot.sequence, sourceCursor: snapshot.sourceCursor, + root: snapshot.root, roots: snapshot.roots ?? null, + }))); + return { + // Existing scoped object cleanup also removes these unreferenced metadata objects. + key: `${objectPrefix}source-prefix-proof-v1-${fingerprint}`, + bytes: Buffer.from(JSON.stringify({ schema: "paperclip.run-log.source-prefix-proof.v1", fingerprint })), + }; + } + async function hasVerifiedSourcePrefix(snapshot: ObjectJournalHead, signal?: AbortSignal) { + const proof = sourcePrefixProof(snapshot); + let stored: Awaited>; + try { stored = await getBytes(proof.key, 4096, signal); } + catch (error) { if (isMissing(error)) return false; throw error; } + if (!stored.bytes.equals(proof.bytes)) throw new ObjectJournalSourcePrefixProofInvalidError(); + return true; + } + async function recordVerifiedSourcePrefix(writer: ObjectJournalWriter, sourceCursor: number, signal?: AbortSignal) { + const callerSignal = signal; + signal = signal + ? AbortSignal.any([signal, AbortSignal.timeout(15_000)]) + : AbortSignal.timeout(15_000); + signal.throwIfAborted(); + if (!Number.isSafeInteger(sourceCursor) || sourceCursor < writer.head.sourceCursor) + throw new Error("object_journal_invalid_source_prefix_cursor"); + const current = await head(signal); + if (!current || current.etag !== writer.etag || current.head.closed || current.head.deleted) + throw new ObjectJournalConflictError(); + // One-time verification can repair legacy max-cursor metadata, never payload bytes. + if (sourceCursor !== writer.head.sourceCursor) + writer = await publish({ ...writer.head, sourceCursor }, writer.etag, signal); + const proof = sourcePrefixProof(writer.head); + try { + await retryObjectOperation(() => putConditional({ + objectKey: proof.key, body: proof.bytes, contentLength: proof.bytes.length, + contentType: "application/json", ifNoneMatch: "*", signal, + }), signal); + } catch (error) { + callerSignal?.throwIfAborted(); + if (error instanceof ObjectJournalConflictError) throw error; + // A lost reply or an already published identical immutable proof is safe. + try { + if (await hasVerifiedSourcePrefix(writer.head, signal)) return writer; + } catch (readError) { + callerSignal?.throwIfAborted(); + if (readError instanceof ObjectJournalSourcePrefixProofInvalidError || + readError instanceof ObjectJournalConflictError) throw readError; + if (signal.aborted || isRetryable(readError)) + throw new ObjectJournalSourcePrefixProofUnavailableError(writer); + throw readError; + } + // Only this immutable proof publication is optional. The ownership read + // and any cursor/head CAS above retain their fatal failure boundary. + if (signal.aborted || isRetryable(error)) + throw new ObjectJournalSourcePrefixProofUnavailableError(writer); + throw error; + } + return writer; + } async function publish(value: ObjectJournalHead, etag: string | null, signal?: AbortSignal) { value = headSchema.parse(value); signal = signal @@ -569,6 +640,6 @@ export function createObjectByteJournal(options: ObjectByteJournalOptions) { continuationToken = page.continuationToken; } while (continuationToken); } - return { head, claim, append, close, readRange, remove }; + return { head, claim, append, close, readRange, remove, hasVerifiedSourcePrefix, recordVerifiedSourcePrefix }; } export type ObjectByteJournal = ReturnType; diff --git a/server/src/services/object-run-log-store.test.ts b/server/src/services/object-run-log-store.test.ts index df02e610e73..dc315aae15a 100644 --- a/server/src/services/object-run-log-store.test.ts +++ b/server/src/services/object-run-log-store.test.ts @@ -47,6 +47,7 @@ function memory() { }; return { provider, + objects, puts: () => puts, offline: (value: boolean) => { unavailable = value; @@ -62,6 +63,215 @@ const event = (seq: number) => ({ }); describe("S3 run log store", () => { + it("awaits a successor flush started by another drain waiter before finalizing", async () => { + const m = memory(), store = createObjectRunLogStore({ provider: m.provider, keyPrefix: "logs", flushMs: 1000, + segmentBytes: 1024, assertWriterAuthority: async () => undefined }); + const handle = await store.begin(input), put = m.provider.putObjectConditional!.bind(m.provider); + let firstEntered!: () => void, secondEntered!: () => void, releaseFirst!: () => void, releaseSecond!: () => void; + const firstStarted = new Promise(resolve => { firstEntered = resolve; }); + const secondStarted = new Promise(resolve => { secondEntered = resolve; }); + const firstGate = new Promise(resolve => { releaseFirst = resolve; }); + const secondGate = new Promise(resolve => { releaseSecond = resolve; }); + let publications = 0; + m.provider.putObjectConditional = async value => { + if (value.objectKey.endsWith("/head.json") && Buffer.isBuffer(value.body)) { + const head = JSON.parse(value.body.toString()); + if (!head.closed && head.end > 0) { + publications++; + if (publications === 1) { firstEntered(); await firstGate; } + else if (publications === 2) { secondEntered(); await secondGate; } + } + } + return put(value); + }; + const first = await store.enqueue!(handle, { ...event(1), chunk: "first ".repeat(200) }); + const firstCommitted = first.committed.catch(error => error); + await firstStarted; + const second = await store.enqueue!(handle, { ...event(2), chunk: "second" }); + const secondCommitted = second.committed.catch(error => error); + let finalized = false; + const finalizing = store.finalize(handle).then(result => { finalized = true; return result; }); + releaseFirst(); + await secondStarted; + await new Promise(resolve => setImmediate(resolve)); + const finalizedBeforeSecondCommit = finalized; + releaseSecond(); + const summary = await finalizing; + const committed = await Promise.all([firstCommitted, secondCommitted]); + const content = (await store.read(handle)).content; + expect(finalizedBeforeSecondCommit).toBe(false); + expect(committed.every(value => typeof value === "number")).toBe(true); + expect(summary.bytes).toBe(Buffer.byteLength(content)); + expect(content.trim().split("\n").map(line => JSON.parse(line).seq)).toEqual([1, 2]); + }); + + it("rejects outer records exceeding 8MiB without losing later bounded appends", async () => { + const m = memory(), store = createObjectRunLogStore({ provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }); + const handle = await store.begin(input); + await expect(store.append(handle, { ...event(1), chunk: "x".repeat(8 * 1024 * 1024) })) + .rejects.toThrow("Object run log record exceeds pending-byte limit"); + await store.append(handle, event(1)); + const content = (await store.read(handle)).content; + expect(content.trim().split("\n")).toHaveLength(1); + expect((await store.finalize(handle)).bytes).toBe(Buffer.byteLength(content)); + }); + + it("keeps live byte appends deliverable after a proof-only outage and requires cold prefix verification", async () => { + const m = memory(), options = { provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }; + const put = m.provider.putObjectConditional!.bind(m.provider); + let proofUnavailable = false, proofFailures = 0; + m.provider.putObjectConditional = async value => { + if (proofUnavailable && value.objectKey.includes("/objects/source-prefix-proof-v1-")) { + proofFailures++; + throw Object.assign(new Error("proof storage unavailable"), { $metadata: { httpStatusCode: 503 } }); + } + return put(value); + }; + const store = createObjectRunLogStore(options), handle = await store.begin(input); + await store.recordVerifiedSourcePrefix!(handle, 0); + proofUnavailable = true; + const first = await store.append(handle, { ...event(1), sourceCursor: 2, preservesSourceCoverage: true }) + .catch(error => error); + // The existing byte/index/head publication succeeded despite the proof PUT failure. + expect((await store.read(handle)).content.trim().split("\n")).toHaveLength(1); + proofUnavailable = false; + const second = await store.append(handle, { ...event(2), sourceCursor: 5, preservesSourceCoverage: true }) + .catch(error => error); + const summary = await store.finalize(handle); + const cold = createObjectRunLogStore(options), resumed = await cold.begin(input); + const content = (await cold.read(resumed)).content; + expect(resumed.initialSourceCursor).toBe(5); + // Absence selects the maintained consumer's mandatory full source-prefix scan. + expect(resumed.initialSourcePrefixVerified).toBe(false); + proofUnavailable = true; + // A complete legacy proof can advance the old max cursor before its optional + // proof PUT fails. The public recorder must retain that known committed head. + await cold.recordVerifiedSourcePrefix!(resumed, 8); + expect(resumed.initialSourcePrefixVerified).toBe(false); + proofUnavailable = false; + const third = await cold.append(resumed, { ...event(3), sourceCursor: 11, preservesSourceCoverage: true }); + await cold.finalize(resumed); + const final = await store.begin(input); + const finalContent = (await store.read(final)).content; + await store.finalize(final); + expect(proofFailures).toBeGreaterThan(0); + expect(first).toBeTypeOf("number"); + expect(second).toBeTypeOf("number"); + expect(third).toBeTypeOf("number"); + expect(summary.bytes).toBe(Buffer.byteLength(content)); + expect(finalContent.trim().split("\n").map(line => JSON.parse(line).seq)).toEqual([1, 2, 3]); + expect(final.initialSourceCursor).toBe(11); + expect(final.initialSourcePrefixVerified).toBe(false); + }); + + it.each(["internal-deadline", "caller-abort"] as const)("distinguishes proof %s after the byte head committed", async kind => { + const m = memory(), caller = new AbortController(); + const options = { provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }; + const store = createObjectRunLogStore(options), handle = await store.begin({ ...input, signal: caller.signal }); + await store.recordVerifiedSourcePrefix!(handle, 0); + const put = m.provider.putObjectConditional!.bind(m.provider); + const deadline = new AbortController(); + let entered!: () => void; + const proofStarted = new Promise(resolve => { entered = resolve; }); + m.provider.putObjectConditional = async value => { + if (!value.objectKey.includes("/objects/source-prefix-proof-v1-")) return put(value); + entered(); + return new Promise((_resolve, reject) => { + if (value.signal!.aborted) reject(value.signal!.reason); + else value.signal!.addEventListener("abort", () => reject(value.signal!.reason), { once: true }); + }); + }; + const timeout = vi.spyOn(AbortSignal, "timeout").mockReturnValue(deadline.signal); + let first: unknown; + const callerReason = new Error("caller revoked writer"); + try { + const pending = store.append(handle, { ...event(1), sourceCursor: 2, preservesSourceCoverage: true }) + .catch(error => error); + await proofStarted; + if (kind === "internal-deadline") deadline.abort(new DOMException("proof deadline", "TimeoutError")); + else caller.abort(callerReason); + first = await pending; + } finally { timeout.mockRestore(); m.provider.putObjectConditional = put; } + const second = await store.append(handle, { ...event(2), sourceCursor: 5, preservesSourceCoverage: true }) + .catch(error => error); + const summary = await store.finalize(handle); + const cold = createObjectRunLogStore(options), resumed = await cold.begin(input); + await cold.finalize(resumed); + expect(resumed.initialSourcePrefixVerified).toBe(false); + if (kind === "internal-deadline") { + expect(first).toBeTypeOf("number"); + expect(second).toBeTypeOf("number"); + expect(summary.bytes).not.toBeNull(); + expect(resumed.initialSourceCursor).toBe(5); + } else { + expect(first).toBe(callerReason); + expect(second).toBe(callerReason); + expect(summary.bytes).toBeNull(); + expect(resumed.initialSourceCursor).toBe(2); + } + }); + + it("keeps an unknown head publication failure fatal", async () => { + const m = memory(), store = createObjectRunLogStore({ provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }); + const handle = await store.begin(input); + await store.recordVerifiedSourcePrefix!(handle, 0); + const put = m.provider.putObjectConditional!.bind(m.provider); + m.provider.putObjectConditional = async value => { + if (value.objectKey.endsWith("/head.json")) throw new Error("unknown head publication failure"); + return put(value); + }; + await expect(store.append(handle, { ...event(1), sourceCursor: 2, preservesSourceCoverage: true })) + .rejects.toThrow("unknown head publication failure"); + await expect(store.append(handle, { ...event(2), sourceCursor: 5, preservesSourceCoverage: true })) + .rejects.toThrow("unknown head publication failure"); + expect((await store.read(handle)).content).toBe(""); + await store.finalize(handle); + }); + + it("binds source proof to exact immutable bytes and invalidates it on ordinary appends", async () => { + const m = memory(), options = { provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }; + const store = createObjectRunLogStore(options), handle = await store.begin(input); + expect(handle.initialSourcePrefixVerified).toBe(false); + await store.recordVerifiedSourcePrefix!(handle, 0); + await store.append(handle, { ...event(1), sourceCursor: 2, preservesSourceCoverage: true }); + await store.finalize(handle); + const replacement = createObjectRunLogStore(options), verified = await replacement.begin(input); + expect(verified.initialSourceCursor).toBe(2); + expect(verified.initialSourcePrefixVerified).toBe(true); + const head = JSON.parse([...m.objects].find(([key]) => key.endsWith("/head.json"))![1].toString()); + expect(Object.keys(head).sort()).toEqual([ + "cleanupAfter", "closed", "deleted", "end", "generation", "owner", "root", "roots", "sequence", "sourceCursor", "v", + ]); + // An older/generic caller cannot carry the attestation across new bytes, + // even when it reuses the old max cursor or calls its payload a diagnostic. + await replacement.append(verified, { ...event(2), sourceCursor: 2, + chunk: '{"type":"paperclip.prp.event","event":{"duplicate":true}}' }); + await replacement.finalize(verified); + const legacy = await store.begin(input); + expect(legacy.initialSourceCursor).toBe(2); + expect(legacy.initialSourcePrefixVerified).toBe(false); + await store.finalize(legacy); + }); + + it("fails closed when an existing exact-prefix proof is malformed or changed", async () => { + const m = memory(), options = { provider: m.provider, keyPrefix: "logs", flushMs: 1, + assertWriterAuthority: async () => undefined }; + const store = createObjectRunLogStore(options), handle = await store.begin(input); + await store.recordVerifiedSourcePrefix!(handle, 0); + await store.append(handle, { ...event(1), sourceCursor: 2, preservesSourceCoverage: true }); + await store.finalize(handle); + const proofs = [...m.objects.keys()].filter(key => key.includes("/objects/source-prefix-proof-v1-")); + expect(proofs.length).toBeGreaterThan(0); + for (const key of proofs) m.objects.set(key, Buffer.from('{"schema":"changed-proof"}')); + await expect(createObjectRunLogStore(options).begin(input)) + .rejects.toThrow("object_journal_source_prefix_proof_invalid"); + }); + it("batches concurrent appends, confirms durability, and resumes offsets/sequence on a replacement", async () => { const m = memory(), options = { diff --git a/server/src/services/object-run-log-store.ts b/server/src/services/object-run-log-store.ts index e8ca21fe6ba..ddff39f39b4 100644 --- a/server/src/services/object-run-log-store.ts +++ b/server/src/services/object-run-log-store.ts @@ -2,10 +2,11 @@ import { beginIdleTrackedWork } from "./task-admission.js"; import { createHash, randomUUID } from "node:crypto"; import type { StorageProvider } from "../storage/types.js"; import type { RunLogStore, RunLogHandle, RunLogBeginInput } from "./run-log-store.js"; -import { createObjectByteJournal, type ObjectJournalWriter } from "./object-byte-journal.js"; +import { createObjectByteJournal, ObjectJournalSourcePrefixProofUnavailableError, type ObjectJournalWriter } from "./object-byte-journal.js"; +import { MAX_RUN_LOG_RECORD_BYTES } from "./run-log-record-limits.js"; const MAX_SEGMENT_BYTES = 1024 * 1024; -const MAX_PENDING_BYTES = 8 * MAX_SEGMENT_BYTES; +const MAX_PENDING_BYTES = MAX_RUN_LOG_RECORD_BYTES; const MAX_READ_BYTES = 4 * MAX_SEGMENT_BYTES; export interface ObjectRunLogStoreOptions { provider: StorageProvider; @@ -32,6 +33,9 @@ interface WriterState { closed: boolean; failure?: unknown; signal?: AbortSignal; + sourcePrefixVerified: boolean; + coverageEligible: boolean; + admittedSourceCursor: number; } export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunLogStore { @@ -103,8 +107,7 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL } if (state.flushing) { await state.flushing; - if (state.pending.length) return flush(state); - return; + return flush(state); } if (state.failure) throw state.failure; if (!state.pending.length) return; @@ -127,6 +130,20 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL state.writer.head.sourceCursor, ), ); + if (state.sourcePrefixVerified) { + try { + state.writer = await state.journal.recordVerifiedSourcePrefix( + state.writer, state.writer.head.sourceCursor, state.signal, + ); + } catch (error) { + if (!(error instanceof ObjectJournalSourcePrefixProofUnavailableError)) throw error; + // The byte/index/head append is already committed. Lose only the + // optional provenance optimization; later appends remain deliverable. + state.writer = error.writer; + state.sourcePrefixVerified = false; + state.coverageEligible = false; + } + } for (const item of batch) item.resolve(item.bytes.length); } catch (error) { state.failure = error; @@ -196,6 +213,12 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL if (state.closed) throw new Error("Object run log writer is closed"); state.signal?.throwIfAborted(); if (state.failure) throw state.failure; + if (event.preservesSourceCoverage !== true || event.sourceCursor !== undefined && + (!Number.isSafeInteger(event.sourceCursor) || event.sourceCursor <= state.admittedSourceCursor)) { + state.sourcePrefixVerified = false; + state.coverageEligible = false; + } + state.admittedSourceCursor = Math.max(state.admittedSourceCursor, event.sourceCursor ?? 0); state.pendingBytes += bytes.length; totalPendingBytes += bytes.length; const finishIdle = beginIdleTrackedWork(); @@ -228,6 +251,7 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL assertAuthority: () => options.assertWriterAuthority(input), signal: input.signal, }); + const sourcePrefixVerified = await store.hasVerifiedSourcePrefix(writer.head, input.signal); const handle: RunLogHandle = { store: "s3_segments", logRef, @@ -235,6 +259,7 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL initialBytes: writer.head.end, initialSequence: writer.head.sequence, initialSourceCursor: writer.head.sourceCursor, + initialSourcePrefixVerified: sourcePrefixVerified, }; writers.set(handle, { journal: store, @@ -243,6 +268,9 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL pendingBytes: 0, closed: false, signal: input.signal, + sourcePrefixVerified, + coverageEligible: true, + admittedSourceCursor: writer.head.sourceCursor, }); return handle; }, @@ -255,6 +283,39 @@ export function createObjectRunLogStore(options: ObjectRunLogStoreOptions): RunL if (!state) throw new Error("Object run log writer not found"); await flush(state); }, + async recordVerifiedSourcePrefix(handle, sourceCursor) { + const state = writers.get(handle); + if (!state || state.closed) throw new Error("Object run log writer is closed"); + if (!state.coverageEligible) throw new Error("native_log_source_prefix_changed"); + await flush(state); + if (!state.coverageEligible) throw new Error("native_log_source_prefix_changed"); + // Serialize metadata publication with byte flushes, including diagnostics + // admitted while the one-time source proof is being recorded. + state.flushing = (async () => { + try { + let proofUnavailable = false; + try { + state.writer = await state.journal.recordVerifiedSourcePrefix(state.writer, sourceCursor, state.signal); + } catch (error) { + if (!(error instanceof ObjectJournalSourcePrefixProofUnavailableError)) throw error; + state.writer = error.writer; + proofUnavailable = true; + } + if (!state.coverageEligible) throw new Error("native_log_source_prefix_changed"); + state.sourcePrefixVerified = !proofUnavailable; + if (proofUnavailable) state.coverageEligible = false; + state.admittedSourceCursor = Math.max(state.admittedSourceCursor, sourceCursor); + handle.initialSourcePrefixVerified = state.sourcePrefixVerified; + handle.initialSourceCursor = sourceCursor; + handle.initialBytes = state.writer.head.end; + handle.initialSequence = state.writer.head.sequence; + } finally { + state.flushing = undefined; + schedule(state); + } + })(); + await state.flushing; + }, async finalize(handle, finalizeOptions) { const state = writers.get(handle); if (!state) throw new Error("Object run log writer not found"); diff --git a/server/src/services/run-log-record-limits.ts b/server/src/services/run-log-record-limits.ts new file mode 100644 index 00000000000..2872a7ddeeb --- /dev/null +++ b/server/src/services/run-log-record-limits.ts @@ -0,0 +1,2 @@ +/** Maximum encoded outer NDJSON record, including its newline. */ +export const MAX_RUN_LOG_RECORD_BYTES = 8 * 1024 * 1024; diff --git a/server/src/services/run-log-store.ts b/server/src/services/run-log-store.ts index 05dfcfa0e9f..0c90321953a 100644 --- a/server/src/services/run-log-store.ts +++ b/server/src/services/run-log-store.ts @@ -22,6 +22,8 @@ export interface RunLogHandle { initialBytes?: number; initialSequence?: number; initialSourceCursor?: number; + /** Exact immutable prefix has a durable source-coverage proof, not just a max cursor. */ + initialSourcePrefixVerified?: boolean; } export interface RunLogReadOptions { @@ -68,13 +70,17 @@ export interface RunLogStore { begin(input: RunLogBeginInput): Promise; append( handle: RunLogHandle, - event: { stream: "stdout" | "stderr" | "system"; chunk: string; ts: string; seq?: number; sourceCursor?: number }, + event: { stream: "stdout" | "stderr" | "system"; chunk: string; ts: string; seq?: number; sourceCursor?: number; + /** Caller proved this is ordered canonical output or a non-native diagnostic. */ + preservesSourceCoverage?: boolean }, ): Promise; enqueue?( handle: RunLogHandle, event: Parameters[1], ): Promise<{ committed: Promise }>; flush?(handle: RunLogHandle): Promise; + /** Record the caller's complete ordered source-prefix proof without changing log bytes. */ + recordVerifiedSourcePrefix?(handle: RunLogHandle, sourceCursor: number): Promise; finalize(handle: RunLogHandle, options?: { computeDigest?: boolean }): Promise; read(handle: RunLogHandle, opts?: RunLogReadOptions): Promise; // Optional so existing fakes/fixtures keep compiling: uploads every dirty