diff --git a/doc/architecture/runner-cursor-capabilities.md b/doc/architecture/runner-cursor-capabilities.md index 545211f6126..18c718e583f 100644 --- a/doc/architecture/runner-cursor-capabilities.md +++ b/doc/architecture/runner-cursor-capabilities.md @@ -1,6 +1,6 @@ # Cursor ACP capability inventory -Evidence date: 2026-09-28. Candidate: `2026.09.26-dd393fe`. This profile is **not live-qualified**. One authorized task-context prompt on the initial free account returned an upgrade requirement, invoked no semantic tools, and supplied no usage receipt. Its cost is unknown; the account dashboard remained unchanged at coarse precision. The user then selected another account, whose authenticated catalog and exact model selection passed without a prompt. Local semantic execution, restrictive permission enforcement, precise usage, and Daytona execution remain required qualification gates. +Evidence date: 2026-09-28. Candidate: `2026.09.26-dd393fe`. This profile is **not live-qualified**. One authorized task-context prompt on the initial free account returned an upgrade requirement, invoked no semantic tools, and supplied no usage receipt. Its cost is unknown; the account dashboard remained unchanged at coarse precision. The user then selected another account, whose exact-model local Runner Eval passed task-context and history tools with clean terminal settlement. Its dashboard attributed 56K rounded tokens to included usage and no incremental charge; ACP still supplied no token or dollar receipt. Product E2E, native interactions, restrictive permissions, recovery, and Daytona execution remain required qualification gates. The reference is the runner's Codex app-server integration and its closed thread-item inventory in `src/provider-events.ts`. Cursor ACP and its private extension methods are the transport; the legacy Cursor adapter is unchanged. @@ -84,18 +84,18 @@ Three real ACP stream tests prove child lifecycle/transcript preservation before ## Integrated pack and offline launch evidence -The full `build-provider-pack.mjs --candidate-providers=cursor` path passed on source `a92d06ca5940a42d45cba937f19ba7e7e9c03018` (foundation includes upstream master `14795136f56c11ed83dc754791945bb5a0b8f7fd`). It used standalone Node, pnpm 9.15.4, a fresh production deployment and the pinned vendor archive. The build checked portable Node relocation, fresh ACPX import and complete Cursor materialization. The retained manifest is `packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json`; it contains only relative paths and digests. +The full `build-provider-pack.mjs --candidate-providers=cursor` path passed on source `01959b8a602683f13706807983f02c3cba9d36a0` (foundation includes upstream master `14795136f56c11ed83dc754791945bb5a0b8f7fd`). It used standalone Node, pnpm 9.15.4, a fresh production deployment and the pinned vendor archive. The build checked portable Node relocation, fresh ACPX import and complete Cursor materialization. The retained manifest is `packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json`; it contains only relative paths and digests. -- Pack digest: `sha256:3d36acd9adcfe049fdc30b93ee50f8ce35d59938362eb0c497b4e6b4fbcac028`. +- Pack digest: `sha256:f0b622e9151c1c0886e6220c48ea71993b65887baa88b1600b27462074748ddb`. - Cursor declaration: `sha256:1157a5d071abbd57ab132f22bace75c65e84cc47a045b0023475488755e14899`. - macOS ARM64 closure: `sha256:77394184a89b0e7384971181da19c3c82d83a399b04e7944b3f94fe3d7e62b25`. - Resolved dependency lock: `sha256:ec689ad9c31aa2004c7c2c39889764d55897ac2e6d899c8f059d9c23b082c2c8`, also the reviewed Daytona build digest for this branch. This digest was resolved from the clean tracked lock with the exact Docker resolution-only command. The frozen install retained it. Image creation rejects a different digest before execution. `provider-pack-offline-proof.json` records a real launch through the generic profile installation registry from the pack’s verified native closure and retained snapshot, using private directories and no credentials. ACP v1 initialize succeeds. The correct `cursor/list_available_models`, `session/list` and `session/new` methods return authentication-required; `session/fork` and `session/resume` return method-not-found. The process produced no stderr, was explicitly terminated after these probes, and its lease closed. The earlier discovery fixture’s `_cursor/list_available_models` probe used an incorrect method prefix; this later probe corrects that uncertainty without changing the original evidence. -After the final foundation rebase to `7721662f2`, the TypeScript/verified-sidecar build and all 177 targeted cases passed: Cursor normalization/policy/artifacts, credential bindings, the durable launcher's actual process specification, candidate backend admission, and sidecar behavior. The actual process-launch regressions verify explicit candidate credentials and their marker survive the final closed allowlist; ambient credentials and caller-supplied markers cannot select themselves. The prior source `f09a9a3f8` passed all 47 CI jobs after one retry for runner shutdown and a wall-clock rate-limit case, plus Greptile 5/5; it also passed 29 installed ACPX/materializer Node cases and 6 Daytona image-content cases. These prior results remain historical, distinct from the final source proof. +At the prior foundation checkpoint `7721662f2`, the TypeScript/verified-sidecar build and all 177 targeted cases passed: Cursor normalization/policy/artifacts, credential bindings, the durable launcher's actual process specification, candidate backend admission, and sidecar behavior. The actual process-launch regressions verify explicit candidate credentials and their marker survive the final closed allowlist; ambient credentials and caller-supplied markers cannot select themselves. The prior source `f09a9a3f8` passed all 47 CI jobs after one retry for runner shutdown and a wall-clock rate-limit case, plus Greptile 5/5; it also passed 29 installed ACPX/materializer Node cases and 6 Daytona image-content cases. These prior results remain historical, distinct from the final source proof. -The fresh pack/probe above binds the final runtime bytes, including the actual-spawn credential fix and preservation of actual usage receipts on terminal provider failure; previous pack evidence remains in Git history. Its explicit offline factory model sentinel is not an authenticated model selection; no ACP prompt was sent. Daytona content identity includes the candidate selection, Cursor materializer and distribution manifest. This is local macOS ARM64 packaging/initialization evidence only. It does not qualify Linux execution, a Daytona image build/run, authenticated model work, permissions, or dollar accounting. No screenshot is claimed for these headless tests. That offline probe submitted no prompts and incurred no model usage. Subsequent authenticated attempts are recorded separately below. +The current pack/probe binds foundation `a589381f9`, including candidate admission, biller attribution, explicit unavailable usage, actual-spawn credential binding, and preservation of usage receipts on terminal provider failure. The verified TypeScript build, 56 Cursor/sidecar/eval-provider tests, 67 shared live/eval tests, and 25 mixed-usage contract tests passed during these qualification fixes. Earlier pack evidence remains in Git history. Its explicit offline factory model sentinel is not an authenticated model selection; no ACP prompt was sent. Daytona content identity includes the candidate selection, Cursor materializer and distribution manifest. This is local macOS ARM64 packaging/initialization evidence only. It does not qualify Linux execution, a Daytona image build/run, authenticated model work, permissions, or dollar accounting. No screenshot is claimed for these headless tests. That offline probe submitted no prompts and incurred no model usage. Subsequent authenticated attempts are recorded separately below. ## Authenticated discovery evidence @@ -111,6 +111,8 @@ Credential setup uses [Cursor's documented browser login](https://cursor.com/doc The provider returned only an upgrade requirement and then normal completion. Source inspection of pinned `5672.index.js` confirms that actionable authentication/entitlement errors are rendered as ordinary assistant text and lose their typed failure before ACP settlement. No text-matching terminal heuristic is used. This is a P1 native-wrapper gap: preserve typed errors upstream or through a verified owned hook. The semantic oracle must still fail a response that did not invoke the required tool. +The replacement-account attempt passed all four canonical `get-task-context` checks at source `01959b8a602683f13706807983f02c3cba9d36a0`, using newly rebuilt daemon source `f77ae83aeb6d802c73f1c955760017ae272eba29`. Both `get_task_context` and `get_task_history` returned successful authenticated semantic results. It took 29.291 seconds and exited cleanly. The Usage page showed a new `gpt-5.6-luna-medium` row at 19:28:55 UTC with 56K tokens, marked Included. Incremental cash was zero for that row; metered dollars remain unavailable. A conservative $0.07 list-price bound assumes at most 57K rounded tokens at the maximum listed $1.20/M rate and is not an invoice amount. There was no retry. + The first attempt also exposed the shared live-eval layer's rejection of missing usage. The foundation now retains explicit unavailable-usage records for diagnostic candidates, leaves the numeric receipt ledger empty, preserves the response for grading, and keeps unknown aggregate costs unknown across mixed turns. This fix does not retroactively turn the retained failed attempt into a pass. [Cursor's Grok Bot billing documentation](https://cursor.com/help/grok-bot/plans) says linking SuperGrok grants Grok Bot usage while leaving the Cursor plan unchanged. [Cursor's pricing page](https://cursor.com/pricing) lists Composer for free Hobby and frontier models for paid plans. These documents and model-list presence do not establish entitlement for a particular CLI prompt. The operator selected a replacement Pro+ account; its exact Luna configuration was echoed successfully, with no automatic model substitution. diff --git a/packages/paperclip-runner/test/fixtures/cursor-acp/authenticated-qualification-attempts.json b/packages/paperclip-runner/test/fixtures/cursor-acp/authenticated-qualification-attempts.json index 2a33acb0ccd..b97e0352c42 100644 --- a/packages/paperclip-runner/test/fixtures/cursor-acp/authenticated-qualification-attempts.json +++ b/packages/paperclip-runner/test/fixtures/cursor-acp/authenticated-qualification-attempts.json @@ -68,6 +68,91 @@ }, "dashboardLimitation": "Aggregate display unchanged at coarse precision; this does not prove zero metered usage or zero charge." } + }, + { + "id": "cursor-new-account-first-20260928", + "accountContext": "operator-selected replacement Pro+ account", + "case": "get-task-context", + "runnerSourceRevision": "01959b8a602683f13706807983f02c3cba9d36a0", + "providerPackDigest": "sha256:f0b622e9151c1c0886e6220c48ea71993b65887baa88b1600b27462074748ddb", + "runnerPackageSha256": "75ddd8bf9dd474a01df0879ea1ceda6d015e08a3364dc21c38ddfc9e65a60ec0", + "runnerdSha256": "986060810ba7377c6ddd64a5d89e322d0a434e1a9c80400e6d4acf5934bfc421", + "runnerdSourceRevision": "f77ae83aeb6d802c73f1c955760017ae272eba29", + "evalRevision": "b01676fdb7a2783f7b3635a90ba9583041e86338", + "requestedModel": "gpt-5.6-luna[context=272k,reasoning=medium,fast=false]", + "observedModel": { + "id": "gpt-5.6-luna[context=272k,reasoning=medium,fast=false]", + "provider": "cursor" + }, + "startedAt": "2026-09-28T19:28:46.976Z", + "finishedAt": "2026-09-28T19:29:16.268Z", + "durationMs": 29291, + "limits": { + "turnTimeoutMs": 60000, + "maxAgentTurns": 1, + "maxEstimatedCostNanodollars": 500000000 + }, + "automaticRetries": 0, + "nativeTerminalStatus": "completed", + "assistantText": "I\u2019m assigned PAP-101, \u201cAdd task-context orientation eval,\u201d under PAP-100.\n\nThe immediate next step is to inspect the runner/evaluation harness and implement the smallest end-to-end check proving an agent reads its assigned task context before acting, while preserving inspectable evidence. The manager specifically asked to start with that smallest check. No task completion or blocking action is authorized yet.", + "semanticResults": [ + { + "operationId": "get_task_context", + "ok": true + }, + { + "operationId": "get_task_history", + "ok": true + } + ], + "runnerResult": "passed", + "oracleChecks": [ + { + "id": "context-call", + "passed": true + }, + { + "id": "terminal-completed", + "passed": true + }, + { + "id": "transcript-complete", + "passed": true + }, + { + "id": "mock-only", + "passed": true + } + ], + "scoreDigest": "sha256:0e39e3067a928b9ff4da7a70426f2e643bf9e869bbee514de8dd6a3661bc0942", + "networkEvidence": { + "childPaperclipEnvironmentKeys": [], + "realPaperclipRequests": 0 + }, + "cleanup": { + "runnerExited": true, + "runnerExitCode": 0 + }, + "usage": { + "submittedPrompts": 1, + "nativeReceipt": null, + "tokenUsage": null, + "costUsd": null, + "coverage": "provider usage unavailable; dashboard row attributed" + }, + "billing": { + "source": "parent-observed account Usage row after bounded attempt", + "observedRequestAt": "2026-09-28T19:28:55Z", + "modelLabel": "gpt-5.6-luna-medium", + "tokensDisplay": "56K", + "usageType": "Included", + "chargeDisplay": "Included", + "incrementalCashChargeUsd": 0, + "meteredCostUsd": null, + "conservativeListCostUpperBoundUsd": 0.07, + "listCostBoundBasis": "At most 57,000 rounded-display tokens at the maximum listed $1.20 per million token rate; this is not a billing receipt." + }, + "scope": "Runner Eval: authenticated local native-MCP semantic tools on mock control plane; not Product E2E or native interaction/recovery/Daytona qualification" } ], "newAccountDiscovery": { diff --git a/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json b/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json index bd4a556c091..e02faf48b2b 100644 --- a/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json +++ b/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-darwin-arm64.json @@ -1,6 +1,6 @@ { "schema": "paperclip-runner/remote-provider-pack/v1", - "digest": "sha256:3d36acd9adcfe049fdc30b93ee50f8ce35d59938362eb0c497b4e6b4fbcac028", + "digest": "sha256:f0b622e9151c1c0886e6220c48ea71993b65887baa88b1600b27462074748ddb", "payload": { "pins": { "nodeMinimum": "24.11.0", @@ -14,9 +14,9 @@ "platform": "darwin", "architecture": "arm64" }, - "runnerSourceRevision": "a92d06ca5940a42d45cba937f19ba7e7e9c03018", - "distDigest": "sha256:78fc5189d6f8a441aa1060dc968b09cd423f03fb039ef33b17568bb44b7f6da6", - "bridgeDigest": "sha256:d58c15293fd44bad94d222b982da989af54621150c1f16fa7da53beb3bb16f9d", + "runnerSourceRevision": "01959b8a602683f13706807983f02c3cba9d36a0", + "distDigest": "sha256:6ac11b85a406f041e13a9896362cd78ebea5e9edef97527bffb7a8360f6a10bb", + "bridgeDigest": "sha256:e444f448c6fe3c7e0246dc0cc1dcb98c2f735479ba5576f9a9bbb7a3137061c1", "acpxProfileDigests": { "claude": "sha256:9d73d1f0f121fb96cc8badb28c22d5bff02d8582eb2e40360a81c189e1b9422a", "codex": "sha256:c4538599d1ab767db5dff50934f13bb5ba313a59d9c4a83e993fac4617ea63d3" @@ -54,7 +54,7 @@ }, "acpxSidecar": { "path": "dist/cli/acpx-runtime-sidecar.cjs", - "sha256": "sha256:b0c2c42374f8f6dc7a9a4b3a31f3cc94cd8e9e74a5934441188c2ec1fc33e9f9" + "sha256": "sha256:f688c95784dc8d0422c8610251263e374e765d28d22b2f5eeeda509f6155e3e5" } } } diff --git a/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-offline-proof.json b/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-offline-proof.json index 056136eb865..d89969c13eb 100644 --- a/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-offline-proof.json +++ b/packages/paperclip-runner/test/fixtures/cursor-acp/provider-pack-offline-proof.json @@ -1,8 +1,8 @@ { "schema": "paperclip-cursor-offline-pack-proof/v1", - "capturedAt": "2026-09-28T18:36:20.637Z", - "runnerSourceRevision": "a92d06ca5940a42d45cba937f19ba7e7e9c03018", - "packDigest": "sha256:3d36acd9adcfe049fdc30b93ee50f8ce35d59938362eb0c497b4e6b4fbcac028", + "capturedAt": "2026-09-28T19:28:15.778Z", + "runnerSourceRevision": "01959b8a602683f13706807983f02c3cba9d36a0", + "packDigest": "sha256:f0b622e9151c1c0886e6220c48ea71993b65887baa88b1600b27462074748ddb", "target": { "platform": "darwin", "architecture": "arm64"