mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users can stop a run and send another message on the same task.
> - Remote runners need evidence from their sandbox provider that
execution stopped.
> - Local process checks cannot prove that a remote process exited.
> - This pull request records provider stop receipts and uses them for
conversation admission.
> - New user messages can proceed after confirmed cleanup without
repeating interrupted actions.
## Linked Issues or Issue Description
Refs #13237 and #13239. Related: #13163 covers app-restart recovery;
this change covers an explicit stop followed by a new user message.
**What happened?**
A stopped remote Claude ACP task kept its execution hold after Daytona
cleanup succeeded. Native runners also rejected remote process
identities and retained stale session cleanup gates. A message sent
during cleanup could stay deferred after the sandbox stopped.
**Expected behavior**
After the provider confirms that the old execution stopped, a new user
message starts a fresh turn. Pending user messages must not need another
message to trigger admission. Prior action outcomes remain recorded.
**Steps to reproduce**
1. Start a long-running task in Daytona with a legacy Claude ACP or
native ACP runner.
2. Cancel the run while its tool is active.
3. Send a new message immediately, or after cleanup completes.
4. Observe the execution hold despite the old sandbox having stopped.
**Paperclip version or commit**
Reproduced on master at 7b829efdf6. The
branch is rebased on current master.
## What Changed
- Add optional provider stop receipts to sandbox release and destroy
hooks. Old plugins remain compatible.
- Bind receipts to the company, run, lease, and provider resource.
Failed cleanup cannot supply stop authority.
- Acknowledge legacy remote cancellation after confirmed termination.
- Admit native user continuations using remote receipts instead of host
process checks.
- Retire only the settled cleanup owner matching the stopped company,
run, and provider resource. Isolate cleanup gates between remote
sandboxes, including two sandboxes owned by one run.
- Reconsider user messages deferred during remote cleanup through normal
admission, including successful later cleanup retries.
- Preserve receipts through cleanup retries and inline cleanup after
failed startup.
- Permit provider destruction after a terminal remote checkpoint
failure. Busy ownership still blocks destruction.
- Add regression tests and update execution semantics.
- Give the real preview fixture ten seconds for cold startup. Reuse
release-mode Rust artifacts for the filtered parity checks, avoiding a
duplicate debug test build that exhausted CI disk twice; test filters
and assertions are unchanged.
## Verification
- Recursive typecheck and build passed.
- Targeted server, Daytona plugin, and native runtime tests passed. They
cover missing or mismatched receipts, failed cleanup, local process
protection, exact cleanup ownership, and a message sent during cleanup.
- Live Daytona tests passed for legacy Claude ACP, native per-turn,
native warm, and a newly created native runner using disposable
sandboxes. Each original run was cancelled; its explicit follow-up
completed with no execution hold. The disposable case confirmed a new
sandbox after deletion.
- Native tests used the provider's Opus 5 selector, `opus[1m]`, and the
Linux runner bundle from the sandbox image. Existing checkpoint/sync
finalization warnings remained visible before the native follow-ups
reached committed success. This change does not repair those separate
warnings or guarantee recovery of uncheckpointed files.
- A direct live provider test also passed with the final delete-wait
change: the destroy hook returned its receipt only after Daytona
reported the sandbox destroyed. The final Daytona plugin suite passed
all 153 tests; its build passed.
- After rebasing on master, 284 targeted server/plugin tests and 313
native executor tests passed. The native session runtime suite passed
all 128 tests.
- The review regression passed all 145 tests across the continuation,
environment runtime, and pending-cleanup sweep suites. Recursive
typecheck and build passed again after that fix.
- The security review's exact-resource finding is fixed. Cleanup
completion requires the same provider-resource scope used during session
creation. All 128 native runtime tests, 61 server continuation/cleanup
tests, recursive typecheck, and build passed after this fix. The
two-sandboxes-in-one-run regression proves one receipt cannot retire the
other quarantine.
- Greptile reviewed the final commit at 5/5, the security scan passed,
and no review threads remain unresolved. The final native executor suite
also passed all 313 tests.
- The full local suite reached 10,616 passing tests before stopping on
four failures. All four now pass in focused reruns: the final-code
continuation/teardown suites, the attachment suite, and the native
session test after building its required fake-provider binary. The
original full run overlapped source edits and did not reach the
remaining groups; it is not counted as a full-suite pass.
- The preview exposure suite passed all 25 applicable tests (three
Linux-only tests skipped locally) after the startup allowance change.
Both release-mode Rust parity commands passed locally. All final-head PR
checks passed, including full server/workspace/browser test groups, full
native runner verification, build, typecheck, canary dry-run, and the
aggregate gates.
## Risks
- A provider must return a receipt only after confirmed termination.
Incorrect provider claims could permit overlapping execution.
- Older providers without receipts retain the existing hold. Missing
evidence, failed cleanup, active ownership, pauses, approvals, and
budgets still block admission.
- This change preserves unknown action outcomes and old checkpoints. It
does not authorize replay or alter historical runs.
- No database migration or telemetry contract change is required.
## Model Used
OpenAI GPT-6 through Codex, with repository inspection, code execution,
and browser tools. The exact backend revision and context-window size
are not exposed in this session.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run targeted tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
199 lines
15 KiB
JSON
199 lines
15 KiB
JSON
{
|
|
"name": "@paperclipai/paperclip-runner",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"license": "MIT",
|
|
"engines": {
|
|
"node": ">=24.11.0"
|
|
},
|
|
"type": "module",
|
|
"bin": {
|
|
"paperclip-runner-eval-session": "./dist/cli/eval-session.js",
|
|
"paperclip-runner-codex-proxy": "./dist/cli/codex-app-server-unix-proxy.js",
|
|
"paperclip-runner-opencode-proxy": "./dist/cli/opencode-app-server-proxy.js",
|
|
"paperclip-runner-acpx-sidecar": "./dist/cli/acpx-runtime-sidecar.js"
|
|
},
|
|
"exports": {
|
|
".": {
|
|
"types": "./dist/index.d.ts",
|
|
"import": "./dist/index.js"
|
|
},
|
|
"./testing": {
|
|
"types": "./dist/testing.d.ts",
|
|
"import": "./dist/testing.js"
|
|
},
|
|
"./evals": {
|
|
"types": "./dist/evals/index.d.ts",
|
|
"import": "./dist/evals/index.js"
|
|
},
|
|
"./live": {
|
|
"types": "./dist/live/index.d.ts",
|
|
"import": "./dist/live/index.js"
|
|
},
|
|
"./devtools": {
|
|
"types": "./dist/devtools/index.d.ts",
|
|
"import": "./dist/devtools/index.js"
|
|
},
|
|
"./browser": {
|
|
"types": "./dist/browser/index.d.ts",
|
|
"import": "./dist/browser/index.js"
|
|
},
|
|
"./react": {
|
|
"types": "./dist/react/index.d.ts",
|
|
"import": "./dist/react/index.js"
|
|
},
|
|
"./standalone": {
|
|
"types": "./dist/standalone/index.d.ts",
|
|
"import": "./dist/standalone/index.js"
|
|
},
|
|
"./styles.css": "./styles.css"
|
|
},
|
|
"files": [
|
|
"dist",
|
|
"dist-issue-thread",
|
|
"protocol",
|
|
"styles.css",
|
|
"README.md"
|
|
],
|
|
"sideEffects": false,
|
|
"scripts": {
|
|
"build": "pnpm run check:protocol-manifest && pnpm run build:typescript && pnpm run check:capability-contract && pnpm run check:capability-inventory && pnpm run check:protocol-coverage && pnpm run check:semantic-contracts && pnpm run check:runner-workflow-traceability && pnpm run build:binary && node scripts/generate-replay-goldens.mjs --check && node scripts/generate-semantic-action-catalog.mjs --check",
|
|
"build:typescript": "pnpm run ensure:eval-build-deps && pnpm run check:protocol-types && node ./node_modules/typescript/bin/tsc --version && node ./node_modules/typescript/bin/tsc -p tsconfig.json && node ./node_modules/typescript/bin/tsc -p tsconfig.surfaces.json && node scripts/build-verified-provider-entrypoints.mjs",
|
|
"build:rust": "cargo build --manifest-path runner/Cargo.toml --locked --workspace --bins",
|
|
"build:binary": "cargo build --release --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node scripts/stage-runner-binary.mjs",
|
|
"build:provider-pack": "pnpm run build:typescript && node scripts/build-provider-pack.mjs",
|
|
"build:runner-binaries": "cargo build --manifest-path runner/Cargo.toml --locked --workspace --bins",
|
|
"build:browser": "vite build --config vite.config.ts",
|
|
"build:sdk": "vite build --config vite.sdk.config.ts",
|
|
"build:standalone": "vite build --config vite.standalone.config.ts",
|
|
"build:scenarios": "vite build --config vite.scenarios.config.ts && node scripts/check-capability-csp-bundle.mjs",
|
|
"build:issue-thread": "vite build --config vite.issue-thread.config.ts",
|
|
"typecheck": "pnpm run typecheck:typescript && pnpm run typecheck:rust",
|
|
"typecheck:typescript": "pnpm run ensure:eval-build-deps && node --check scripts/protocol-contract.mjs && node --check scripts/generate-protocol-manifest.mjs && node --check scripts/generate-protocol-schema-module.mjs && node --check scripts/generate-acpx-sidecar-contract.mjs && node --check scripts/generate-replay-goldens.mjs && node --check scripts/generate-semantic-action-catalog.mjs && pnpm run check:protocol-types && node ./node_modules/typescript/bin/tsc --version && node ./node_modules/typescript/bin/tsc -p tsconfig.json --noEmit && node ./node_modules/typescript/bin/tsc -p tsconfig.surfaces.json --noEmit",
|
|
"typecheck:rust": "cargo fmt --manifest-path runner/Cargo.toml --all -- --check && cargo check --manifest-path runner/Cargo.toml --locked --workspace",
|
|
"typecheck:browser": "tsc -p tsconfig.browser.json --noEmit",
|
|
"test": "pnpm run test:typescript && pnpm run test:rust",
|
|
"test:typescript": "pnpm run ensure:eval-build-deps && pnpm run build:rust && node --test test/protocol-contract.test.mjs test/acpx-sidecar-contract.test.mjs test/acpx-codex-package-contract.test.mjs scripts/aws-agentcore-provisioning.test.mjs scripts/build-verified-provider-entrypoints.test.mjs scripts/local-provider-smoke-environment.test.mjs scripts/materialize-opencode-binary.test.mjs && vitest run",
|
|
"test:rust": "cargo test --release --manifest-path runner/Cargo.toml --locked --workspace",
|
|
"test:codex": "cargo test --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --test codex_provider",
|
|
"test:durable": "cargo test --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core durable::",
|
|
"test:browser": "pnpm run build:typescript && pnpm run build:runner-binaries && pnpm run build:browser && playwright test --config devtools/browser/playwright.config.ts",
|
|
"test:sdk": "vitest run src/browser/client.test.ts src/browser/transcript-model.test.ts src/react/public-contract.test.tsx",
|
|
"test:scenarios": "vitest run src/scenarios src/live src/semantic-tools/semantic-tools.test.ts src/mock-core/capability-mock-control-plane-adapter.test.ts src/issue-thread devtools/issue-thread/src examples/scenario-explorer",
|
|
"test:browser:sdk": "pnpm run build:typescript && playwright test --config examples/playwright.config.ts",
|
|
"test:browser:scenarios": "playwright test --config examples/playwright.scenarios.config.ts && pnpm run test:browser:issue-thread",
|
|
"test:browser:issue-thread": "pnpm run build:typescript && pnpm run build:issue-thread && playwright test --config devtools/issue-thread/playwright.config.ts",
|
|
"record:sdk:codex": "pnpm run build:typescript && playwright test --config examples/playwright.real.config.ts",
|
|
"generate:protocol-manifest": "node scripts/generate-protocol-manifest.mjs",
|
|
"check:protocol-manifest": "node scripts/generate-protocol-manifest.mjs --check",
|
|
"generate:protocol-types": "node scripts/generate-protocol-schema-module.mjs && node scripts/generate-acpx-sidecar-contract.mjs",
|
|
"check:protocol-types": "node scripts/generate-protocol-schema-module.mjs --check && node scripts/generate-acpx-sidecar-contract.mjs --check",
|
|
"generate:capability-contract": "node scripts/generate-capability-contract.mjs",
|
|
"check:capability-contract": "node scripts/generate-capability-contract.mjs --check",
|
|
"generate:semantic-contracts": "pnpm run build:typescript && node scripts/generate-semantic-contracts.mjs",
|
|
"check:semantic-contracts": "pnpm run build:typescript && node scripts/generate-semantic-contracts.mjs --check",
|
|
"generate:semantic-action-catalog": "pnpm run build:typescript && node scripts/generate-semantic-action-catalog.mjs",
|
|
"check:semantic-action-catalog": "pnpm run build:typescript && node scripts/generate-semantic-action-catalog.mjs --check",
|
|
"check:protocol": "pnpm run typecheck:typescript && pnpm run check:protocol-manifest && pnpm run test:typescript && pnpm run check:replay-goldens",
|
|
"check:runner": "pnpm run typecheck:rust && pnpm run test:rust && pnpm run check:conformance-parity && pnpm run check:replay-parity",
|
|
"check:all": "pnpm run check:eval-kernel && pnpm run check:protocol && pnpm run check:runner && pnpm run check:api-authority",
|
|
"check:api-authority": "node scripts/check-api-authority.mjs",
|
|
"generate:replay-goldens": "pnpm run build:typescript && node scripts/generate-replay-goldens.mjs",
|
|
"check:replay-goldens": "pnpm run build:typescript && node scripts/generate-replay-goldens.mjs --check",
|
|
"check:browser-tokens": "node scripts/check-browser-tokens.mjs",
|
|
"check:forbidden-imports": "node scripts/check-forbidden-imports.mjs",
|
|
"check:tracked-imports": "node scripts/check-tracked-imports.mjs",
|
|
"check:numbered-milestones": "node scripts/check-numbered-milestones.mjs",
|
|
"check:package-boundaries": "node scripts/check-package-boundaries.mjs",
|
|
"check:clean-consumers": "node scripts/check-clean-consumers.mjs",
|
|
"check:eval-kernel": "pnpm --filter @paperclipai/paperclip-eval-kernel test",
|
|
"ensure:eval-build-deps": "pnpm --filter @paperclipai/paperclip-eval-kernel build",
|
|
"generate:capability-inventory": "node scripts/generate-capability-inventory.mjs",
|
|
"generate:protocol-coverage": "pnpm run build:typescript && node scripts/generate-protocol-coverage.mjs",
|
|
"check:protocol-coverage": "node scripts/generate-protocol-coverage.mjs --check",
|
|
"check:capability-inventory": "node scripts/check-capability-inventory.mjs",
|
|
"test:capability-inventory": "node scripts/check-capability-inventory.test.mjs",
|
|
"test:capability-evals": "vitest run src/conformance/capability-eval-suite.test.ts",
|
|
"test:eval-slice": "pnpm run ensure:eval-build-deps && vitest run src/eval",
|
|
"test:runner-workflow-evals": "pnpm run ensure:eval-build-deps && node --test scripts/render-runner-workflow-evalbook.test.mjs && vitest run src/eval/workflow-evals.test.ts src/eval/live-workflow-executor.test.ts",
|
|
"test:runner-protocol-eval-publish": "node --test scripts/runner-protocol-eval-campaign.test.mjs scripts/publish-runner-protocol-eval-history.test.mjs scripts/runner-protocol-eval-metrics.test.mjs scripts/runner-protocol-eval-workflow-security.test.mjs scripts/public-eval-chat.test.mjs",
|
|
"check:runner-workflow-traceability": "pnpm run build:typescript && node scripts/check-runner-workflow-traceability.mjs",
|
|
"report:capability-evals": "pnpm run build:typescript && node scripts/run-capability-eval-suite.mjs",
|
|
"report:capability-live-evals": "pnpm run build:typescript && cargo build --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node scripts/run-capability-live-eval-matrix.mjs",
|
|
"report:runner-workflow-evals": "pnpm run build:typescript && node scripts/run-runner-workflow-evals.mjs",
|
|
"report:runner-live-evals": "pnpm run build:typescript && pnpm run build:runner-binaries && node scripts/run-runner-live-eval-schedule.mjs --mode nightly --execute",
|
|
"report:runner-protocol-eval:catalog": "node scripts/runner-protocol-eval-campaign.mjs catalog",
|
|
"report:runner-protocol-eval:publish": "node scripts/publish-runner-protocol-eval-history.mjs",
|
|
"report:runner-chaos-evals": "pnpm run build:typescript && node scripts/run-runner-live-eval-schedule.mjs --mode chaos",
|
|
"check:conformance-parity": "cargo test --release --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core runs_the_mock_core_path_with_stable_output",
|
|
"check:replay-parity": "cargo test --release --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core replay_fixture_parity",
|
|
"docs:validate": "node scripts/validate-doc-links.mjs",
|
|
"trace:conformance": "pnpm run trace:conformance:rust",
|
|
"trace:conformance:rust": "cargo run --quiet --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin conformance-tracer",
|
|
"trace:conformance:typescript": "pnpm run build:typescript && node dist/tracer/conformance.js",
|
|
"replay:fixture": "pnpm run build:typescript && node dist/cli/replay.js",
|
|
"trace:local-runner": "pnpm run build:typescript && pnpm run build:runner-binaries && node dist/cli/local-runner.js",
|
|
"trace:codex": "pnpm run build:typescript && node dist/cli/codex.js",
|
|
"trace:standalone": "pnpm run build:typescript && node dist/cli/paperclip-adapter.js",
|
|
"trace:live-runner": "pnpm run build:typescript && cargo build --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node dist/cli/live-runner.js",
|
|
"demo:standalone": "pnpm run build:typescript && vite --config vite.standalone.config.ts --host 127.0.0.1 --port 4182",
|
|
"demo:scenarios": "pnpm run build:typescript && vite --config vite.scenarios.config.ts --host 127.0.0.1 --port 4183",
|
|
"console:issue-thread": "pnpm run build:typescript && vite --config vite.issue-thread.config.ts --host 127.0.0.1 --port 4184",
|
|
"aws-agentcore:provision": "bash scripts/aws-agentcore.sh provision",
|
|
"aws-agentcore:probe": "bash scripts/aws-agentcore.sh probe",
|
|
"aws-agentcore:lab": "bash scripts/aws-agentcore.sh lab",
|
|
"aws-agentcore:destroy": "bash scripts/aws-agentcore.sh destroy",
|
|
"test:aws-agentcore-provisioning": "node --test scripts/aws-agentcore-provisioning.test.mjs",
|
|
"smoke:capability:aws-agentcore": "pnpm run build:typescript && cargo build --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node scripts/capability-aws-agentcore-smoke.mjs",
|
|
"demo:live-console": "pnpm run build:typescript && node scripts/live-console-demo-server.mjs",
|
|
"smoke:capability:ui": "pnpm run build:typescript && cargo build --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node scripts/capability-issue-thread-smoke.mjs",
|
|
"smoke:capability:cleanroom": "pnpm run build:typescript && cargo build --manifest-path runner/Cargo.toml --locked -p paperclip-runner-core --bin paperclip-runnerd && node scripts/capability-clean-room-smoke.mjs",
|
|
"smoke:local-provider": "node scripts/run-local-provider-smoke.mjs",
|
|
"console:live-console": "pnpm run build:typescript && vite --config vite.config.ts --host 127.0.0.1 --port 4180",
|
|
"console:sdk": "pnpm run build:typescript && vite --config vite.sdk.config.ts --host 127.0.0.1 --port 4181",
|
|
"browser:dev": "pnpm run build:typescript && pnpm run build:runner-binaries && vite --config vite.config.ts",
|
|
"browser:preview": "vite preview --config vite.config.ts",
|
|
"verify": "pnpm run build && pnpm run typecheck && pnpm run check:replay-goldens && pnpm run test && pnpm run test:sdk && pnpm run test:scenarios && pnpm run check:browser-tokens && pnpm run test:browser && pnpm run test:browser:sdk && pnpm run test:browser:scenarios && pnpm run check:forbidden-imports && pnpm run check:tracked-imports && pnpm run check:numbered-milestones && pnpm run check:package-boundaries && pnpm run check:clean-consumers && pnpm run docs:validate && pnpm run check:conformance-parity && pnpm run check:replay-parity && pnpm run trace:conformance && pnpm run replay:fixture && pnpm run trace:local-runner -- --quiet",
|
|
"verify:rootless": "bash scripts/verify-rootless-linux.sh"
|
|
},
|
|
"dependencies": {
|
|
"@agentclientprotocol/claude-agent-acp": "0.73.0",
|
|
"@agentclientprotocol/codex-acp": "1.6.2",
|
|
"@openai/codex": "0.153.4",
|
|
"acpx": "0.13.1",
|
|
"ajv": "^8.20.0",
|
|
"json-schema-to-ts": "^3.1.1",
|
|
"opencode-ai": "1.18.29",
|
|
"react-markdown": "^10.1.0",
|
|
"remark-gfm": "^4.0.1",
|
|
"smol-toml": "^1.4.2"
|
|
},
|
|
"peerDependencies": {
|
|
"react": ">=18",
|
|
"react-dom": ">=18"
|
|
},
|
|
"peerDependenciesMeta": {
|
|
"react": {
|
|
"optional": true
|
|
},
|
|
"react-dom": {
|
|
"optional": true
|
|
}
|
|
},
|
|
"devDependencies": {
|
|
"@paperclipai/paperclip-eval-kernel": "workspace:*",
|
|
"@playwright/test": "^1.61.1",
|
|
"@types/node": "^24.0.0",
|
|
"@types/react": "^19.2.17",
|
|
"@types/react-dom": "^19.2.5",
|
|
"@vitejs/plugin-react": "^4.7.0",
|
|
"axe-core": "^4.12.1",
|
|
"react": "^19.2.7",
|
|
"react-dom": "^19.2.7",
|
|
"tsx": "^4.23.12",
|
|
"typescript": "^7.0.2",
|
|
"vite": "^6.1.0",
|
|
"vitest": "^4.1.11"
|
|
}
|
|
}
|