mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
300a89ec136d76f4168e739578ddf144bc91ca2f
4053
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
300a89ec13 |
Detect the qualifier-less Claude usage-limit message in quota classification (#12475)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The heartbeat runtime classifies adapter run failures, and the
recovery service uses that classification to decide between automatic
retry, a timed provider-quota wait, and a board escalation
> - The Claude CLI changed its subscription-limit stop message to
"You've hit your limit · resets 2:30am (UTC)", and no quota matcher
knows this qualifier-less wording
> - A limit-hit run therefore classifies as `adapter_failed` (or
`claude_auth_required`), recovery burns its continuation retries against
a hard limit, and the issue blocks with the opaque "No live execution
path" notice instead of waiting for the reset and retrying automatically
> - This pull request teaches the adapter and the recovery service the
new wording, and titles stranded-escalation notices from the classified
run error code so operators see the cause at a glance
> - The benefit is that usage-limit stops self-heal at the provider
reset time, and the notices that do post say "Error: usage limit
reached" or "Error: not logged in to Claude" instead of a generic title
## Linked Issues or Issue Description
No public issue exists; the underlying problem follows the bug template:
**What happened?**
On a staging deployment, an assigned `in_progress` issue hit the Claude
subscription usage limit. The run recorded the error `Claude run failed:
subtype=success: You've hit your limit · resets 2:30am (UTC)`. The
automatic continuation retry failed the same way in 34 seconds with
`errorCode: adapter_failed`. Terminal-run recovery then escalated: the
issue moved to `blocked` with the notice "No live execution path" and a
board-owned recovery action. The notice gave the operator no indication
that the cause was a usage limit with a known reset time.
**Expected behavior**
A usage-limit stop classifies as `provider_quota` with the reset clock
parsed into `retryNotBefore`. The recovery service takes its
provider-quota wait path: a system-owned recovery action that waits for
the reset time and retries the original assignee automatically. If an
escalation notice does post, its title names the classified cause.
**Steps to reproduce**
1. Run a `claude_local` agent on an issue until the Claude subscription
limit is hit, so the CLI result is "You've hit your limit · resets
\<time\> (UTC)".
2. Let terminal-run recovery retry the continuation.
3. Observe the issue block with the "No live execution path" notice
instead of a timed quota wait. `classifyAdapterFailureForRecovery`
returns `null` for the recorded error text; `CLAUDE_PROVIDER_QUOTA_RE`
and `PROVIDER_QUOTA_ERROR_RE` both fail to match it.
## What Changed
- `CLAUDE_PROVIDER_QUOTA_RE` and `CLAUDE_EXTRA_USAGE_RESET_RE`
(claude-local adapter) accept "you've hit your limit" with no qualifier,
alongside the existing "session"/"usage" wordings, so the run classifies
as `provider_quota` and the reset clock lands in `retryNotBefore`.
- `PROVIDER_QUOTA_ERROR_RE` and `isProviderQuotaRecovery` (recovery
service) accept the same wording, so runs recorded before the adapter
fix (errorCode `adapter_failed` with the limit text in the error) also
route to the quota wait.
- `parseProviderQuotaClockReset` parses the "resets 2:30am (UTC)" clock
shape alongside the existing "try again at" shape.
- `buildStrandedRecoveryEscalationNotice` titles the notice from the
source run's classified error code when one is mapped: `provider_quota`
→ "Error: usage limit reached", `claude_auth_required` → "Error: not
logged in to Claude", `acpx_auth_required` → "Error: agent login
required". The raw failure text stays withheld from the issue thread;
only the server-classified code is surfaced. Unmapped codes keep the
existing seed/cause titles.
## Verification
- `pnpm vitest run
packages/adapters/claude-local/src/server/parse.test.ts
server/src/services/recovery/provider-failure-classification.test.ts
server/src/services/recovery/stranded-notice.test.ts` — 72 tests pass,
including 5 new cases that use the exact new CLI message.
- `pnpm vitest run server/src/__tests__/issue-recovery-actions.test.ts
server/src/__tests__/heartbeat-retry-scheduling.test.ts
server/src/__tests__/heartbeat-process-recovery.test.ts` — 189 tests
pass (no reroute regressions from the widened matchers).
- `tsc --noEmit` clean for `@paperclipai/adapter-claude-local` and
`@paperclipai/server`.
## Risks
- Low risk. The regex widenings are additive; every previously matched
wording still matches, and the existing negative test ("Workspace
storage capacity limit reached." stays unclassified) still passes.
- Behavioral shift, intended: an `adapter_failed` run whose error text
is the new limit wording now routes to the silent system-owned quota
wait instead of a board escalation. This matches how the older limit
wordings already behave.
- The notice title change only affects escalations whose source run
carries one of the three mapped error codes; all other notices render
exactly as before.
## Model Used
Claude Fable 5 (`claude-fable-5`, Claude Code CLI, extended thinking
with tool use).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
canary/v2026.831.0-canary.15
|
||
|
|
25cf079ec5 |
feat(runner): add Codex-native application integration (#12591)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package is useful only when the application can start, observe, and recover a native Codex run safely. > - Existing direct adapters must keep their current execution and finalization paths. > - The application boundary therefore needs additive persistence, authorization, coordination, and recovery behind an explicit experimental adapter. > - This pull request adds that Codex-only boundary without activating generalized providers, remote environments, or the later task/SDK surfaces. ## Linked Issues or Issue Description **Subsystem affected** Shared contracts, database persistence, adapter utilities, server native-runtime services, and the experimental Paperclip Runner adapter. **Problem or motivation** The already-landed runner package has a qualified Codex path, but the application needs durable native-run state, guarded runtime selection, authenticated coordination, tool security, finalization, and recovery before the experimental adapter can be exercised safely. **Proposed solution** Add a Codex-only `paperclip_runner` application path behind the existing default-off native-runner setting. Bind native state and coordination to company/run identity, preserve persisted-run recovery, and leave every direct adapter on its existing legacy execution path. **Alternatives considered** The earlier stack boundary introduced a generalized executor and remote-environment lifecycle here. That made this PR depend on implementations in higher PRs and changed reusable sandbox behavior globally. Those pieces are now deferred together to #12592. **Roadmap alignment** ROADMAP.md does not list a conflicting native-runner integration project. This change adds the application boundary for the existing Runner architecture. ## What Changed - Added native run/result/finalization/provider-trace persistence, shared validators, and idempotent migration/replay coverage. - Added guarded Codex-only runtime selection, authenticated PRP coordination, recovery, finalization, and interaction services. - Added run/company-bound tool-gateway authorization, credential redaction, SSRF protections, and replay-safe behavior. - Added the explicit `paperclip_runner` adapter behind the default-off rollout setting. - Preserved legacy answered-question wake projection and direct-adapter execution/finalization paths. - Hardened cancellation so only owned in-memory child processes are signaled; persisted recycled PIDs/process groups are never trusted. - Retained the narrow Claude ACPX isolated-context security follow-up discovered after #12590. - Deferred the generalized executor, provider ingress, remote lifecycle, SDK/lab/eval work, release-process changes, and lockfile. ## Verification - Changed-file delta against `master`: 133 files. - GitHub Actions is the authoritative verification environment for this PR. - Full CI, security, and Greptile review will run on this lowest unmerged stack PR. - Local tests/build/typecheck were not run because this checkout is resource constrained. - Static diff/reference checks pass, and `pnpm-lock.yaml` is unchanged. ## Risks - This touches central heartbeat and agent-route code, so legacy compatibility is the primary risk. - Runtime selection remains Codex-only and explicit; direct Codex, Claude, OpenCode, process, HTTP, and plugin adapters remain on their existing paths. - Fresh native starts fail closed while the rollout flag is off; persisted native records remain readable and recoverable. - Cancellation, company/run binding, tool calls, status decisions, and completion writes are guarded or replay-safe. > For core feature work, check [ROADMAP.md](ROADMAP.md) first and discuss it in #dev before opening the PR. Feature PRs that overlap with planned core work may need to be redirected. ## Model Used OpenAI Codex, GPT-5.6, with repository tools, code execution, and parallel agent review. ## 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 linked existing issues or described the issue in-PR following the relevant issue template - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass — GitHub Actions is authoritative for this resource-constrained checkout - [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 risks above - [ ] All Paperclip CI and security gates are green - [ ] Greptile is 5/5 with no open actionable findings - [x] I will address all Greptile and reviewer comments before merge ## Stack - Position: 3 of 5 overall; lowest of 3 currently unmerged - Base: `master` - Previous: [#12590](https://github.com/paperclipai/paperclip/pull/12590), qualified Claude ACPX runtime — merged - Next: [#12592](https://github.com/paperclipai/paperclip/pull/12592), generalized Codex executor, task experience, and developer SDKs --------- Co-authored-by: Dev Agent <dev@paperclip.ing>canary/v2026.831.0-canary.14 |
||
|
|
a7e6b818e9 |
feat(apps): add Paperclip Cloud managed OAuth connector (#12600)
## Thinking Path > - Paperclip lets operators give governed tools to AI agents. > - Connected Apps already support provider OAuth and personal connection grants. > - Some providers require one stable callback and do not support dynamic client registration. > - Self-hosted Paperclip instances can run at private or changeable origins. > - Paperclip Cloud can provide the stable callback while each instance keeps its durable provider credentials. > - This pull request adds the instance side of that managed OAuth protocol and keeps customer-created clients available. > - The benefit is a safe path to one-click Workspace connections for hosted and enrolled self-hosted instances. ## Linked Issues or Issue Description **Subsystem affected** Cross-cutting. This change updates the server, Apps UI, shared app definitions, and connection documentation. **Problem or motivation** Some OAuth providers require a pre-registered callback and provider-owned client. An arbitrary self-hosted Paperclip origin cannot use that client callback directly. Paperclip ID must also stay limited to product identity instead of resource authorization. **Proposed solution** Use the existing Paperclip Cloud application as the fixed callback broker. Enroll each instance to an exact origin and separate Ed25519 and X25519 keys. Bind every request and sealed envelope to the instance, environment, user, company, provider, profile, and exact scope set. Store durable provider credentials only in the originating instance vault. **Alternatives considered** Customer-created OAuth clients remain available as the independent fallback. A generic redirect relay was rejected because it would allow caller-selected destinations and scopes. Paperclip ID was rejected as the broker because it is the identity boundary. A new service was rejected because the existing Cloud application already owns customer login and the public callback origin. **Roadmap alignment** This work extends the shipped MCP Tool Gateway and Apps milestone. It also supports the Connected Apps and Cloud deployments roadmap items. Companion Cloud implementation: https://github.com/paperclipai/paperclip-cloud/pull/312 The duplicate search found no related open Paperclip PR or issue. ## What Changed - Add a `paperclip_cloud_connector` client with signed requests, exact profile and scope bindings, and X25519-sealed credential handling. - Add explicit self-hosted enrollment with owner-only instance key storage and exact HTTPS origins. - Route managed Google Workspace setup through Paperclip Cloud and preserve customer-created OAuth clients. - Keep broker claims retryable until the local vault transaction commits. - Keep managed Google per-profile removal local-only to avoid client-wide provider revocation. - Add setup status to the Connections page and retain the Paperclip ID names as compatibility aliases. - Document the trust boundaries, enrollment, callback, refresh, removal, and rollout flows. ## Verification - `pnpm -r typecheck` - `pnpm --filter @paperclipai/shared exec vitest run src/app-definitions.test.ts` - `pnpm --filter @paperclipai/server exec vitest run src/services/paperclip-cloud-connector.test.ts src/services/paperclip-cloud-connector-enrollment.test.ts` - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/tool-access-service.test.ts -t 'brokered Gmail OAuth|brokered OAuth state'` - `pnpm --filter @paperclipai/ui exec vitest run src/pages/apps/Connections.test.tsx` - `pnpm check:token-gates` - `pnpm build` - The full stable test runner also reproduced existing macOS workspace, skill-discovery, and listener fixture failures outside the changed paths. GitHub Linux CI is the authoritative full-suite result. ## Risks - The managed flow depends on https://github.com/paperclipai/paperclip-cloud/pull/312. Real provider profiles stay disabled until Cloud deploys that protocol and the provider approves the managed client. - A Cloud outage blocks new authorization and refresh. Existing access tokens continue to work until expiry. - Managed Google profile removal only deletes the local grant. This avoids invalidating the user's other profiles that share the managed Google client. - Legacy `paperclip_id_connector` records require a reconnect after their current access tokens expire. Old Paperclip ID keys and refresh tokens are not sent to Paperclip Cloud. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5.6 (Codex). Agentic coding, tool use, code execution, and subagents were enabled. The context-window size is 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 `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
ad0ad43cf4 |
feat(runner): activate qualified Claude ACPX runtime (#12590)
## Thinking Path > - Paperclip Runner already has a hardened ACPX path for Codex. > - Claude can reuse that protocol only with an exact package/model profile and provider-lifetime fencing. > - Pi needs a separately spawned runtime whose executable does not yet have the descriptor-confined verified launch used by the ACP server. > - This pull request therefore activates Claude only and keeps Pi unavailable before installation or process launch. ## Linked Issues or Issue Description **Subsystem affected** Paperclip Runner ACPX driver, runtime host, sidecar, backend factory, package dependency, and provider conformance tests. **Problem or motivation** The production ACPX backend was Codex-only. Claude needs the same fail-closed model, authorization, cancellation, cleanup, and recovery boundaries without exposing an unsafe secondary runtime path. **Proposed solution** Generalize the hardened ACPX runtime for the exact qualified `claude` profile, add the pinned Claude ACP package and reviewed isolation patch, and reject Pi before installation, backend construction, sidecar initialization, Rust session admission, or process creation. **Alternatives considered** Activating Pi in this PR was rejected after security review because its secondary runtime executable was pathname-based and lacked the verified descriptor/snapshot boundary. Pi is deferred to a dedicated follow-up. Replaying the older generic ACPX implementation was rejected because it predates current hardening. **Roadmap alignment** ROADMAP.md does not list a conflicting ACPX-provider project. This extends the existing Runner provider architecture. ## What Changed - Generalized the ACPX backend, driver, runtime adapter, host, and sidecar for the qualified Claude profile. - Added Claude ACPX activation through its exact pinned package/model pair and isolated-settings patch. - Added provider-lifetime fencing for non-Codex qualified ACPX sessions. - Kept Pi dependencies and its patch out of the package and build configuration. - Added fail-closed Pi rejection at driver validation, backend construction, runtime-host admission, sidecar initialization, and Rust session validation. - Added focused tests for Claude selection, model enforcement, lifecycle fencing, cancellation, recovery, and Pi rejection. - Did not change or commit `pnpm-lock.yaml`; CI regenerates the PR lockfile under the existing repository policy. ## Verification - GitHub Actions is the authoritative verification environment for this PR. - CI runs dependency policy, runner package checks, protocol parity, typecheck, build, security, and stack policy. - Local tests were not run because this checkout is resource constrained, per the requested workflow. ## Risks - Claude package behavior can drift from the qualified protocol; the package and patch are pinned and admission verifies the exact profile. - Unsupported providers and models fail closed. - Pi remains unavailable until descriptor-confined verified launch exists for its separate runtime. - Existing Codex ACPX behavior remains covered by shared conformance tests. > For core feature work, check [ROADMAP.md](ROADMAP.md) first and discuss it in #dev before opening the PR. Feature PRs that overlap with planned core work may need to be redirected. ## Model Used OpenAI Codex, GPT-5.6, with repository tools, code execution, and parallel agent review. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used - [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 - [x] I have described the issue in the PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name contains no internal task identifier - [ ] I have run tests locally and they pass — GitHub Actions is authoritative for this resource-constrained checkout - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation - [x] I have considered and documented risks - [ ] All applicable Paperclip CI gates are green - [ ] Greptile is 5/5 with no actionable findings ## Stack - Position: lowest unmerged PR - Base: `master` - Previous: [#12588](https://github.com/paperclipai/paperclip/pull/12588), merged qualified OpenCode runtime - Next: [#12591](https://github.com/paperclipai/paperclip/pull/12591), native application integrationcanary/v2026.831.0-canary.13 |
||
|
|
2e5a24e177 |
feat(runner): add qualified OpenCode runtime (#12588)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Paperclip Runner provides a durable execution boundary for supported providers. > - The current production runtime supports Codex but cannot execute OpenCode sessions. > - OpenCode needs a qualified transport, strict input mapping, and normalized events. > - This pull request adds the OpenCode runtime as one isolated provider unit. > - The benefit is a reviewable provider expansion that does not weaken the existing Codex path. ## Linked Issues or Issue Description **Subsystem affected** Cross-cutting: packages/paperclip-runner and the Codex-local adapter configuration contract. **Problem or motivation** Paperclip Runner has provider-neutral contracts, but the production backend factory cannot start a qualified OpenCode session. This blocks OpenCode from using the durable runner path. **Proposed solution** Add the qualified OpenCode app-server proxy, driver, MCP bridge, backend, fixtures, and factory wiring. Keep existing Codex behavior unchanged. **Alternatives considered** Keeping OpenCode only on the direct adapter path would avoid this runtime work, but it would not provide durable runner recovery or normalized provider events. **Roadmap alignment** ROADMAP.md does not list a conflicting provider-runtime project. This change extends the existing Paperclip Runner architecture. ## What Changed - Added the qualified OpenCode app-server proxy and input queue. - Added collaboration-mode and provider-event normalization. - Added the OpenCode MCP bridge and native session backend. - Added strict fixtures and focused unit coverage. - Added only the package exports and adapter configuration required by this runtime. - Kept deferred SDK, lab, eval, and public package surfaces out of this change. ## Verification - GitHub Actions is the authoritative verification environment for this PR. - Run the package type checks and focused OpenCode tests in CI. - Run repository typecheck, test, build, security, and policy gates through the stack-aware workflow. - Local tests were not run because this checkout is resource constrained. ## Risks - OpenCode protocol changes could affect event normalization or recovery. - The driver fails closed on malformed input and unsupported runtime behavior. - Existing Codex selection remains unchanged unless the stored provider is OpenCode. > For core feature work, check [ROADMAP.md](ROADMAP.md) first and discuss it in #dev before opening the PR. Feature PRs that overlap with planned core work may need to be redirected. ## Model Used OpenAI Codex, GPT-5.6, with repository tools, code execution, and parallel agent review. ## 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 linked existing issues or described the issue in-PR following the relevant issue template - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass — GitHub Actions is authoritative for this resource-constrained checkout - [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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge ## Stack - Position: 1 of 4 - Base: master - Next: additional qualified provider runtimescanary/v2026.831.0-canary.12 |
||
|
|
39eafad47d |
test(e2e): shorten and split Smoke Lab coverage (#12506)
## Thinking Path > - Paperclip uses browser tests to protect critical operator flows. > - The trusted pull request workflow runs the E2E catalog on three existing runners. > - Smoke Lab was one 168-second spec, so the shard scheduler could not divide it. > - The spec also repeated service-start calls, page loads, and full-page screenshots. > - This pull request removes that repeated work and divides the scenario catalog into two independent specs. > - The benefit is a shorter Smoke Lab run and a balanced E2E lane without more AWS capacity. ## Linked Issues or Issue Description Refs: #10629 **What existing behavior does this improve?** This improves the trusted pull request E2E lane and its Smoke Lab Playwright coverage. **Current behavior** Smoke Lab is one indivisible 168-second CI spec. It starts services for every scenario, loads the same evidence page twice, and captures a full-page success screenshot for all 56 lifecycle steps. **Proposed behavior** Start Smoke Lab services once per spec. Keep the per-scenario fixture reset. Capture one representative success screenshot per scenario and keep every failure screenshot. Run P1–P4 and P5–P7 as separate specs so the existing duration-aware scheduler can put them on different runners. **Reason and benefit** The optimized lifecycle reduced local Smoke Lab wall time from 57.68 seconds to 37.04 seconds. This is a 35.8% reduction. The two halves also let the existing three runners target about 125, 124, and 124 seconds of recorded spec work instead of about 168, 125, and 124 seconds. **Breaking changes** None. The same seven scenarios and eight lifecycle steps still run. The result API still records every step. Successful non-connect steps no longer attach redundant screenshots. ## What Changed - Reused one Smoke Lab service start within each spec while retaining isolated fixture installation for every scenario. - Removed the duplicate catalog evidence navigation. - Reduced success screenshots from 56 to 7 while retaining screenshots for every failed step. - Split the shared lifecycle runner into P1–P4 and P5–P7 specs. - Mark each successful split result as partial and keep dashboard health amber until one run covers the full catalog. - Updated the duration manifest and contributor docs for the split. ## Verification - `pnpm -r typecheck` passed on Node.js 24.20.0. - `pnpm build` passed on Node.js 24.20.0. - `node --test scripts/__tests__/e2e-shard.test.mjs` passed 9 tests. - `pnpm exec vitest run ui/src/pages/tools/smoke-lab-matrix.test.ts` passed 8 tests. - Both split specs passed together on Node.js 24.20.0 after the review fixes: 2 passed in 35.7 seconds; shell wall time was 36.86 seconds. - The pre-change Smoke Lab baseline passed with a 57.68-second shell wall time. The optimized unsplit A/B run passed with a 37.04-second shell wall time. - The full local E2E catalog passed 44 tests and skipped 2 tests. One existing `pipelines-tutorial-flow.spec.ts` assertion failed again when run alone. - The broad local unit run reproduced failures in untouched workspace-runtime suites. Typecheck, build, shard tests, and all changed browser coverage pass. CI remains the authoritative full-suite result. ## Risks - The split duration weights use the measured local reduction and the previous 168-second CI weight. They should be refreshed after two real pull request runs. - Service state is shared within each half. Fixture installation still runs before every scenario to reset connection, policy, and catalog state. - Each half records passed execution with partial coverage. Dashboard health recognizes the partial flag and stays amber because no single runner covers the full catalog. A failed half still records failed/red. - Fewer success screenshots reduce redundant artifacts. Every scenario keeps its connect screenshot, and every failure still captures evidence. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5. The exact deployment ID and context window are not exposed in this session. The model used agentic reasoning, code editing, shell execution, browser testing, and GitHub tools. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.831.0-canary.11 |
||
|
|
a34c615cc1 |
fix(release): skip lifecycle scripts for bundle staging (#12585)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The release system builds the workspace before it prepares npm packages. > - Bundled packages then move the built files and runtime dependencies into a standalone staging directory. > - npm pack and npm publish still run package lifecycle scripts in that directory. > - The server `prepack` script requires the source workspace and cannot run from the standalone directory. > - This pull request disables lifecycle scripts only for npm operations on prepared bundled packages. > - The benefit is that release packaging uses the artifacts that the release already built. ## Linked Issues or Issue Description Refs #12584 **What happened?** The canary dry run passed bundled dependency installation and then failed while it packed `@paperclipai/server`. npm ran the server `prepack` script in the standalone staging directory. That script called `pnpm run prepare:ui-dist && pnpm run build`, which requires files from the source workspace. See the [failed canary dry-run job](https://github.com/paperclipai/paperclip/actions/runs/33399041712/job/99510762364). **Expected behavior** Bundled package packing and publishing must use the artifacts that the release already built. They must not run workspace-only package lifecycle scripts from the standalone staging directory. **Steps to reproduce** 1. Build the Paperclip workspace. 2. Prepare the bundled server package in a temporary directory. 3. Run npm pack from that directory. 4. Observe that npm runs the server `prepack` script outside the source workspace. **Paperclip version or commit** `08af15bd7629790a618e8787c11490c96a1b619a` ## What Changed - Add `--ignore-scripts` to npm pack for prepared bundled packages. - Add `--ignore-scripts` to both normal and no-provenance npm publish attempts for prepared bundled packages. - Update release helper tests to require this behavior. ## Verification - `node --test scripts/acpx-patch-packaging.test.mjs scripts/release-lib.test.mjs` (22 passed) - `pnpm test:release-registry` (98 passed) - `git diff --check` - The full test suite and build were not run locally. GitHub runs the canary dry run and full matrix. ## Risks - Low risk. The flag applies only to bundled packages that the release prepares after the workspace build. - Normal pnpm package publishing is unchanged. - Package lifecycle scripts remain in the published manifest. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with `gpt-5.6-sol`. The model used agentic reasoning, tool use, and code execution. The context window size is not exposed in this environment. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.831.0-canary.10 |
||
|
|
08af15bd76 |
fix(release): omit dev dependencies from bundle staging (#12584)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The release system publishes the server package with selected runtime dependencies inside its tarball. > - The staging step writes a temporary package manifest before it runs npm install. > - That manifest kept private development dependencies that npm still tried to resolve with `--omit=dev`. > - The canary release then stopped because the matching private runner version was not published yet. > - This pull request removes development dependencies from only the temporary install manifest. > - The benefit is that bundled package staging installs only the runtime dependencies that the tarball includes. ## Linked Issues or Issue Description Refs #12582 **What happened?** The canary release failed while it prepared `@paperclipai/server`. npm tried to resolve `@paperclipai/paperclip-runner@2026.831.0-canary.8` from the temporary staging manifest. The runner package was not published at that version, so npm returned `ETARGET`. See the [failed release job](https://github.com/paperclipai/paperclip/actions/runs/33395418107/job/99504474818). **Expected behavior** Bundled package staging must install only dependencies that the published tarball bundles. Private development dependencies must not affect the staging install. **Steps to reproduce** 1. Prepare a bundled package with a public bundled runtime dependency. 2. Add an unpublished package version to `devDependencies`. 3. Run `scripts/prepare-bundled-package.mjs`. 4. Observe that npm resolves the development dependency even when the command uses `--omit=dev`. **Paperclip version or commit** `5a988df600ebda30e446496862bf83c76d6d53d6` ## What Changed - Remove `devDependencies` from the temporary manifest used for bundled package installation. - Keep the final publish manifest unchanged. - Add unit and staging regression checks for the unpublished development dependency case. ## Verification - `pnpm install --frozen-lockfile` - `node --test scripts/acpx-patch-packaging.test.mjs` (12 passed) - `pnpm test:release-registry` (98 passed) - `git diff --check` - The full test suite and build were not run. This change has focused release-packaging coverage. ## Risks - Low risk. The change affects only the temporary manifest used to install bundled runtime dependencies. - The script restores the complete publish manifest before it creates the package tarball. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with `gpt-5.6-sol`. The model used agentic reasoning, tool use, and code execution. The context window size is not exposed in this environment. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] 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> |
||
|
|
5a988df600 |
chore(lockfile): refresh pnpm-lock.yaml (#12583)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
8610e7934e |
fix(release): bundle vendored runner ACPX runtime (#12582)
## Thinking Path > - Paperclip is the open source app that people use to manage AI agents for work. > - The npm release includes the Paperclip server and a vendored runner. > - The vendored runner imports ACPX when it starts a Codex agent. > - The server package did not include the ACPX version that the runner needs. > - A fresh canary install therefore stopped with `ERR_MODULE_NOT_FOUND` after onboarding. > - This pull request bundles the patched ACPX runtime with the server package. > - The benefit is that a fresh npm install can load the vendored runner. ## Linked Issues or Issue Description No public issue exists for this bug. A GitHub search found no duplicate or related pull request. **What happened?** A fresh `npx paperclipai@canary onboard` command completed onboarding. The server then failed to start. Node could not resolve `acpx` from the vendored Paperclip runner. **Expected behavior** The server should start after onboarding from a fresh npm cache and a temporary data directory. **Steps to reproduce** 1. Run `npx paperclipai@canary onboard --data-dir "$(mktemp -d /tmp/paperclip-canary.XXXXXX)"`. 2. Select Quickstart. 3. Start Paperclip. 4. Observe `ERR_MODULE_NOT_FOUND` for `acpx`. **Paperclip version or commit** `paperclipai@2026.831.0-canary.6` **Deployment mode** Other: local trusted Quickstart through `npx`. **Installation method** npm through `npx`. **Agent adapter(s) involved** Codex. **Database mode** Embedded PGlite. **Access context** Board operator during onboarding. **Node.js version** Node.js 26.4.0. **Operating system** macOS. **Relevant logs or output** ```shell Cannot find package 'acpx' imported from .../node_modules/@paperclipai/server/dist/vendor/paperclip-runner/drivers/acpx/codex-runtime-adapter.js ``` **Relevant config (if applicable)** No custom configuration was required. **Additional context** The published adapter utilities contain a nested `acpx@0.12.0`. Node cannot resolve that nested package from the sibling vendored runner. Installing `acpx@0.13.1` at the clean package root makes the failing runner import succeed. **Privacy checklist** The log excerpt contains no user path, token, company name, or other private value. ## What Changed - Added `acpx@0.13.1` as a bundled server runtime dependency. - Added a version-specific patch check for the ACPX versions used by the server and adapter utilities. - Added release-package coverage for the server ACPX bundle. ## Verification - `pnpm test:release-registry` passed 98 tests. - `node --test scripts/acpx-patch-packaging.test.mjs` passed 12 tests. - `pnpm exec vitest run server/src/__tests__/server-package-build-script.test.ts` passed 4 tests. - `node --test scripts/release-package-map.test.mjs` passed 12 tests. - `pnpm -r typecheck` passed. - A clean extracted server tarball contained the patched `acpx@0.13.1` runtime. - The previously failing vendored runner module imported from that clean tarball. - The repository-wide test suite was stopped before completion at the maintainer's request because it takes too long for this urgent packaging fix. ## Risks - Risk is low. - The server tarball grows because it now contains ACPX and its production dependencies. - The release stager now uses a version-specific marker to verify the ACPX patch. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with `gpt-5.6-sol`. - The model used reasoning mode, tool use, and code execution. - The context window size was not disclosed. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] 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> |
||
|
|
f0fbfb9394 |
chore(lockfile): refresh pnpm-lock.yaml (#12546)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>canary/v2026.831.0-canary.7 |
||
|
|
8478ddbcee |
feat(runner): persist ACPX suspension checkpoints (#12425)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust ACPX session can now suspend only at a safe idle boundary and its events have a durable projection > - A later runner process cannot safely resume from an unbound or partially written identity record > - The recovery anchor must bind the exact provider identity, run, normalized session, catalog revision, and catalog digest > - The record must be bounded, private, strict about schema drift, and atomically replaceable > - Recovery must re-admit the entire prospective session configuration before releasing the stored identity > - This pull request adds only that package-local checkpoint store without selecting ACPX in runnerd ## Linked Issues or Issue Description Refs #12424 Refs #12422 ## What Changed - Add a versioned ACPX safe-suspension checkpoint contract with unknown fields rejected at every persisted level. - Bind each checkpoint to the run, normalized session, catalog revision, catalog digest, and exact provider identity. - Persist a checkpoint-specific strict identity that requires the pinned permission mode without narrowing the additive live sidecar identity wire shape. - Construct checkpoints only from a session configuration whose model, permission policy, tool catalog, and expected identity validate. - Admit recovery only when reconstructing the checkpoint from the prospective configuration produces an exact match. - Reject run, session, catalog revision, catalog digest, model, permission, expected-identity, profile, and workspace drift fail closed. - Require persisted run/session IDs to satisfy the same stable-ID boundary as fresh session admission. - Store the checkpoint under a dedicated private runner-state subdirectory. - Bound checkpoint files to 1 MiB before reading or decoding. - Refuse symlinked state directories and non-private or non-regular checkpoint files. - Replace checkpoints atomically through a private temporary file and directory sync. - Make repeated saves of the same checkpoint idempotent. - Add integration coverage for private round trips, complete recovery admission, malformed/oversized files, nested schema drift, missing permission binding, invalid stable IDs, and symlink denial. - Document the package-local suspension recovery boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `1ee738cf487defe88043b241c4e2dc34a1a8a7bc` (`master` after #12424 merged). - Exact replay head: `89cfea5495428be890810d2b8a27673943234ca3`. - Stable patch ID: `dbaeb0bbe773f1ca5ef1f9bdc0fa61f4a08ca451`. - The exact delta is 4 files and 591 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, dependency, or migration change. - `git diff --check` and the Cargo formatting check pass on the replayed delta. - Exact-head GitHub Actions run `33374006661` (attempt 2): **PASSED** with 23/23 jobs passed. - Greptile reviewed exact head `89cfea5495428be890810d2b8a27673943234ca3`: **5/5**, with zero unresolved review threads. - Superagent, contributor trust, Socket, and Snyk security checks: **PASSED**. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - A checkpoint is valid only after the sidecar has confirmed safe suspension. The constructor therefore accepts the exact identity returned by that operation and revalidates it against local authority. - Loading proves only that the file is structurally valid; `admit_recovery` is the boundary that proves the file belongs to the prospective run, catalog, model, permission policy, and expected provider identity. - The checkpoint intentionally contains no credentials, bootstrap ticket, provider output, or pending request payload. - Strict checkpoint schema and identity validation rejects incompatible or tampered recovery records rather than attempting partial migration. This strictness is checkpoint-local and does not narrow existing PRP or sidecar wire compatibility. - Atomic replacement uses the platform `rename` primitive; Unix additionally syncs the private parent directory before reporting success. - No production path loads this checkpoint in this pull request. Runnerd execution and durable recovery wiring remain a later slice. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used with version and capability details - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have linked the preceding public PRs or described the issue in-PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
1ee738cf48 |
feat(runner): project durable ACPX events (#12424)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now owns validated, scoped ACPX reducer events and safe session suspension > - Durable PRP transport must receive provider-neutral events rather than sidecar-native envelopes > - Semantic calls and questions must retain the exact run, session, turn, item, and provider-request authority used by the durable command stream > - Terminal, result, assistant, process, and diagnostic events also need one reviewed projection boundary > - Permission requests remain impossible under the pinned Codex policy and must fail closed if they reach projection > - This pull request adds only that package-local projection without selecting ACPX in runnerd ## Linked Issues or Issue Description Refs #12422 ## What Changed - Add a validated durable ACPX event projection context bound to one run, normalized session, turn, and item. - Pass already normalized activity events through without reintroducing provider-native envelopes. - Project authorized tool calls into canonical semantic input receipts with exact correlation and content digests. - Project structured questions into provider-neutral `paperclip.runtime_request.v2` events. - Preserve both the public projected request identity and the original provider request identity so responses resolve the exact sidecar request. - Project dynamic semantic operation results as `semantic_tool.result`; only reserved finish/block operations may propose the run result. - Project semantic completion results into `run.result.proposed`. - Project terminal-flushed assistant messages on the final channel and turn terminal states into existing provider-neutral event families. - Project sanitized process metadata and diagnostics into bounded harness diagnostics. - Validate runtime-request origins against their strict durable shape and fall back from empty optional titles to a valid question prompt. - Reject invalid identities, projected-identity collisions, unstable semantic receipt identities, permission requests, and cross-turn projection fail closed. - Add integration coverage across reducer event families, correlation, identity validation, projected question resolution, and pinned-policy denial. - Document the durable projection boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `80639f4f69c8938eb74bdc0833df93e0ed91dab3` (`master` after #12422 merged). - Exact replay head: `3cb29581d2bcbc4b47f8069baffd721c6ce4e444`. - Stable patch ID: `92910b56575e67ae83960177d467a565019ba282`. - The exact delta is 22 files, 1,206 additions, and 59 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, dependency, or migration change. - `git diff --check` and the Cargo formatting check pass on the replayed delta. - Exact-head GitHub Actions run `33372209037` (attempt 2): **PASSED** with 23/23 jobs passed. - Greptile reviewed exact head `3cb29581d2bcbc4b47f8069baffd721c6ce4e444`: **5/5**, with zero unresolved review threads. - Superagent, contributor trust, Socket, and Snyk security checks: **PASSED**. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This function accepts reducer output, not raw sidecar frames. Callers must preserve the existing scope-first decode and reduction order. - Semantic input includes the already sanitized provider input while its content receipt uses the same canonical digest. - Structured input preserves the validated provider-neutral question set and sanitized origin. - Noncanonical provider request identities are deterministically projected for PRP while the original identity remains authoritative for the sidecar resolution command. - Existing PRP v1 identifiers remain schema-compatible; the only public ID-schema change widens turn/item limits from 160 to 240 characters. The internal ACPX sidecar wire schema now mirrors the stable IDs its Rust transport already enforced. - The projector verifies event-carried terminal and assistant turn identifiers against the durable context. - No production path invokes this projector in this pull request. Durable command execution remains the next slice. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used with version and capability details - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have linked the preceding public PR or described the issue in-PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.831.0-canary.6 |
||
|
|
80639f4f69 |
feat(runner): suspend safe ACPX sessions (#12422)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now owns exact ACPX request resolution and fail-closed session state > - A recoverable provider session needs an explicit suspension boundary before runnerd can safely hand work across process lifetimes > - Suspension is unsafe while a turn or provider request is active because remote effects may still be in flight > - A successful acknowledgement must preserve the exact immutable session identity > - This pull request adds only that guarded package-local lifecycle operation without selecting ACPX in runnerd > - The benefit is a small recovery primitive whose safety rules are independently reviewable ## Linked Issues or Issue Description Refs #12421 ## What Changed - Add a provider-state query for active pending tool, input, or permission requests. - Permit session suspension only when no turn or provider request is active. - Send a bounded `session.suspend` command with an operator-safe reason. - Require an affirmative suspension acknowledgement and the exact existing session identity. - Treat transport failure, rejection, omitted or malformed identity, and identity drift as fail-closed terminal errors. - Mark a successfully suspended session closed and terminate the local sidecar process while retaining cleanup ownership if termination must be retried. - Preserve a valid session after purely local unsafe-state rejection so it can settle before retry. - Extend the fake sidecar with deterministic suspension success, acknowledgement mismatch, identity mismatch, and missing-identity modes. - Add integration coverage for safe suspension, active-turn rejection, fail-closed remote mismatches, and retained cleanup. - Document the package-local suspension boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `91d861ff69d415a3b105ae2eaad9cc56c66a9231` (`master` after #12421 merged). - Exact replay head: `085667e10c51c6c0360732f63c8fef83e806dd88`. - Stable patch ID: `b18d6b7efd1de569d3068b0a782f8aac2fbc9322`; this is the prepared suspension delta plus the focused fake-sidecar fix that consolidates mismatch modes into the existing command arm. - The exact delta is 5 files, 136 additions, and 5 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Exact-head GitHub Actions run `33369571343` (attempt 1): **PASSED** with 23 jobs passed and zero failures. - Greptile reviewed exact head `085667e10c51c6c0360732f63c8fef83e806dd88`: **5/5**, with zero unresolved review threads. - Superagent, contributor trust, Socket, and Snyk security checks: **PASSED**. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - The sidecar may apply suspension before a transport failure is observed. The local session closes rather than retrying an ambiguous effect. - Local active-work rejection happens before transport and leaves the valid session open so the caller can settle it safely. - Identity equality is checked across provider, driver, session, thread, run, and company fields before accepting suspension. - No production path invokes suspension in this pull request. Runnerd execution and durable recovery wiring remain later slices. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either linked existing issues with `Refs #` or described the issue in-PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
91d861ff69 |
feat(runner): resolve ACPX provider requests (#12421)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now owns a scoped ACPX turn and validates provider requests before exposing them > - A live turn can pause for semantic tool results or structured input > - Local state and the sidecar can diverge if the runner clears a request before the sidecar accepts its resolution > - A mismatched or ambiguous remote acknowledgement must close the session, while a local validation error must preserve the request for a safe retry > - This pull request adds those two-phase resolution paths and rejects Codex permission events that bypass the pinned policy without selecting ACPX in runnerd > - The benefit is an atomic request boundary that can be wired into durable execution in a later slice ## Linked Issues or Issue Description Refs #12420 Refs #12419 ## What Changed - Resolve authorized semantic tool calls only for the active turn and exact pending operation. - Validate semantic results against the authorized response schema before transport. - Send a bounded generic provider error when a semantic operation fails without exposing internal error text or payloads. - Resolve structured input only after validating the exact persisted question set. - Support explicit submit, decline, and cancel input outcomes. - Reject any Codex permission event that bypasses the pinned sidecar policy. - Build candidate provider and authorization state before each request. - Commit candidate state only after the sidecar returns an affirmative resolution acknowledgement. - Preserve pending work after local validation errors so the caller can retry safely. - Terminate the session after transport failure or an invalid remote acknowledgement because the remote effect is ambiguous. - Bind every resolution to the exact active turn and request or call identity. - Extend the fake sidecar and add integration coverage for successful commits, safe local retries, pinned-policy enforcement, redaction, and fail-closed acknowledgement mismatch. - Document the package-local resolution boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `3aa2065d084d6a29492aaa15e822b5d17c3a4266` (`master` after #12420 merged). - Exact replay head: `9507024f70c6f434c2c322385d3a9e240250b03c`. - Stable patch ID: `a4f27d2fae606596f70b5b1c2b29dd7f250541d8`, identical to the prepared two-commit delta. - The exact delta is 5 files, 463 additions, and 7 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - GitHub Actions run `33368135190`, attempt 2: **PASSED** on the exact replay head (23/23 jobs passed; a failed-job-only retry cleared one unrelated server test environment failure where `npm` was unavailable). - Greptile: **5/5** on the exact replay head with zero unresolved review threads; Superagent, Socket, Snyk, and contributor-trust checks also passed. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - A transport failure can happen after the sidecar applied a resolution. The session closes instead of retrying an ambiguous effect. - Local validation happens before transport and preserves pending state, so a corrected answer or result can be retried. - The sidecar transport already correlates each command response to its request identifier. This slice also requires `resolved: true` before local commit. - The initial Codex sidecar owns its pinned permission policy and does not delegate permission resolution. Any permission event therefore terminates the session fail closed. - No production path invokes these methods in this pull request. Durable ACPX execution wiring remains a later slice. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
3aa2065d08 |
feat(runner): validate structured question responses (#12420)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now owns a bounded ACPX session and a fail-closed turn lifecycle > - Provider questions pause a turn and must return structured answers to the same persisted question set > - JSON Schema validates the wire shape, but it cannot validate identifiers and constraints across two documents > - Unknown questions, invalid choices, and malformed custom answers must fail before any provider receives them > - This pull request adds only the package-local response validator and tests > - The benefit is a small trust boundary that later request-resolution code can use without changing production selection ## Linked Issues or Issue Description Refs #12419 ## What Changed - Validate `paperclip.question_response.v1` against its versioned JSON Schema. - Bound serialized responses to 768 KiB before validation. - Require answer identifiers to match the exact persisted question set. - Require answers for required questions and reject unknown question identifiers. - Enforce text, single-select, and multi-select answer modes. - Match the existing TypeScript numeric syntax, including decimal, exponent, hexadecimal, octal, and binary input. - Match ECMAScript trimming exactly, including BOM whitespace while rejecting Unicode NEL rather than inheriting Rust-specific whitespace behavior. - Enforce known options, custom-answer policy, text length, pattern, and numeric constraints. - Validate duplicate option IDs, inverted bounds, and dynamic patterns before answer lookup so malformed optional questions fail closed even when unanswered. - Match JavaScript UTF-16 code-unit length semantics for text constraints and the 100,000-unit response-field bound. - Preserve the public optional `recommended` question-option field in the versioned schema, generated schema bundle, and Rust validation path. - Return typed validation errors for malformed inputs without panics. - Export the validator from the Rust runner core. - Add table-driven tests for valid, mismatched, malformed, oversized, and numeric-boundary responses. - Document the package-local structured-response boundary. - Add `num-bigint` 0.4 and `num-traits` 0.2 as direct runner-core dependencies for exact arbitrary-length radix parsing and one-step JavaScript Number rounding; update only the package-local runner Cargo lockfile. - Do not change the repository PNPM lockfile, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `9a9fdf06ee4142f77427db30efccc4c43056f64b` (`master` after #12419 merged). - Exact replay head: `fad92b3fb348b66ddb10dde44b7b060e55c4fe96`. - Stable patch ID: `4d6ffbd519dd081f7ea530977cd965bd4569fc75`; this is the prepared two-commit delta plus the focused cross-language parity fix found during replay review. - The exact delta is 10 files, 712 additions, and 2 deletions, all in `packages/paperclip-runner`. - The package-local `packages/paperclip-runner/runner/Cargo.lock` records the two direct runner-core dependencies; their already-resolved versions and checksums are unchanged. - The question-set schema source, generated TypeScript schema bundle, and protocol manifest hash are updated together; the schema SHA-256 is `42b5441a3d388851dacb6e4500dfd4a17d878eded2e724228078b647e7440d3f`. - GitHub Actions run `33366812025`, attempt 2: **PASSED** on the exact replay head (23/23 jobs passed; a failed-job-only retry cleared one unrelated ACPX runtime-host timeout). - Greptile: **5/5** on the exact replay head with zero unresolved review threads; Superagent, Socket, Snyk, and contributor-trust checks also passed. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - The validator compiles the embedded response schema for each submission. Responses are user-paced and bounded, so this keeps the slice simple without affecting a hot event path. - The persisted question set is the source of truth for identifiers and constraints. A malformed persisted set fails closed. - Numeric input follows the existing structured-question contract, including JavaScript-prefixed syntax. Optional whitespace-only answers are rejected instead of being treated as an omitted value. - Error messages identify the invalid field but do not include answer text. - No production path invokes this validator in this pull request. Request resolution remains the next slice. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
9a9fdf06ee |
feat(runner): drive ACPX provider turns (#12419)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now validates and opens an exact Codex ACPX session and attaches one run/catalog identity > - A live session must start one turn, preserve immutable workspace authority, accept interruption, and consume provider events > - Command acknowledgements and event scope are trust boundaries; disagreement must terminate the session rather than permit divergent state > - The existing reducer already owns bounded state, ordering, correlation, and terminal cleanup > - This pull request connects turn commands and polling only to that reviewed reducer without selecting ACPX in runnerd > - The benefit is a fail-closed execution loop before semantic request resolution and production selection are added ## Linked Issues or Issue Description Refs #12418 Refs #12417 ## What Changed - Start one ACPX turn only after validating a bounded turn identifier, bounded message, and the session's immutable working directory. - Require `turn.start` to acknowledge the exact requested turn before mutating provider state. - Request interruption only for the active turn and require an affirmative cancellation acknowledgement. - Keep the turn active until the authoritative terminal event is polled and reduced. - Poll bounded sidecar events and route every event through the existing scope-first payload/state boundary. - Terminate the sidecar fail closed after a rejected or mismatched turn command, transport failure, or invalid scoped event. - Preserve ordinary local validation failures without mutating or closing an otherwise valid session. - Admit semantic tool calls through the run-scoped authorized tool bridge before returning them to runnerd. - Reduce events and authorize tool calls on candidate clones, then commit both together only after every check passes. - Rotate and scope tool receipts by run and turn; reserve pending, completed, and settled call IDs across both tool bridges so cross-bridge duplicates cannot be re-admitted. - Preserve exact turn correlation through payload, scope, provider state, fake sidecar, and integration fixtures. - Extend the package-local fake sidecar with deterministic turn activity, terminal, acknowledgement-mismatch, and scope-violation modes. - Add integration coverage for happy-path activity/interruption/settlement, local validation, turn mismatch, cancellation mismatch, cross-run denial, receipt rotation, and cross-bridge call-ID reuse. - Document the turn lifecycle boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `10cf68295d5457ccf1010db20a06e2951e47162a` (`master` after #12418 merged). - Exact replay head: `1ec18368bdacafafa58720b9e2b982e1b0d11163`. - Stable patch ID: `4b43a5ef2a428850a05b0741d06e7cf4f48ec334`, identical to the prepared four-commit delta plus the focused cross-bridge call-ID reservation fix. - The exact delta is 13 files, 1,855 additions, and 37 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - GitHub Actions run `33364033038`, attempt 2: **PASSED** on the exact replay head (23/23 jobs passed; the failed-job-only retry cleared one unrelated flaky server heartbeat test). - Greptile: **5/5** on the exact replay head with zero unresolved review threads; Superagent, Socket, and Snyk checks also passed. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - A sidecar may emit events while a command response is in flight. The transport buffers them, then the session binds the acknowledged turn before polling and reducing those events. - A turn-start rejection can leave provider-native state ambiguous, so command rejection or acknowledgement mismatch terminates the session instead of attempting unsafe reuse. - Interruption does not settle local state; only the validated terminal event clears the active turn. - Any transport or event validation failure terminates the child process so a compromised stream cannot continue. - Call identifiers are authorization identities and remain reserved across pending, completed, and settled states in both bridges. - The package exposes new Rust methods, but no production path invokes them in this pull request. - Tool authorization is atomic with reducer state, but tool results, structured input, and permission resolution remain later slices. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.831.0-canary.5 |
||
|
|
10cf68295d |
feat(runner): bootstrap ACPX provider sessions (#12418)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now has bounded ACPX transport, scope, payload, normalization, and state-reduction layers > - A live provider needs a lifecycle owner that starts the sidecar and proves it opened the exact requested session > - The initial production slice is Codex-only and must fail closed on capability, model, identity, policy, or catalog drift > - Failed bootstraps must not leak a child process, and ordinary shutdown must preserve resumable provider state > - This pull request adds that package-local lifecycle without selecting ACPX in runnerd > - The benefit is a reviewable bootstrap/recovery boundary before turn commands and production selection are connected ## Linked Issues or Issue Description Refs #12417 Refs #12416 ## What Changed - Add a package-local ACPX provider session configuration and lifecycle owner. - Reject non-UTF-8 runtime and working directories before spawning so JSON path serialization cannot panic. - Validate the sidecar launch contract, Codex-only agent, model, run and session identifiers, absolute directories, positive JSON-safe catalog revision, pinned permission mode, bounded instructions, and canonical authorized tool catalog before spawning. - Verify the initialization protocol version, child PID, persistent-session support, exact-model support, runner-owned permission policy, semantic-tool bridge, and structured-input contract. - Open an identity-bound session and require the requested and effective models, permission mode, session identifier, digests, and optional recovery identity to match exactly. - Attach the run and require the sidecar to confirm the exact run identifier and catalog revision. - Retry failed transport cleanup while retaining lifecycle ownership; terminate the sidecar after every failed bootstrap and on an unclosed session drop. - Close sessions without discarding persistent state and make explicit shutdown idempotent. - Extend the package-local fake sidecar with deterministic bootstrap, wrong-model, and wrong-run responses. - Add five integration tests covering successful bootstrap/shutdown, pre-spawn policy validation, model mismatch, run mismatch, and recovery identity matching. - Document the session bootstrap boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `f038633bf5b04163ff985ef0542876bd9f455379` (`master` after #12417 merged). - Exact replay head: `a6d9ad62f20fdb47a1dbc76aa4baa9d8fa6dae53`. - Stable patch ID: `82b6f2551749598a688c3f44a1a3714516030429`, identical to the reviewed `e6e550f9..d51a8855` delta. - The exact delta is 5 files and 609 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused Rust lifecycle, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33362799786` is green; its failed-job retry passed one unrelated flaky server shard without a patch change. Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This lifecycle owns a child process and session identity. Configuration is fully validated before spawning, every bootstrap response is checked against the child PID and requested identity, and failed bootstrap always terminates the process. - Recovery identity matching is exact so a persisted native record cannot silently attach to another session, model, workspace, profile, or permission policy. - Explicit shutdown preserves persistent provider state; a dropped unclosed session still terminates its process group as a safety fallback. - The package exports a new Rust module, but no production path constructs it in this pull request. - Turn commands, event polling, request resolution, and runnerd selection remain later slices. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.831.0-canary.4 |
||
|
|
f038633bf5 |
feat(runner): reduce ACPX provider state (#12417)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now has bounded ACPX transport, scope, payload, and provider-neutral normalization layers > - A live provider still needs state across events to correlate requests and preserve turn ordering > - That state must not mutate before scope and payload validation succeeds > - It must bound retained text and pending values, suppress repeated reasoning boundaries, and make one semantic result authoritative > - This pull request adds that reducer without issuing process commands or selecting ACPX in runnerd > - The benefit is a separately reviewable state machine before transport commands and production selection are connected ## Linked Issues or Issue Description Refs #12416 Refs #12415 ## What Changed - Add a package-local ACPX provider state reducer with one run binding and one active turn. - Decode every sidecar event through the existing scope-first payload boundary before state mutation. - Bound retained assistant text, pending semantic tool inputs, and pending runtime request values. - Correlate semantic tool calls, structured input requests, and permission requests by stable IDs. - Keep pending tool resolution two-phase so callers remove state only after a later sidecar command succeeds. - Carry authoritative tool classification from validated payloads into retained state. - Suppress repeated reasoning-start activity within one turn. - Accept one semantic result idempotently and fail closed on a conflicting result. - Flush the final assistant message before the authoritative terminal event. - Clear unresolved turn-scoped requests at terminal state and reject late events for the settled turn. - Admit redacted global process and diagnostic events without requiring an active turn. - Add seven integration tests for turn ordering, correlation, conflicts, scope-before-mutation, redaction, and terminal cleanup. - Document the state boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `7bb6cebeae727a16c205bb80b5c2b9e92ea6b5fa` (`master` after #12416 merged). - Exact replay head: `da82e7f67ecd6f0f2184f303b1b703721099cd86`. - Stable patch ID: `3027df409450d08b2c32383585597a39e06c6f53`, identical to the reviewed `f9cb4e54..e6e550f9` delta. - The exact delta is 4 files and 720 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused Rust state, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33362166929` completed successfully, Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This reducer owns security-sensitive correlation and terminal ordering, so its only raw-event entry point always invokes scope-first decoding. - Pending resolution methods must be called only after the corresponding sidecar transport command succeeds; the later process adapter owns that sequencing. - Terminal events intentionally clear unresolved turn-scoped requests so late tool or input results fail closed. - One semantic result remains readable after terminal state for later durable finalization and is cleared only when a new turn begins. - The package exports a new Rust module, but no production path constructs it in this pull request. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
7bb6cebeae |
feat(runner): normalize ACPX provider events (#12416)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now admits ACPX sidecar frames only after transport, scope, and payload validation > - Valid payloads still contain provider-native runtime event shapes > - Provider-native shapes must not cross the PRP boundary or diverge from direct Codex task activity > - This pull request maps the display-safe runtime subset into existing provider-neutral event families > - Stateful semantic-result, terminal, and reasoning-deduplication behavior remains reserved for the later provider adapter > - The benefit is a reviewable normalization boundary without selecting ACPX in production ## Linked Issues or Issue Description Refs #12415 Refs #12414 ## What Changed - Normalize validated ACPX text, reasoning, plan, status, tool, notice, and error updates into existing PRP activity families. - Keep reasoning contents private while preserving a reasoning activity boundary. - Map plan entries, usage, review-mode status, and tool lifecycle into bounded canonical payloads. - Generate one shared ACPX sidecar event/classification contract for TypeScript and Rust, with ASCII-only classification parity and bounded kind/title fields. - Preserve authoritative tool-call identity and classification even when the aggregate native event exceeds the generic frame budget. - Resolve display-only tool targets within the workspace under the provider host's path semantics; reject raw, unmarked, absolute, parent-traversing, URL-shaped, and unsafe drive-shaped values. - Redact and digest retained tool output with the existing durable policy. - Ignore provider inventory status updates that have no user-facing activity. - Leave semantic results and `done` updates to the stateful adapter so durable receipts and terminal events are not duplicated. - Add cross-language and Rust coverage for every mapping family, classifier parity, privacy, unsafe paths, redaction, bounded titles/kinds, and oversized tool-call preservation. - Document the normalization and display-path authorization boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `fe2ddfad2b5cb604b3244492257db0e6aec11d47` (`master` after #12415 merged). - Exact replay head: `b7f5588bf6e8e0f946ffa8869a3204c344808418`. - Stable patch ID: `fda62c7c20afc5ef9c75d07f163a466db82efabd`, identical to the prepared six-commit delta plus the focused oversized-tool-call review fix. - The exact delta is 14 files, 1,714 additions, and 60 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused protocol-generation, TypeScript sidecar, Rust normalization, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33361437835` completed 23/23 jobs successfully, Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This code controls what provider activity is retained and displayed, so malformed native values must not bypass the earlier decoder. - The function contract requires an already scope-checked and payload-validated runtime event; the future adapter must preserve that order. - Tool classification and identity are security-relevant authorization inputs and remain explicit even when optional aggregate display data is dropped for bounds. - Repeated reasoning chunks require stateful suppression. This mapper exposes a privacy-safe start boundary and the later adapter owns per-turn deduplication. - Semantic results and terminal authority intentionally produce no activity here; the later adapter must commit them through the durable operational paths. - The package exports new generated and Rust normalization surfaces, but no production path invokes them in this pull request. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
fe2ddfad2b |
feat(runner): validate ACPX event payloads (#12415)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The runner needs a bounded process boundary for each qualified provider runtime > - The ACPX transport now verifies frame shape, sequence, run scope, and turn scope > - The sidecar schema keeps event payloads open so each event family needs a second validation boundary > - A later provider adapter must not retain or act on malformed payload fields > - This pull request validates and redacts package-local payloads and keeps the provider unselected > - The benefit is a typed fail-closed boundary before provider state or semantic tools can consume an event ## Linked Issues or Issue Description Refs #12414 Refs #12412 ## What Changed - Decode sidecar payloads only after run and turn scope validation passes. - Limit each decoded payload to 256 KiB. - Add typed payload variants for runtime events, permission requests, input requests, semantic tool calls, terminal events, process events, and diagnostics. - Admit only the nine runtime event shapes emitted by the reviewed Codex ACPX sidecar. - Validate runtime text, plan entries, tool locations, semantic result identities, notices, errors, and terminal status values. - Validate input requests against `paperclip.question_set.v1`. - Reject duplicate question IDs and duplicate option IDs within one question. - Require bounded control identities and object-shaped operational values. - Redact diagnostic, error, process, permission, tool, and retained runtime values before they can enter provider state. - Add six integration tests for every admitted shape, malformed values, scope-before-decode ordering, size limits, question ambiguity, and secret redaction. - Document the payload boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `3db24d9366831559b1219782475e760ec041b639` (`master` after #12414 merged). - Exact replay head: `de045b42b5b52cca6c3021380747c56693ccd179`. - Stable patch ID: `90a6f0ed68b2ca7fa5397a8bf93e5e95df5bb58c`, identical to the reviewed `972a3b38..9bb85e93` delta. - The exact delta is 4 files and 806 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused Rust payload, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33360832792` completed 23/23 jobs successfully, Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This decoder is a security boundary because later code can act on decoded semantic tool calls and input requests. - It validates event authority before it inspects a payload. - It fails closed on unknown runtime event types, malformed fields, ambiguous question identifiers, unsupported terminal states, and oversized payloads. - It applies the existing durable redaction policy to retained values. - The package exports a new Rust module, but no production path constructs it in this pull request. - A later provider adapter must preserve this validation order and must not consume raw sidecar payloads directly. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
3db24d9366 |
feat(runner): bind ACPX event scope (#12414)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The runner needs a bounded process boundary for each qualified provider runtime > - The package now has a fail-closed transport for the Codex ACPX sidecar > - A valid sidecar frame can still name the wrong run or turn > - A later provider adapter must reject those events before it maps or persists them > - This pull request adds package-local run and turn scope validation and keeps it unselected > - The benefit is an explicit authorization boundary without a production behavior change ## Linked Issues or Issue Description Refs #12412 Refs #12410 ## What Changed - Add an `AcpxEventScope` for one run and at most one active turn. - Validate run and turn identifiers before they enter scope state. - Make repeated binding of the same turn safe. - Reject a second active turn and a stale turn clear. - Require exact run and active turn bindings for operational, tool, input, permission, and terminal events. - Permit process and diagnostic events without a scope because they can describe the sidecar process itself. - Validate every optional run or turn binding on process and diagnostic events. - Add an integration-test file for all seven event families, missing scope, cross-run scope, cross-turn scope, inactive turns, turn lifecycle, and invalid identifiers. - Document the event authorization boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `75708fec6d421a247ba2fc832997de24ed10a085` (`master` after #12412 merged). - Exact replay head: `88bb248442b8f628c20e977d2c2dbc21d85fb6dd`. - Stable patch ID: `0b6443b1bc32ed244f650936026367dd84bcfd65`, identical to the reviewed `c5654218..972a3b38` delta. - The exact delta is 4 files and 280 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused Rust scope, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33360199404` completed successfully, Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - Event scope is a security boundary because it rejects data from another run or turn. - The validator fails closed on missing, malformed, stale, or cross-scope identifiers. - Process and diagnostic events can remain global, but any scope they provide must be valid. - The package exports a new Rust module, but no production path constructs it in this pull request. - A later provider adapter must bind and clear the exact turn around each sidecar turn. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.831.0-canary.3 |
||
|
|
75708fec6d |
feat(runner): add ACPX sidecar transport (#12412)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The runner needs a bounded process boundary for each qualified provider runtime > - The package now provides a reviewed Codex-only ACPX sidecar executable > - Runnerd does not yet have a strict client for that sidecar protocol > - A later provider adapter must not mix process transport defects with provider mapping > - This pull request adds the package-local Rust transport and keeps it unselected > - The benefit is a tested fail-closed boundary for the later Codex provider adapter without a production behavior change ## Linked Issues or Issue Description Refs #12410 Refs #12386 ## What Changed - Add a Rust client for the generated ACPX sidecar v2 contract. - Validate the executable path, launch arguments, request timeout, and shutdown grace before process start. - Require exact request identities and contiguous event sequence numbers. - Reject replayed events, sequence gaps, wrong response identities, malformed frames, unknown fields, and unsupported protocol versions. - Bound stdout frames to 1 MiB and buffered events to 512 entries. - Bound event poll timeouts to 120 seconds before any `Instant` arithmetic. - Buffer valid events that arrive while a command waits for its response. - Treat an empty event poll as a normal timeout without poisoning the transport. - Discard retained events and reject all polling after a terminal transport failure. - Terminate the process group after a timeout, transport failure, or protocol failure. - Keep a valid sidecar command rejection separate from a transport failure so the next command can run. - Redact and bound stderr diagnostics before they enter an error. - Add a deterministic fake sidecar and twelve integration tests for success, polling, timeout bounds, poisoned queues, replay, gaps, identity mismatch, rejection, event floods, oversized frames, and secret redaction. - Document that the transport remains package-local and does not change runnerd provider selection. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `9ad8dbffa0a4759dcda2769042d6e8f02adcdf8d` (`master` after #12410 merged). - Exact replay head: `5c41111c4f9564405a6e87a02b6cf253a4424e5f`. - Stable patch ID: `60aca2620fdbb73fbbc203e928d39dcd450e085b`; this preserves the reviewed `1334a7f5..c5654218` six-file delta and keeps trusted bounded-reader failures distinct from fully redacted child stderr. - The exact delta is 6 files and 896 additions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, or migration change. - Focused Rust transport, package, repository, security, and Greptile checks: **PASSED** on the replayed exact head. Full CI run `33359202433` is green; its failed-job retry passed the two unrelated flaky jobs without a patch change. Greptile is exact-head 5/5, all security checks pass, and no review threads remain unresolved. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - The transport crosses an untrusted process boundary and is security-sensitive. - It fails closed on malformed frames, identity drift, event replay, sequence gaps, queue overflow, frame overflow, timeout, process exit, and channel failure. - A terminal failure clears retained events before it marks the transport unavailable. - It redacts and bounds retained diagnostics before it returns them to a caller. - A valid remote command rejection does not corrupt the transport state. - The package exports a new Rust module, but no production path constructs it in this pull request. - The later provider adapter must validate run, turn, session, model, and tool bindings before it selects this transport. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5.6, agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
9ad8dbffa0 |
feat(runner): add Codex ACPX sidecar (#12410)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner needs a bounded process boundary for each qualified provider runtime. > - The ACPX contract, Codex profile, structured questions, and recovery rules now exist in the package. > - The package does not yet provide an executable that applies those rules to a real Codex ACPX host. > - Provider admission must retain process, credential, and cleanup ownership on every failure path. > - A production selector must not depend on an unreviewed provider-generic sidecar. > - This pull request adds one installable Codex-only ACPX sidecar and leaves it unselected. > - The benefit is a testable package boundary for later runnerd integration without changing current execution selection. ## Linked Issues or Issue Description Refs #12409 Refs #12386 This pull request implements the Codex-only executable for the ACPX sidecar contract merged in #12386. It builds on the question conformance gate merged in #12409. Runnerd and the server do not select this executable in this pull request. ## What Changed - Publish the `paperclip-runner-acpx-sidecar` package binary and document its current boundary. - Add a versioned stdin/stdout sidecar that admits only the qualified Codex ACPX profile and exact initialized model. - Support atomic session open, run attachment, turn start and cancellation, tool and input resolution, session read and snapshot, safe suspension, close, and recovery identity checks. - Bind runtime directory, workspace, permission mode, provider identity, run identity, and semantic tool catalog before use. - Validate completion and blocked results against the PRP result contract. Bound pending tools, pending inputs, messages, events, usage, diagnostics, and errors. - Redact provider output and convert file locations to bounded workspace-relative display data. Do not treat displayed paths as file-access authority. - Harden verified executable loading, module resolution, launch environment filtering, process-group guardianship, and provider termination. - Retain managed credentials and every failed-admission resource until the exact provider cleanup proves ownership was released. - Keep failed-admission cleanup alive with bounded backoff until the provider exits. Do not scrub credentials or admit a replacement while cleanup still owns the provider. - Use one runtime-host cleanup-owner registry and preserve sequential cleanup retries across command timeouts and shutdown. - Arm a credential-free same-group watchdog before provider admission so guardian death reaps even a stopped provider; retain an independent kernel EOF proof before releasing credentials. - Add sidecar process, lifecycle, location, package, driver, credential, installation, runtime-adapter, and runtime-host regression tests. - Add `tsx` as a package test-only development dependency for the real TypeScript sidecar process test. ## Verification - Replay base: `b93ad538b63c81a1e3d24bbb54c02f8effdea787` (`master` after #12409 merged). - Exact replay head: `ca7e93f4385c37289c82b360ca8def0d88c1bd00`. - Stable patch ID for the resolved 18-file delta: `d293717a1e9f2485b61c553c58ea37690fc0a4fa`. - The intended pull request delta contains exactly these 18 files: - `packages/paperclip-runner/README.md` - `packages/paperclip-runner/package.json` - `packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts` - `packages/paperclip-runner/src/cli/acpx-runtime-sidecar.test.ts` - `packages/paperclip-runner/src/cli/acpx-sidecar-lifecycle.ts` - `packages/paperclip-runner/src/cli/acpx-sidecar-locations.ts` - `packages/paperclip-runner/src/cli/acpx-sidecar-locations.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-credentials.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-credentials.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts` - `packages/paperclip-runner/src/drivers/acpx/installation-integrity.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `packages/paperclip-runner/test/acpx-codex-package-contract.test.mjs` - The resolved combined delta is 4,725 additions and 665 deletions; it preserves the lower-PR runtime-close semantics, repairs stale successful-admission fixtures, deterministically observes renewed reconciliation, accepts authoritative same-host cleanup recovery without dropping pending owners, ignores superseded cleanup failures after a newer owner recovers, and requires both guardian exit and independent provider-lifetime EOF before releasing cleanup or credential ownership. A readiness-gated, credential-free watchdog also reaps a stopped provider if its guardian is externally killed. - This change updates the runner package manifest, README, and test-only dependencies. It does not change `pnpm-lock.yaml`, a workflow, migration, server route, UI path, runnerd selection, or current direct-adapter behavior. - Focused GitHub verification: **PASSED** for the sidecar process, lifecycle, location, package-contract, driver, credential, installation-integrity, runtime-adapter, and runtime-host suites on the replayed head. - Package verification: **PASSED** for the clean tarball, Node shebang, and exact binary mapping on the replayed head. - GitHub Actions and security checks: **PASSED** for the replayed exact head; full CI run `33357846557` completed 23/23 jobs successfully, and Superagent, Socket, Snyk, supply-chain, and contributor-trust checks are green. Storybook was intentionally skipped because this PR does not touch its paths. - Greptile: **5/5** on the exact head with zero unresolved review threads. - No local test result is claimed. GitHub Actions is the authoritative verification environment for the replayed revision. ## Risks This change has medium security and lifecycle risk because the new executable crosses a process, credential, filesystem, and provider boundary. The sidecar fails closed on unsupported providers, models, permissions, identities, catalogs, forms, commands, and persistent-state deletion. A cleanup owner can remain alive until a stubborn provider exits. Its retries use bounded backoff, and admission stays closed while ownership remains. Command and shutdown waits remain bounded without abandoning the underlying cleanup. The new `tsx` dependency is development-only. The package exposes a new binary, but no runnerd, server, UI, or direct-adapter path starts it in this pull request. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
b93ad538b6 |
test(runner): add question adapter conformance (#12409)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner maps provider questions to one versioned Paperclip contract. > - Codex and ACPX now perform that mapping through separate adapters. > - Separate adapter tests do not prove that both paths preserve the same user-visible form. > - Fixture validation must also match production behavior for optional answers and unsupported patterns. > - This pull request adds shared fixtures, validation, and cross-adapter conformance checks. > - The benefit is a reusable question contract for later providers without enabling a new runtime. ## Linked Issues or Issue Description Refs #12408 This pull request builds on the Codex ACPX question bridge merged in #12408. It adds fixture and generator checks for the existing Codex and ACPX question adapters. It does not add another provider or production execution path. ## What Changed - Add a canonical ACPX form fixture and native response. Mark the equivalent Codex fixture field as required. - Add shared validation for question IDs, option IDs, answer modes, required answers, text bounds, numeric bounds, and response shapes. - Evaluate fixture-only regular expressions in a bounded child process. Reject patterns that cannot finish safely. - Validate ACPX fixtures against a manifest-side mirror of the production form projection. Reject free-text ACPX patterns, but ignore patterns on enumerated option fields. - Accept explicit empty optional answers and omit them from the projected ACPX response, which matches the production parser. - Validate every question fixture during manifest generation and regenerate the checked-in manifest. - Add cross-adapter tests that compare user-visible presentation while preserving provider-owned IDs and provider-specific response conversion. - Add negative regressions for malformed forms, invalid responses, unsafe patterns, special property names, and projection drift. ## Verification - Replay base: `4fe3189f0256873a359d2d53c209076919fd1c3b` (`master` after #12408 merged). - Exact replay head: `0532e7dfbb5a246033ffeef55a0c0013fdab07f1`. - Stable patch ID for the intended seven-file delta: `28154d86b2c37e0e8d442419e26703584852f67e`. - The intended pull request delta contains exactly these seven files: - `packages/paperclip-runner/protocol/fixtures/questions/acpx.json` - `packages/paperclip-runner/protocol/fixtures/questions/codex.json` - `packages/paperclip-runner/protocol/manifest.json` - `packages/paperclip-runner/scripts/generate-protocol-manifest.mjs` - `packages/paperclip-runner/scripts/protocol-contract.mjs` - `packages/paperclip-runner/src/contracts/question-adapter-conformance.test.ts` - `packages/paperclip-runner/test/protocol-contract.test.mjs` - The intended combined delta is 1,211 additions and 20 deletions. - This change does not add a dependency, lockfile update, migration, workflow, server route, UI change, documentation file, or production runtime change. - GitHub Actions run `33352004952` passed the complete matrix on retry at the unchanged exact head, including protocol/package verification, build, typecheck/release-registry, general and serialized server suites, canary, and all e2e shards. - Superagent, Socket, Snyk, contributor-trust, policy, and PR-review checks pass on the exact replay head. - Greptile reviewed the exact replay head at 5/5 with no blocking finding and zero unresolved review threads. - No local test result is claimed. GitHub Actions is the authoritative verification environment for the replayed revision. ## Risks This change has low runtime risk because it changes fixtures, generator validation, generated metadata, and tests only. Fixture pattern checks run in a child process with a one-second timeout and a bounded output buffer. The ACPX gate intentionally rejects free-text patterns because the production adapter has no bounded expression engine. It intentionally permits an explicit empty optional answer because production omits that answer from the native response. A validation mismatch can block manifest generation, but it cannot change server selection, direct adapters, or task-page behavior. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 mergecanary/v2026.831.0-canary.2 |
||
|
|
4fe3189f02 |
feat(runner): bridge Codex ACPX questions (#12408)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package gives provider sessions one normalized execution contract. > - The merged Codex ACPX path can run and recover settled turns. > - It cannot yet send a structured provider question through the existing Paperclip question boundary. > - Provider questions must not expose ACPX-specific data to later server integrations. > - Every pending provider request must also settle on resolution, handoff, cancellation, failure, or close. > - This pull request adds a bounded Codex ACPX form bridge inside the runner package. > - The benefit is a provider-neutral question flow with fail-closed lifecycle handling. ## Linked Issues or Issue Description Refs #12407 This pull request builds on the settled Codex ACPX recovery path merged in #12407. It adds only package-local structured-question support for Codex ACPX sessions. ## What Changed - Enable ACPX form elicitation for the Codex runtime and pass its handler through the runtime host boundary. - Normalize ACPX forms to `paperclip.question_set.v1` and emit `paperclip.runtime_request.v2` events. - Validate `paperclip.question_response.v1` resolutions before conversion to ACP form responses. - Support explicit resolution and durable handoff. Cancel pending requests on provider abort, stream failure, turn settlement, and session close. - Limit each session to 16 pending requests. Reject unsupported input modes, regular expression patterns, session-wide acceptance, stale turns, and late responses. - Fail closed under bounded event-queue pressure: cancel an input whose creation event cannot be retained, and preserve a live request when its durable-handoff event cannot be retained. - Persist pending-request facts in snapshots and reject recovery while a provider request is still pending. - Add focused driver, runtime-adapter, and runtime-host regression tests for round trips, aborts, stream failures, handoff, and handler forwarding. ## Verification - Replay base: `96421b0663d8b740ac5d5d53359aef65c5a158ca` (`master` after #12407 merged). - Exact replay head: `d8184502e1c4570d1003379365850f3419f64d82`. - Stable patch ID for the exact replay delta: `00807ebfcd1b153f759366db023437b681d69017`. - The pull request delta contains exactly these six files: - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - The exact combined delta is 716 additions and 14 deletions. - This change does not add a dependency, lockfile update, migration, workflow, server route, UI change, documentation file, or public package export. - GitHub Actions run `33351323368` passed the full matrix on the exact replay head, including Paperclip Runner verification, build, typecheck/release-registry, general and serialized server suites, canary, and all e2e shards. - Superagent, Socket, Snyk, contributor-trust, policy, and PR-review checks pass on the exact replay head. - Greptile reviewed the exact replay head at 5/5 with no blocking finding and zero review threads. - No local test result is claimed. GitHub Actions is the authoritative verification environment for the replayed revision. ## Risks This change has medium package-local risk because it connects provider-owned input to durable runner state. Unsupported modes and unbounded patterns fail closed. The pending-request limit bounds retained provider state. Provider abort, turn settlement, stream failure, and session close cancel live questions. A durable handoff expires the request before it interrupts the turn. Recovery rejects a snapshot that still contains a pending provider request. Existing direct adapters, server selection, and task-page behavior do not use this route. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 |
||
|
|
96421b0663 |
feat(runner): recover settled Codex ACPX sessions (#12407)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package keeps provider sessions durable across process restarts. > - The merged Codex ACPX backend can admit a new qualified session through the package factory. > - It cannot yet recover a settled session from a durable checkpoint. > - Recovery must prove the same provider identity, runtime root, workspace, and latest terminal settlement before it resumes. > - ACPX cannot yet prove continuity for a provider turn that was active when the process stopped. > - This pull request recovers only settled Codex ACPX checkpoints and rejects ambiguous or stale state. > - The benefit is fail-closed restart recovery without repeated work, silent session replacement, or recovery of an older semantic result. ## Linked Issues or Issue Description Refs #12406 This pull request builds on the Codex ACPX backend route merged in #12406. It adds only settled-session recovery and the package-local durability and filesystem checks that recovery requires. ## What Changed - Add settled-session recovery to the Codex ACPX harness driver and advertise resume support for that bounded path. - Keep provider recovery on the same persisted ACPX session. Do not permit a replacement provider session. - Require persisted run, normalized session, provider, profile, workspace, permission, result, terminal, and recovery-policy identities to agree. - Reopen the provider with the exact persisted ACPX identity and reject provider or qualification drift. - Restore the last source sequence, terminal history, semantic result, provider recovery policy, and normalized terminal fact before new work can start. - Clear a stale active-turn marker only when durable terminal history proves that exact turn settled. - Reject active-turn recovery when durable history cannot prove provider-turn continuity. - Require a semantic result to belong to the latest completed terminal settlement. - Reject an older completed semantic result when a later identical retry failed or was interrupted. - Reject resultless recovery unless the latest terminal turn completed successfully. - Bound terminal history and semantic-result recovery by entry count, aggregate bytes, fingerprint bytes, node count, and nesting depth before cloning or serializing persisted data. - Read the private workspace record through pinned namespace, runtime-root, record, and workspace identities. - Reject symbolic links, substituted directories, replaced records, invalid files, root workspaces, and workspace changes during admission. - Keep the recovery workspace lease pinned and revalidate it at the host and provider-spawn boundaries. - Retain and close a workspace lease that resolves after cancellation. Close a partially recovered provider session if lease cleanup fails. - Stage a valid isolated Codex credential in the runtime-open-boundary regression so the test reaches and proves the intended workspace revalidation fence. - Add focused recovery tests for settled checkpoints, terminal ownership, stale semantic results, active turns, identity drift, bounded persisted data, cancellation, directory substitution, record replacement, and spawn-boundary workspace replacement. ## Verification - Replay base: `30ef14edd4e7290d9eac43ca7b7835611933cc74` (`master` after #12406 merged). - Exact replay head: `3d1b16d5cda2dd72f83785c921a025cc57aab8d6`. - Stable patch ID for the exact replay delta: `10742d7db00f801b5723e7a8582c637261ceb0dd`. The source-stack combined patch was `4d7c9de72a0a30f6e33c935c092b745fe414c588`; the replay preserves the newer unconditional provider process-group containment from `master` while adding recovery workspace revalidation before spawn, plus the exact-head credential fixture correction exposed by GitHub Actions. - The exact pull request delta contains exactly 14 files: - `packages/paperclip-runner/src/backends/harness-driver-backend.ts` - `packages/paperclip-runner/src/backends/harness-driver-backend.test.ts` - `packages/paperclip-runner/src/backends/native-backend-factory.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/recovery-identity.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts` - `packages/paperclip-runner/src/native-session-runtime.ts` - `packages/paperclip-runner/src/native-session-runtime.test.ts` - The exact combined delta is 2,279 additions and 73 deletions. - This delta does not change dependencies, `pnpm-lock.yaml`, workspace configuration, workflows, migrations, server selection, UI behavior, or public package exports. - Focused GitHub recovery tests: **PASS**. The exact-head Build job passed the harness backend, native runtime, Codex ACPX driver, runtime host, runtime sandbox, runtime adapter, and backend factory suites as part of all 751 TypeScript runner tests. - GitHub Actions: **PASS** for exact head `3d1b16d5cda2dd72f83785c921a025cc57aab8d6`. Every applicable job passed. The Storybook visual regression skipped intentionally because this package-only delta does not touch UI or Storybook paths. - Security checks: **PASS** for the exact head. Superagent, Snyk, both Socket checks, and contributor trust completed successfully. - Greptile: **5/5** for the exact head, with no open P1/P2 findings, recommendations, or follow-ups. - No local test result is claimed. GitHub Actions is the authoritative verification environment for the replayed revision. ## Risks This change has medium package-local risk because it admits persisted state back into a provider session. Recovery fails closed when an active provider turn has no matching terminal fingerprint, when a semantic result is not owned by the latest completed settlement, when any durable identity changes, or when the workspace cannot remain pinned through provider spawn. Recovery never selects a replacement provider session. Bounds prevent oversized or deeply nested persisted state from consuming unbounded work before validation. The workspace lease prevents path substitution during recovery admission. Existing direct adapters and the Codex app-server driver do not use this ACPX recovery route. This change does not add a migration, dependency, lockfile update, workflow, server route, UI surface, public export, or production rollout flag. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 |
||
|
|
30ef14edd4 |
feat(runner): wire the Codex ACPX backend (#12406)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package gives provider runtimes one normalized session boundary. > - The merged Codex ACPX driver implements that boundary and keeps its cleanup ownership bounded. > - The package backend factory still needs a narrow route from a persisted Codex ACPX execution input to that qualified driver. > - The route must validate the stored qualification snapshot and reject unsupported providers before runtime admission. > - This pull request wires only the qualified Codex ACPX driver into the package-local backend factory. > - The benefit is a fail-closed backend construction path without enabling a server adapter, changing execution selection, or adding another provider. ## Linked Issues or Issue Description Refs #12405 This pull request builds on the Codex ACPX harness driver merged in #12405. It adds only the package-local backend factory route for that driver. ## What Changed - Add an internal Codex ACPX native backend constructor. - Require provider kind `acpx` and agent `codex` at the provider-specific boundary. - Resolve the qualified Codex ACPX profile for the requested model. - Compare the persisted driver kind, protocol version, ACPX version, agent profile, package versions, runtime package fields, and command digest with the qualified profile. - Compose the existing native system instructions and task constraints for the Codex ACPX driver. - Route qualified Codex ACPX inputs through the native backend factory only when the caller supplies an explicit instance runtime directory. - Pass the scoped environment, managed credential source, dynamic tools, and ACPX tool handler through the factory boundary. - Keep Pi, Claude, OpenCode, managed Claude, AgentCore, and every other deferred ACPX agent unavailable. - Add factory tests for qualified construction, the explicit runtime-root requirement, unsupported ACPX agents, and qualification-snapshot drift. - Keep ACPX construction lazy. Reading the backend descriptor does not start ACPX transport or a provider process. ## Verification - Replay base: `74aabb7ea6c5cf373f2254e5f854a5233b745ddc` (`master` after #12405 merged). - Exact replay head: `827090a0cff870eedb99fa1b5cfda8bb87efa515`. - Stable patch ID for the exact replay delta: `e0f6733a5a124a4fb93155257358b966c354a176` (identical to the original narrow source patch). - The exact pull request delta contains exactly three files: - `packages/paperclip-runner/src/backends/codex-acpx-native-backend.ts` - `packages/paperclip-runner/src/backends/native-backend-factory.ts` - `packages/paperclip-runner/src/backends/native-backend-factory.test.ts` - The exact source delta is 193 additions and 10 deletions. - This delta does not change dependencies, `pnpm-lock.yaml`, workspace configuration, workflows, migrations, server selection, UI behavior, or public package exports. - Focused GitHub test coverage: **PASS**. The exact-head Build job passed all six native backend factory tests and all 720 TypeScript runner tests. - GitHub Actions: **PASS** for exact head `827090a0cff870eedb99fa1b5cfda8bb87efa515`. Every applicable job passed. Failed-job-only reruns cleared unrelated database timeout and server concurrency flakes without changing the patch. The Storybook visual regression skipped intentionally because this backend-only delta does not touch UI or Storybook paths. - Security checks: **PASS** for the exact head. Superagent, Snyk, both Socket checks, and contributor trust completed successfully. - Greptile: **5/5** for the exact head, with no open P1/P2 findings, recommendations, or follow-ups. - No local test result is claimed. GitHub Actions is the authoritative verification environment for the replayed revision. ## Risks This change has low package-local runtime risk. It adds a new branch to the native backend factory, but no server or runnerd factory selects an ACPX execution in this pull request. The route fails closed when the runtime directory is absent, the agent is not Codex, or the persisted qualification snapshot differs from the qualified Codex profile. The constructor repeats the provider-kind and agent checks as a second boundary. Existing direct adapters do not use this route. The change does not add a migration, dependency, lockfile update, workflow, UI surface, public export, or production rollout flag. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 P1/P2 findings, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
74aabb7ea6 |
feat(runner): add Codex ACPX harness driver (#12405)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package hides provider behavior behind the `HarnessDriver` contract. > - The admitted Codex ACPX runtime can open sessions, execute bounded turns, and use run-scoped semantic tools. > - The package still needs a driver that translates those turns into canonical PRP events and semantic results. > - The driver must preserve terminal facts under backpressure and retain cleanup ownership after caller-facing timeouts. > - Abort can win after the host transfers a credential-bearing admission but before the adapter body starts, so that boundary must publish a completed cleanup proof without changing the exact cancellation reason. > - An external close can join an autonomous reconciliation attempt; if it joins the exhausted final attempt, its batched intent must create one new bounded generation when that exact cleanup fails. > - A late cleanup failure needs a finite reconciliation budget that cannot renew itself without a distinct external intent. > - This pull request adds the Codex-only ACPX harness driver and the package-local lifecycle rules it needs. > - The benefit is a tested provider-neutral session boundary for later runnerd and server integration. ## Linked Issues or Issue Description Refs #12404 **Subsystem affected** This change affects `packages/paperclip-runner`, the Codex ACPX driver, and the provider-neutral native session runtime. **Problem or motivation** The package has an admitted Codex ACPX session, bounded turn control, and authenticated semantic tools. It does not have a `HarnessDriver` implementation that joins those parts and emits canonical PRP events. It also needs bounded ownership for provider cleanup that settles after a caller-facing timeout. Cancellation can win after the host schedules runtime admission and transfers the staged credential but before the adapter body starts; that rejected admission must still prove that provider cleanup is complete so the credential can be scrubbed and later admission can proceed. Separately, an external close that coalesces onto an exhausted autonomous reconciliation must not lose its cleanup intent if that exact protocol or provider-process cleanup fails. **Proposed solution** Add a Codex-only harness driver. It opens the admitted host, executes one active turn, normalizes ACPX events, dispatches run-scoped tools, and commits one schema-valid completion or blocked result. It provides bounded event storage, interruption, transcripts, usage, snapshots, diagnostics, and ordered close behavior. The native session runtime quarantines incomplete cleanup before another session can enter the same cleanup domain. The ACPX adapter records the immutable origin and attempt number of each exact close attempt. Autonomous reconciliation failures stay inside the three-attempt budget of the generation that created them. External callers that join an attempt are represented by one idempotent batched intent: success consumes it, failure on an earlier attempt uses the remaining same-generation retries, and failure on the exhausted final attempt creates exactly one new bounded generation. Both direct and late protocol/provider cleanup outcomes use the same rule. At the adapter entry boundary, an already-aborted admission transfers an already-complete cleanup proof before rethrowing the exact abort reason; the host retains credential cleanup until that proof settles. **Alternatives considered** The multi-provider integration driver was not copied because it mixes deferred providers and recovery behavior into the Codex path. Direct server registration was also deferred because this package slice must remain inactive and independently safe. Relabeling a coalesced autonomous attempt as external was rejected because it would let observers replenish retry budgets; starting another protocol close before the exact retained attempt settles was rejected because it would overlap cleanup ownership. **Roadmap alignment** This is package-local production hardening for the experimental runner. It does not enable a new adapter or change current agent execution selection. ## What Changed - Add a Codex-only ACPX `HarnessDriver` and session implementation. - Advertise only implemented capabilities. Keep resume, steering, runtime request resolution, runtime request handoff, goals, and thread lineage unavailable. - Emit canonical PRP turn, transcript, tool execution, final reply, result, failure, interruption, and usage facts. - Dispatch authorized dynamic tools through the authenticated semantic bridge. - Validate and commit one completion or blocked result with disposition and conflict checks. - Add stable bounded event identities, one-active-turn admission, terminal capacity reservation, and bounded interruption. - Redact authorization credentials from emitted events and retained transcripts. - Add read, reconcile, transcript, usage, snapshot, status, interruption, and ordered close surfaces. - Retain and quarantine host cleanup that outlives a caller-facing close bound. - Gate new native-session admission on prior cleanup in the same cleanup domain. - Preserve durable success and governed waits while provider cleanup continues under bounded ownership. - Transfer a completed cleanup proof when cancellation wins before the Codex adapter body, then preserve the caller's exact abort reason. - Add a host-level regression proving staged credentials are scrubbed, the credential lease can be reacquired, and a later runtime admission succeeds after that pre-entry abort. - Tag each exact ACPX close attempt with an immutable external or reconciliation origin and immutable reconciliation attempt number. - Keep timed-out autonomous reconciliation failures inside their originating three-attempt budget. - Batch concurrent external callers that join one reconciliation attempt so they cannot mint independent generations. - Consume a joined external intent on successful cleanup and on an earlier failed attempt that still has same-generation retries. - Renew exactly one bounded generation when a joined external intent reaches a failed, exhausted final reconciliation attempt. - Treat both protocol-close and provider-process cleanup failures as failed intent settlement, including non-timeout and timed-out late paths. - Prevent a coalescing external observer from relabeling an immutable autonomous attempt. - Reset the finite reconciliation budget only for a distinct external late-failure generation or one failed batched intent on an exhausted final attempt. - Isolate persistent-cleanup tests by cleanup domain and attach expected rejection handlers before fake timers release them. - Stabilize cleanup-settlement assertions exposed by GitHub Actions: observe retained proofs without relying on callback order, wait for the credential lease release rather than only the preceding credential-file deletion, and use a supported scalar size assertion instead of an unavailable Set matcher. - Add focused tests for driver behavior, event validation, bounded buffers, cleanup quarantine, admission gating, immutable attempt origins, final-attempt intent batching, direct and late cleanup failures, late success consumption, bounded reconciliation, exact pre-entry cancellation, credential recovery, and durable native-session outcomes. ## Verification - Exact head: `584cc420f6ca249cdc0a831779192ca827764d96`. - Stable patch ID for the combined exact delta: `5329d8123baf62c339a15bdff16717b3803ebb74`. - Stack position: #12404 is merged. This pull request targets `master`. #12406 is stacked on this pull request. - The exact pull request delta contains eight files: - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-acpx-driver.test.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `packages/paperclip-runner/src/native-session-runtime.ts` - `packages/paperclip-runner/src/native-session-runtime.test.ts` - `git diff --check` passed for the exact eight-file delta. - This delta does not change dependencies, `pnpm-lock.yaml`, workflows, migrations, server selection, UI behavior, or production runner wiring. - GitHub previously exposed an unsupported Set matcher in the cleanup-settlement regression; this exact delta uses the repository-supported scalar `size` assertion without changing the tested behavior. - GitHub Actions: **PASS** for the exact head. The complete matrix is green after a failed-job-only rerun cleared one unrelated `plugin-worker-manager-duplex` flake; no patch or restack occurred. - Security checks: **PASS** for the exact head (Superagent, Snyk, Socket, and contributor trust). - Greptile: **PASS, 5/5** on the exact head with no open P1/P2 findings, recommendations, or follow-ups. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this revision. ## Risks This change has medium package-local risk. It adds a new driver and changes native-session cleanup coordination. A lagging event consumer could otherwise lose terminal state. The driver reserves terminal capacity and rejects new work when bounded storage cannot safely accept it. A stalled, rejected, or late provider close could otherwise overlap a new session, retain credentials indefinitely, lose an external cleanup request, or consume unlimited retries. Cleanup-proof transfer keeps the staged credential owned across the pre-entry abort race, while the host scrubs it only after the adapter proves that no provider resource exists. Cleanup quarantine blocks conflicting admission and keeps exact attempts owned. Immutable attempt origins and attempt numbers prevent autonomous retries and coalesced observers from silently replenishing the cap. One batched external intent can renew one generation only after the exhausted final attempt fails; earlier failures remain within the original generation, and success consumes the intent. Each renewed generation remains capped at three autonomous attempts. The driver reports recovery and other unimplemented capabilities as unavailable. No server or runnerd factory selects this driver in this pull request. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 P1/P2 findings, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.831.0-canary.1 |
||
|
|
3623a369aa |
feat(runner): bind semantic tools to ACPX sessions (#12404)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner package provides a provider-neutral execution boundary. > - The admitted Codex ACPX runtime needs access to the run-scoped semantic tool catalog. > - The tool endpoint contains an authentication secret and must stay outside durable session state. > - ACPX permission requests must follow the same run policy as semantic tool authorization. > - The deny-all mode must reject every request, including requests for runner-owned MCP tools. > - This pull request composes the authenticated loopback bridge into the admitted Codex runtime. > - The benefit is a closed tool catalog with fail-closed permissions and bounded cleanup. ## Linked Issues or Issue Description Refs #12403 **Subsystem affected** This change affects `packages/paperclip-runner` and its package-local Codex ACPX runtime boundary. **Problem or motivation** The package has an authenticated semantic MCP bridge and an admitted Codex ACPX session. The two components are not connected. A direct connection must not persist the bridge token. It must not allow unrelated MCP operations. The deny-all mode must remain closed for runner-owned MCP requests. **Proposed solution** The runtime host starts one loopback bridge when semantic tools are configured. It passes an ephemeral bearer binding to ACPX. The adapter projects that binding into the ACP runtime configuration. It sends each permission request through the existing ACPX permission policy. The deny-all mode rejects every request. Other requests either receive the policy result or delegate to an available coordinator. **Alternatives considered** Persisting MCP configuration with the ACPX session was rejected because it would retain authentication material. A global MCP endpoint was rejected because it would weaken run isolation. **Roadmap alignment** This is package-local hardening for the existing experimental runner work. It does not enable a new user-facing adapter. ## What Changed - Start and own one authenticated semantic MCP bridge when a host receives semantic tool options. - Pass one ephemeral loopback MCP binding to the Codex ACPX adapter. - Keep the bridge token out of the persisted environment and ACPX session options. - Map the runner-owned HTTP MCP binding into ACPX runtime configuration with a bearer header. - Apply the existing ACPX permission policy to runtime permission requests. - Keep the deny-all mode closed for runner-owned MCP requests. - Delegate only the permission decisions that require a coordinator. - Revoke the tool bridge after the runtime close attempt settles, including when runtime close fails. - Release staged credentials only after the exact runtime close succeeds. - Add focused host and adapter tests for bridge dispatch, secret isolation, fail-closed permissions, delegation, and cleanup. ## Verification - Exact head: `8ec3bec234beb56dfe744099ff9a45109fc583bc`. - Stack position: #12403 is merged. This pull request targets `master`. #12405 is stacked on this pull request. - The exact pull request delta contains four files: - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `git diff --check` passed for the exact four-file delta. - This delta does not change dependencies, `pnpm-lock.yaml`, workflows, migrations, server selection, UI behavior, or production runner wiring. - GitHub Actions: **PASS** for the exact head, including policy, build, typecheck/release, server, workspace, serialized-server, canary, and e2e lanes. An unrelated fixed-port `EADDRINUSE` failure in `loopback-listener.test.ts` passed on the targeted GitHub rerun without a patch change. - Security checks: **PASS** for the exact head, including Superagent, Snyk, contributor trust, and Socket. - Greptile: **5/5** for the exact head with no open P2s, recommendations, follow-ups, or review threads. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this revision. ## Risks The main risk is secret or permission leakage at the ACP boundary. The host passes the bearer token only in ephemeral runtime configuration. It does not put the token in the persisted environment or ACPX session options. The existing permission policy controls every ACPX permission request. The deny-all mode rejects runner-owned MCP requests too. Another risk is partial cleanup. The host revokes the tool bridge after the runtime close attempt settles. It retains staged credentials if the exact runtime close fails. This pull request stays inside the runner package and does not select the experimental runner in the server. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5.6, extended reasoning, repository tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 mergecanary/v2026.831.0-canary.0 |
||
|
|
57449579ca |
feat(runner): add bounded ACPX turn lifecycle (#12403)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The admitted Codex ACPX runtime can open and recover a verified session. > - It cannot yet accept a provider prompt through the narrow host port. > - Turn admission must bound durable identity and prompt payloads. > - Shutdown must cancel an active turn and release runtime resources in a bounded way. > - A cancellation timeout must not leave the runtime, command lease, or staged credentials alive indefinitely. > - This pull request adds the package-local turn lifecycle and its cleanup rules without production wiring. > - The benefit is one explicit and testable prompt boundary for the later harness driver. ## Linked Issues or Issue Description Refs #12402 **What would you like to improve?** The package-local ACPX host stops at session admission. A later driver needs to submit a prompt, consume typed ACP events, wait for the terminal result, cancel work, and close the session. Passing the full third-party runtime through the host would bypass the existing trust and cleanup boundary. **Why is this important?** Provider prompts can be large. Turn identifiers participate in durable correlation. Concurrent turns can make replay and cancellation ambiguous. Shutdown must also stop an active prompt before credentials and verified command resources are released. A provider that does not finish cancellation must not block all remaining cleanup indefinitely. **Suggested approach** Add a minimal turn interface to the admitted runtime port. Accept one prompt turn at a time. Bound the request identity and text before the runtime sees them. Map the call to ACPX prompt mode with the admitted session handle. Track the active turn and request cancellation before ordered runtime cleanup. Bound the cancellation wait. Continue runtime and command cleanup after that timeout. Release staged credentials only after the exact runtime close succeeds. **Additional context** This pull request builds on #12402. It does not attach semantic tools, normalize provider events, create a harness driver, start runnerd, register production execution, or change server, UI, or direct-adapter behavior. ## What Changed - Add a narrow ACPX turn input and result and event lifecycle to the admitted runtime port. - Map prompt turns to the exact persistent ACPX session handle. - Support abort signals without adding steering or attachments. - Reject empty, whitespace-normalized, or oversized request identities. - Reject prompt text larger than one MiB before third-party code executes. - Permit only one active turn per host. - Clear the active turn only after the canonical ACPX result settles. - Reject new turns as soon as shutdown starts. - Cancel an active turn before runtime, credential, and command cleanup. - Bound the cancellation wait to two seconds. - Continue runtime and command cleanup when turn cancellation fails or reaches its timeout. - Release staged credentials only after the exact runtime close succeeds. - Keep the cancellation handle and credential lease when runtime cleanup remains retryable. - Coalesce concurrent close calls and report all cleanup failures in one aggregate error. - Add focused host and adapter tests for turn mapping, bounds, concurrency, cancellation, timeout cleanup, credential retention, and late-turn rejection. ## Verification - Exact corrected head: `57e1edfcfc496bd9688c1ecf22f2d402c6bb2079`. - The pull request delta contains four files: - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `git diff --check` passed for the exact corrected delta. - This delta does not change dependencies, `pnpm-lock.yaml`, workflows, migrations, server selection, UI behavior, or production runner wiring. - Full GitHub PR workflow passed in [run 33343457544](https://github.com/paperclipai/paperclip/actions/runs/33343457544): 28 successful checks, including runner verification/build, typecheck, all test shards, canary, and e2e; Storybook skipped by path as expected. - Greptile is 5/5 on the exact corrected head with no blocking failure and zero unresolved review threads. - Superagent Security, Snyk, contributor trust, and commitperclip passed on the exact corrected head. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this revision. ## Risks The primary risk is ambiguous concurrent execution. The host admits only one active turn and releases that slot from the canonical ACPX terminal result. Another risk is partial shutdown. The host requests cancellation first and waits for at most two seconds. It then attempts runtime and command cleanup even if cancellation fails or reaches the timeout. It releases staged credentials only after the exact runtime close succeeds. If runtime cleanup fails, the host keeps the cancellation handle and credentials for a later cleanup attempt. This pull request does not register the runtime for production use. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
9036d3c484 |
feat(runner): add authenticated semantic MCP bridge (#12402)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Native providers can receive only the semantic operations authorized for one run. > - Codex ACP consumes those operations through an MCP endpoint. > - The endpoint must be private, authenticated, bounded, and deterministic under retries. > - It must not advertise runner-private operations or allow callers to replace terminal-result schemas. > - This pull request adds a provider-neutral loopback MCP bridge with those controls. ## Linked Issues or Issue Description **What would you like to improve?** The runner has a run-scoped semantic catalog and dispatcher, but the ACPX runtime needs a secure transport for that catalog. A generic local MCP server could expose extra operations, accept ambiguous tool definitions, or execute the same call twice after a retry. **Why is this important?** Semantic tool presence is part of the authorization boundary. Undiscoverable operations must remain unavailable. Terminal completion and blocked-result schemas must not be replaceable. Duplicate call identities must be idempotent, and conflicting duplicates must fail closed. **Suggested approach** Bind one MCP endpoint to `127.0.0.1` for each admitted runtime. Require a random bearer secret. Compile the closed tool schemas before listening. Keep private operations out of `tools/list`. Validate and fingerprint each call before dispatch. Bound request size, result size, time, and retained call identities. Abort active operations on timeout, cancellation, or bridge close. **Additional context** #12401 is merged. This PR does not attach the bridge to ACPX, register a provider, or change any server or direct-adapter behavior. ## What Changed - Add a provider-neutral runner semantic MCP bridge bound only to IPv4 loopback. - Require constant-time bearer authentication before MCP operations. - Expose only the supplied public catalog plus fixed completion and blocked-result tools. - Keep runner-private operations callable by trusted extensions but absent from discovery. - Reject invalid names, duplicate definitions, public/private collisions, and terminal schema replacement. - Compile JSON Schema validators before accepting traffic. - Validate calls before dispatch and replay identical duplicate identities exactly once. - Treat numeric and string JSON-RPC identities as distinct and reject conflicting duplicates. - Bound request bodies, result text, timeouts, retained identities, and concurrent capacity. - Terminate oversized request bodies, preserve successful mutation outcomes, and keep complete semantic results. - Propagate MCP cancellation and abort active calls during close. ## Verification - Exact verified head: `e5070e235448680e480e8d3f66bb46ac62d71c8e`. - Full GitHub PR workflow passed in [run 33342776925](https://github.com/paperclipai/paperclip/actions/runs/33342776925), including runner verification/build, typecheck, all test shards, canary, and e2e. - Greptile is 5/5 on the exact head with zero unresolved review threads. - Superagent Security, Snyk, contributor trust, and commitperclip passed on the exact head. - Storybook skipped by path as expected. - The diff contains 2 files and does not change dependencies, `pnpm-lock.yaml`, workflows, migrations, server selection, or UI behavior. - No additional local suite was run during the final restack; GitHub Actions is the authoritative verification environment. ## Risks The main risk is widening model-visible authority. The bridge exposes only its closed public catalog and fixed terminal tools; private operations are omitted from discovery and catalog ambiguity fails during startup. Another risk is duplicate execution after a provider retry. The bridge fingerprints each admitted JSON-RPC identity, reuses the first promise for exact retries, and rejects changed payloads. The endpoint uses loopback plus a per-runtime bearer secret and has no production caller in this pull request. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have added or updated tests where applicable - [x] I have documented the authorization, network, idempotency, and rollout risks - [x] All applicable GitHub Actions are green - [x] Greptile is 5/5 with every actionable comment resolved - [x] I have addressed all review findings before merge |
||
|
|
db52ec0ca0 |
feat(runner): adapt the pinned Codex ACPX runtime (#12401)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner admits a verified Codex ACPX profile before any provider process can start. > - The pinned ACPX library needs a narrow adapter to the admitted runtime host. > - That adapter must keep credentials and launch controls out of durable session records. > - It must preserve exact recovery identity, model controls, and ownership of the complete provider process tree. > - This pull request adds the Codex-only package adapter without registering production execution. ## Linked Issues or Issue Description **Agent or provider** Codex through the exact ACPX and Codex ACP packages landed in #12400. **Why this adapter is useful** The package-local runtime host has an injected port, but no production implementation. This implementation uses the verified executable lease and private runtime sandbox without persisting managed credentials or other launch-only state in ACPX recovery records. **How the agent is invoked** The adapter creates one persistent ACPX Codex session. ACPX receives a placeholder registry command, while its patched spawn callback launches through Paperclip's verified command lease. The private launch environment is supplied only at spawn time. Durable session state receives only the session key, workspace, model, and bounded system instructions. **Additional context** #12400 is merged. This PR does not register an adapter, start runnerd, expose a server route, or change any direct adapter. It supports Codex only, rejects non-Codex profiles, and fails closed on Windows until provider descendants can be contained with an owned Job Object or equivalent. ## What Changed - Add a Codex-only adapter from the pinned ACPX library to the admitted runtime port. - Create the ACPX store inside the private runtime state directory. - Open one persistent session with the qualified model and bounded system instructions. - Route provider launches through the verified executable lease and a dedicated POSIX process group. - Retain cleanup ownership through asynchronous errors and late termination. - Supply the private launch environment at spawn time without persisting it. - Require all ACPX recovery identity fields before returning the runtime port. - Map status, exact model selection, and state-preserving close operations. - Add regression coverage for secret isolation, verified spawning, process-tree cleanup, lifecycle mapping, identity failure, and the Codex-only boundary. ## Verification - Exact verified head: `dc89439d0b2e3dee46d212715caeefc8ae0c0959`. - Full GitHub PR workflow passed in [run 33341468207, attempt 3](https://github.com/paperclipai/paperclip/actions/runs/33341468207/attempts/3), including runner verification/build, typecheck, all test shards, canary, and e2e. - Greptile is 5/5 on the exact head with zero unresolved review threads. - Superagent Security, Snyk, contributor trust, and commitperclip passed on the exact head. - Storybook skipped by path as expected. - The diff contains 2 files and does not change `pnpm-lock.yaml`, workflows, migrations, server selection, or UI behavior. - No additional local suite was run during the final restack; GitHub Actions is the authoritative verification environment. ## Risks The primary risk is leaking launch credentials into durable ACPX state. Session options are constructed explicitly and regression-tested; the launch environment remains behind the spawn-time callback. Another risk is orphaning credential-bearing descendants. Supported launches use a retained POSIX process-group identity with bounded TERM-to-KILL cleanup. Windows fails closed before runtime construction until equivalent process-tree containment exists. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have added or updated tests where applicable - [x] I have documented the process, credential, recovery, and rollout risks - [x] All applicable GitHub Actions are green - [x] Greptile is 5/5 with every actionable comment resolved - [x] I have addressed all review findings before merge |
||
|
|
9ca24bba3c |
feat(runner): pin the Codex ACPX runtime (#12400)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The package-local host boundary is ready for a concrete ACP implementation, but the first production profile is Codex only. > - ACPX must not inherit the server process environment or choose an executable by pathname after admission. > - Codex must not re-enable ambient apps, memory, skills, MCP configuration, or instructions inside its isolated home. > - This pull request pins only the two required production packages and applies narrowly tested host patches. > - The benefit is a minimal dependency boundary that follows the repository's CI-owned lockfile process. ## Linked Issues or Issue Description **Agent or provider** Codex through `acpx@0.13.1` and `@agentclientprotocol/codex-acp@1.6.2`. **Why this adapter is useful** The injected runtime host needs a concrete ACP session manager and the exact reviewed Codex ACP server. Upstream ACPX does not yet expose a host-owned spawn callback, and upstream Codex ACP does not yet apply Paperclip's isolated instruction, MCP, app, memory, and skill boundary. Both behaviors are required before the dependency can execute inside the runner. **How the agent is invoked** The next pull request will adapt these pinned packages to the private runtime host. ACPX receives a host-owned callback that consumes the already verified executable lease. Codex receives only the isolated environment, explicit base instructions, explicit MCP servers, and the skills rooted in its private `CODEX_HOME`. This pull request alone does not spawn either package or register an adapter. **Additional context** This pull request is stacked on #12399. It adds no Pi, Claude, AWS, SDK, lab, browser, or UI dependency. It intentionally does not commit `pnpm-lock.yaml`: the repository policy job regenerates a manifest-only PR lockfile artifact for downstream frozen installs, and the lockfile bot updates master separately. ## What Changed - Pin `acpx` to `0.13.1` and the Codex ACP server to `1.6.2` in the runner package. - Register both patches in the pnpm 9 root configuration and newer-pnpm workspace configuration. - Preserve the existing embedded-Postgres and ACPX 0.12 patch entries used by other packages. - Patch ACPX to evaluate an allowlisted environment at child-spawn time and keep spawn cwd out of provider-visible session identity. - Patch ACPX to accept a host-owned spawn callback with the resolved arguments and options, allowing the verified command lease to own execution. - Patch Codex ACP to retain runner-owned MCP server identity in permission requests. - Patch Codex ACP to pass explicit Paperclip base instructions on both start and resume. - In isolated mode, disable ambient apps, memory, and existing MCP configuration; load skills only from `CODEX_HOME`; and configure only requested servers. - Add a package contract test that enforces exact versions, Codex-only dependency scope, both pnpm patch registries, and every required patch hook. ## Verification - Both patch files dry-apply successfully to fresh published tarballs for `acpx@0.13.1` and `@agentclientprotocol/codex-acp@1.6.2`. - A local no-lockfile install applied both patches; their runtime markers and exact installed versions were inspected. - Runner TypeScript typecheck — passed against the patched packages. - Runner package tests — passed: 16 Node protocol/package tests and 426 Vitest tests. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - `git diff --check` — passed. - The diff contains 6 files and does not change `pnpm-lock.yaml`, a GitHub workflow, server selection, or UI behavior. ## Risks The primary risk is drift between published package contents and checked-in compiled patches. Exact versions are pinned, both patches are exercised by package-contract gates, and CI performs the authoritative regenerated-lockfile frozen install. The spawn callback does not grant a new executable path: the following adapter must consume the opaque verified command lease. Codex isolation changes activate only when `PAPERCLIP_ACPX_ISOLATED_CONTEXT=1`, so existing direct Codex adapters are unaffected. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the dependency, patch, isolation, and lockfile boundaries - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.19 |
||
|
|
d0718c226c |
feat(runner): compose ACPX runtime admission (#12399)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The ACPX pieces already verify profiles, installations, recovery identity, permissions, runtime files, credentials, and models independently. > - A production host must compose those checks in one fail-closed order and clean every acquired resource on partial startup. > - Directly importing a third-party ACP runtime here would mix dependency adoption with the security lifecycle. > - This pull request defines a narrow injected runtime port and admits it only after all package-local boundaries pass. > - The benefit is a testable host lifecycle without adding `acpx`, changing the lockfile, or making the adapter selectable. ## Linked Issues or Issue Description **Agent or provider** The qualified Pi, Claude, and Codex ACPX profiles; Codex additionally uses the managed credential lease. **Why this adapter is useful** The runner needs one owner for startup ordering, immutable identity checks, exact model verification, and cleanup. Otherwise a failure after credential staging or command admission can leave secret files or executable leases alive, and a resumed provider can attach to a different profile, workspace, model, or permission mode. **How the agent is invoked** A later dependency-adapter pull request will implement the injected runtime port with the pinned ACPX library. This host passes that adapter an opaque verified command lease, canonical workspace, private state directory, profile-bound session key, qualified permission policy, launch-only environment, and bounded instructions. It does not expose the runtime directly or add a user-selectable adapter. **Additional context** This pull request is stacked on #12398. Installation verification has a production default; only the third-party runtime opener is injected. Tests use a fake port so this boundary remains package-local and dependency-free. ## What Changed - Add a minimal ACP runtime port for identity, status, model selection, and bounded shutdown. - Derive the qualified profile and canonical recovery binding before any provider startup. - Reject expected-identity drift and irrelevant managed-Codex inputs before opening the provider. - Verify that even an injected installation result matches the closed profile digest. - Prepare the private sandbox and stage Codex credentials only for the Codex profile. - Acquire an opaque verified command lease and pass only the composed launch boundary to the runtime port. - Apply the canonical permission policy and collision-resistant provider session key. - Select and verify the exact effective model before returning an admitted host. - Create a strict versioned identity record and compare resumed provider identifiers with the expected record. - Keep the runtime private and expose only cloned identity, binding, runtime-root, and persistence-safe environment views. - On startup or shutdown failure, attempt runtime close, credential cleanup, and command-lease cleanup in order and aggregate every error. - Add tests for Codex secret isolation, Claude selector verification, recovery drift, injected digest drift, partial-start cleanup, and cleanup retry. ## Verification - Runner TypeScript typecheck — passed. - Runner protocol and TypeScript tests — passed: 12 protocol tests and 426 Vitest tests, including 6 runtime-host tests. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public package export, server selection, or UI behavior. ## Risks The main risk is leaking a partially admitted resource when a later admission step fails. Resource acquisition is linear and all failure paths use the same ordered cleanup routine. The runtime port is deliberately minimal and privately owned by the host; it cannot bypass profile, model, recovery, sandbox, credential, or command admission. The actual ACPX implementation and its process-supervision behavior remain a separate review unit. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the admission and cleanup boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
dba1a2d4f5 |
feat(runner): stage managed Codex credentials (#12398)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Codex can authenticate through an API key or an `auth.json` document. > - Forwarding managed credentials in process arguments, durable session options, or general environment state would leak them across the runner boundary. > - The ACPX sandbox therefore needs a private Codex home, bounded staging, crash-safe cleanup intent, and cross-process ownership that fails closed without relying on writable marker files. > - This pull request establishes that credential boundary before later PRs connect the Codex ACP process. ## Linked Issues or Issue Description **Agent or provider** The qualified Codex ACPX profile. **Why this adapter is useful** Managed installations may already have a Codex login document, while service deployments may provide an API key or inline JSON. The runner needs all three modes without copying ambient home state, accepting ambiguous sources, persisting secret values in ordinary runner state, following links, or allowing concurrent processes to mutate the same credential home. **How the agent is invoked** A later runtime-host pull request acquires this credential lease before opening Codex and closes it during shutdown and failed-start paths. API keys remain launch-only environment values. JSON credentials are atomically staged as `auth.json` inside the isolated Codex home. This pull request does not spawn Codex, add a dependency, register an adapter, or change execution selection. **Additional context** This is the lowest unmerged PR in the runner series and targets `master` directly. It deliberately requires one explicit credential source and never reads the Paperclip server user's ambient home by default. ## What Changed - Add one-use managed Codex credential leases for API-key, inline-JSON, and explicit managed-file modes. - Reject missing and ambiguous source combinations. - Require absolute external managed-file paths, private ownership and permissions on POSIX, bounded documents, no-follow opens, and stable file identity during reads. - Stage JSON through a deterministic private no-follow staging path, scrub stale staging state on admission, sync the file, rename atomically, and sync the parent directory. - Persist a bounded cleanup intent and remove staged or provider-generated authentication files without following links. - Fence each canonical credential home with a markerless 2-of-3 exclusive loopback quorum derived from the current UID and canonical home. One unrelated occupied candidate is tolerated; two occupied candidates fail closed before credential mutation. - Bound stuck parent filesystem operations and cleanup helpers process-wide so an unresponsive filesystem cannot create unbounded work. - Zero temporary credential buffers and make cleanup retryable without allowing a stale cleanup generation to affect a successor. - Add focused tests for credential modes, permissions, malformed and ambiguous sources, symlink rejection, deterministic staging, quorum contention and crash release, stuck-operation bounds, and idempotent cleanup. ## Verification - Prettier and `git diff --check` passed for the exact pushed head. - Greptile reviewed the exact head at 5/5 with no blocking finding; independent static audits found no remaining correctness, security, test-contract, or resource-bound blocker. - GitHub Actions passed on the exact head `29e75afb7b8529b9d070070e0c1462e795d115bb`, including Build, Typecheck, the complete test matrix, e2e, verify, and security checks. One unrelated hosted-runner `npm ENOENT` shard passed on its GitHub rerun. - The diff contains 2 files and does not change `pnpm-lock.yaml`, workflows, dependencies, public package exports, server selection, or UI behavior. ## Risks The primary risks are credential disclosure, concurrent ownership, and cleanup that outlives its authority. Secret values never enter returned identity or durable runner data. Source and destination operations are bounded, no-follow, privately permissioned, and crash-durable. The markerless kernel quorum prevents concurrent home mutation without trusting a replaceable marker, while process-global operation/helper caps prevent unresponsive filesystem work from growing without bound. Cleanup is generation-scoped so a stale retry cannot remove a successor's credential. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [ ] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the credential and cleanup boundary - [x] All applicable GitHub Actions are green - [x] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.18 |
||
|
|
001428a2d6 |
feat(runner): isolate ACPX runtime state (#12397)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - ACPX agents read homes, configuration files, caches, and environment variables. > - Reusing the server user's ambient state would leak unrelated credentials and make recovery nondeterministic. > - Recovery identity already assigns each session a collision-resistant runtime root. > - This pull request materializes that root as a private, bounded sandbox and separates launch-only secrets from persistable configuration. > - The benefit is an isolated runtime boundary before any ACP process is hosted. ## Linked Issues or Issue Description **Agent or provider** The qualified Pi, Claude, and Codex ACPX profiles. **Why this adapter is useful** Each agent expects different home and configuration variables, but none should inherit the Paperclip server user's general home, provider credentials for another agent, or unrelated process secrets. Runtime recovery also needs stable non-secret paths without persisting API keys, OAuth tokens, proxy credentials, or MCP bootstrap tickets. **How the agent is invoked** A later runtime-host pull request will prepare this sandbox, then pass its frozen launch environment and private directories to a verified ACPX command lease. This pull request does not spawn an agent, add dependencies, register an adapter, or alter server execution selection. **Additional context** This pull request is stacked on #12395. It uses that pull request's canonical workspace and collision-resistant runtime binding. All filesystem and environment behavior remains package-local. ## What Changed - Create a normalized session root beneath the private `acpx` runtime namespace. - Create isolated home, configuration, data, cache, state, and agent-specific directories with mode `0700`. - Reject symbolic links, non-directory paths, namespace escapes, and non-normalized roots. - Write the canonical workspace record and Pi trust settings atomically through exclusive no-follow temporary files with mode `0600`. - Give Pi, Claude, and Codex only their qualified home and isolation variables. - Reuse the existing per-agent environment allowlist for launch-time credentials and bound the final environment size. - Return a separate persistence-safe environment containing only stable paths, locale values, and non-secret agent flags. - Explicitly exclude provider credentials, proxy URLs, MCP URLs, and MCP tokens from the persisted projection. - Add table-driven tests for all three agents, file modes, state contents, secret splitting, idempotence, and symbolic-link rejection. ## Verification - Runner TypeScript typecheck — passed. - Runner protocol and TypeScript tests — passed: 12 protocol tests and 413 Vitest tests, including 5 runtime-sandbox tests. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public package export, server selection, or UI behavior. ## Risks The main risks are following attacker-controlled filesystem aliases or persisting a credential under an unexpected variable name. Every created path is checked against its physical parent, the session root must already be absolute and normalized, temporary files use exclusive no-follow opens, and the persisted projection is a positive allowlist rather than a credential-name blacklist. The launch environment remains available only in memory and is bounded before use. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the runtime isolation and secret-persistence boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.17 |
||
|
|
3cc9decd9c |
feat(runner): bind ACPX recovery identity (#12395)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A durable ACPX session must resume only the workspace, profile, model, policy, and provider session that created it. > - Sanitized directory names can collide, and lexical workspace paths can change meaning through symbolic links. > - Schema-less draft records cannot prove workspace or normalized-session provenance. > - This pull request establishes one closed v1 identity format and rejects records that cannot prove every immutable binding. > - The benefit is fail-closed recovery without enabling or selecting the ACPX runtime. ## Linked Issues or Issue Description **Agent or provider** Durable sessions for qualified Pi, Claude, and Codex ACP servers through the internal ACPX driver. **Why this adapter is useful** The runner must prevent a persisted provider session from being reused with another workspace, model, permission policy, profile, or normalized session. It must also distinguish normalized session names that sanitize to the same pathname. **How the agent is invoked** A later pull request will use this binding when the private ACPX runtime opens or recovers a session. This pull request does not launch a process, add a dependency, register an adapter, or change runtime selection. **Compatibility boundary** No ACPX identity writer exists on master or in a shipped runtime. This pull request establishes the first accepted persisted format. Draft schema-less records and early-v1 command-digest records cannot prove every immutable binding and are intentionally rejected; an affected experimental session must start fresh. ## What Changed - Resolve real workspace and runtime-directory paths and reject filesystem roots or non-directories. - Derive collision-resistant runtime roots and provider session keys. - Bind the session key to workspace, complete qualified profile, model, protocol, agent, and permission mode. - Add a closed v1 ACPX identity record. - Verify controller identity and persisted identity against every immutable binding. - Reject schema-less, early-digest, unknown-version, unknown-field, and malformed records. - Add tests for canonical paths, collision resistance, drift, workspace/session replay, missing policy, malformed records, and unsafe roots. ## Verification - GitHub Actions are the authoritative typecheck, test, build, and integration gate for the final head. - Greptile, Superagent, and Snyk are required to pass on the final head. - `git diff --check` passes for the two-file delta. - The diff does not change `pnpm-lock.yaml`, a workflow, a dependency, a public export, server selection, migration, or UI behavior. ## Risks The main risk is accepting an identity under a different immutable session configuration. Controller and v1 record fields are compared exactly, including permission mode and the complete qualified-profile digest. Records that lack workspace/session provenance or use an obsolete partial digest fail closed. Because no writer for those draft formats has shipped, requiring a fresh experimental session is safer than synthesizing missing authority from the current request. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have added or updated tests where applicable - [x] I have documented the recovery and compatibility boundary - [ ] All applicable GitHub Actions are green on the final head - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
d1abff2567 |
feat(runner): verify ACPX installations (#12393)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A qualified ACPX profile binds exact provider and runtime package versions. > - Package metadata alone does not prove which executable will run. > - A pathname, directory entry, or open inode can still change after verification. > - A verified launch therefore needs a one-use lease over entry bytes and retained directories, with ambient loader and package authority removed. > - Provider compatibility is admitted later, per provider; this primitive must fail closed when a provider needs an unqualified path or dependency. ## Linked Issues or Issue Description **Agent or provider** Internal qualified ACPX profiles. The first production consumer remains Codex-only in the follow-on dependency and adapter changes. **Why this adapter is useful** The runner needs to prove that installed package metadata and executable bytes match a reviewed profile, then prevent pathname replacement, symlink escape, host-package lookup, or loader injection from changing what executes. **How the agent is invoked** A later provider-specific adapter requests an opaque one-use command lease. On Linux, the lease starts Node with a synchronous hook, supplies the verified entry snapshot over a private pipe, and retains only the verified package directories needed by that profile. This pull request does not register an adapter, change runtime selection, or make any provider user-visible. **Compatibility boundary** The launched entry deliberately has a Linux descriptor-backed identity such as `/proc/self/fd/4/...`; preserving a mutable canonical pathname would reopen the replacement vulnerability. A provider that requires canonical `import.meta.url`, `__filename`, or `process.argv[1]` is not admitted by this primitive until its provider-specific adapter proves compatibility. Likewise, arbitrary package-manager ancestors are not retained. Hoisted dependencies must be explicitly qualified by a later provider-specific layer; otherwise startup fails closed. The initial production slice is Codex only, not Pi or Claude. ## What Changed - Verify exact server and optional runtime package versions from bounded metadata. - Require one supported relative Node executable and reject ambiguous or package-escaping paths. - Canonicalize the command directory and open final components without following symbolic links. - Bound and hash the open entry file while checking device, inode, size, and timestamps around the read. - Return an opaque installation and one-use launch lease instead of an executable pathname. - Reopen and revalidate retained directory and executable identities when acquiring a lease. - Load the admitted entry bytes and package-contained modules through retained Linux descriptors. - Resolve CommonJS and ESM bare imports only from retained roots, reject host ancestors, and make symlink escape terminal. - Open module bytes with `O_NOFOLLOW`, bound each read, recheck identity, and reject native or unsupported module formats. - Strip Node, native dynamic-loader, glibc, and OpenSSL injection variables before spawn. - Add regressions for replacement races, direct resources, sibling and ancestor imports, explicit runtime roots, host-ancestor denial, descendant and final symlinks, bounded reads, and environment injection. ## Verification - The authoritative GitHub Actions and exact-head Greptile review are the merge gates for the final head. - Prettier and `git diff --check` pass for the final two-file diff. - The diff does not change `pnpm-lock.yaml`, workflows, dependencies, public exports, server selection, or UI behavior. ## Risks The security/compatibility tradeoff is explicit: descriptor identity prevents a replaced lexical path from supplying resources, but pathname-sensitive providers require a later adapter-specific qualification. Unqualified or unsupported dependencies, native addons, non-Linux launch, and unsupported module formats fail closed. No production call path reaches this primitive in this pull request. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have described the issue and provider boundary above - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have added or updated affected tests - [x] I have documented the trust, compatibility, dependency, and rollout boundaries - [ ] All applicable GitHub Actions are green on the final head - [ ] Greptile is 5/5 on the final head with every actionable comment resolvedcanary/v2026.830.0-canary.16 |
||
|
|
a1bd737da6 |
feat(runner): verify ACPX effective models (#12392)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Each qualified ACPX profile binds one exact model and one reported ACP selector. > - A provider can start with a stale default or report a selector that differs from the canonical model name. > - The runner must select and verify the qualified model before it accepts a billable prompt. > - This pull request adds that verification boundary and normalizes a verified selector for provider-neutral consumers. > - The benefit is fail-closed model identity without enabling the ACPX runtime. ## Linked Issues or Issue Description **Agent or provider** Qualified Pi, Claude, and Codex ACP servers through the internal ACPX driver. **Why this adapter is useful** The runner must not assume that an ACP session uses the requested model. It needs a status check, an exact model selection when required, and a second status check before work can begin. **How the agent is invoked** A later pull request will provide the private ACP runtime control behind this interface. This pull request does not launch a process, add a dependency, register an adapter, or change runtime selection. **Additional context** This pull request is stacked on #12391. Claude's qualified canonical model is `claude-sonnet-5`, while its pinned ACP server reports the stable selector `sonnet`. ## What Changed - Require ACP model status before accepting a qualified runtime. - Select the exact canonical model when the session reports a stale default. - Reapply canonical selection when a qualified profile uses a distinct ACP selector. - Fail closed when status, model selection, or the expected reported selector is unavailable. - Normalize a verified selector back to the canonical model for provider-neutral status consumers. - Add tests for exact, stale, aliased, unavailable, and ignored-selection cases. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — passed, including 5 new model-verification tests. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public export, server selection, or UI behavior. ## Risks The main risk is treating a provider alias as proof of the requested model. A distinct selector is accepted only when it is part of the immutable qualified profile, after the runner sends the exact canonical model through ACP and performs a second status check. All other mismatches fail closed. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the model admission boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.15 |
||
|
|
07a80cda41 |
feat(runner): bind ACPX permission policy (#12391)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - ACP agents can request permission before reads, process execution, and workspace mutation. > - The runner must apply the configured policy without allowing provider display text to grant authority. > - Runner-owned semantic tools already have a separate run-scoped authorization catalog. > - This pull request defines the local permission decision and the narrow metadata needed to recognize those authorized tools. > - The benefit is a fail-closed permission boundary before an ACPX process can use it. ## Linked Issues or Issue Description **Agent or provider** Qualified Pi, Claude, and Codex ACP servers through the internal ACPX driver. **Why this adapter is useful** ACP providers use permission requests for both ordinary provider operations and runner-owned semantic operations. Paperclip must apply `approve-all`, `approve-reads`, or `deny-all` consistently while keeping semantic authorization bound to structural MCP metadata. **How the agent is invoked** A later pull request will install this policy in the private ACPX runtime host. This pull request does not launch a provider, add a dependency, register an adapter, or change runtime selection. **Additional context** This pull request is stacked on #12390. Pi uses a different bridge and never receives semantic auto-approval through this ACP permission path. ## What Changed - Map each ACPX permission mode to a closed runtime policy. - Decide local allow, reject, or coordinator delegation outcomes. - Auto-approve only runner-owned semantic MCP calls identified by structural metadata. - Ignore provider display titles when determining semantic authority. - Limit Codex blanket MCP approval to sessions where every configured MCP server is runner-owned. - Add table-driven tests for all modes, agents, metadata shapes, spoofed titles, and non-runner servers. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — passed, including 10 new permission-policy assertions. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public export, server selection, or UI behavior. ## Risks The main risk is mistaking a provider-controlled label for an authorized semantic tool. The implementation ignores display titles and requires a runner-owned MCP server name, a transport tool name, or provider metadata. All other `approve-reads` mutations delegate to the coordinator, and the caller must reject them when no delegate exists. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the permission and semantic-authorization boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
da6124adf2 |
feat(runner): declare ACPX driver profile (#12390)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A native driver must declare its supported behavior before the coordinator can select it. > - ACP-compatible agents do not all expose the same event families. > - A loose config could also select an unqualified model, permission policy, or executable field. > - This pull request defines the ACPX descriptor, capability matrix, and strict configuration parser. > - The benefit is one reviewable admission contract before any ACPX runtime is wired. ## Linked Issues or Issue Description **Agent or provider** Qualified Pi, Claude, and Codex ACP servers through the internal ACPX driver. **Why this adapter is useful** The runner needs a truthful capability descriptor and a closed configuration boundary before it can create an ACPX session. The boundary must reject arbitrary commands and unqualified models. **How the agent is invoked** A later pull request will implement the private runtime behind this descriptor. This pull request does not launch a process, add a dependency, register an adapter, or make ACPX selectable. **Additional context** This pull request is stacked on #12389. Pi reports plan events as unsupported. Claude and Codex report structured plan support. ## What Changed - Add the ACPX driver descriptor and native runtime-context capability declaration. - Add an agent-specific typed event capability matrix. - Add strict config validation for agent, exact qualified model, and permission mode. - Default the permission mode to `approve-all` when the field is absent. - Reject non-object config, unknown fields, unqualified models, and unsupported permission values. - Add table-driven tests for all qualified agents and failure cases. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — passed, including 8 new driver-profile assertions. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public export, server selection, or UI behavior. ## Risks The main risk is advertising a capability that a qualified ACP server cannot supply. The matrix is explicit per agent, and tests cover the one current difference. Config validation rejects unknown fields so a caller cannot smuggle an executable or an unsupported runtime setting into this boundary. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the compatibility and admission boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
7a8c6825a5 |
feat(runner): sequence ACPX sidecar input (#12389)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - An ACPX sidecar will read asynchronous commands from one ordered input stream. > - Concurrent command handling could reorder bootstrap, turn, suspend, and shutdown operations. > - A failed diagnostic callback could also poison the input promise and skip later frames. > - This pull request adds a small serial queue and records the first provider-bootstrap failure. > - The benefit is deterministic input ordering and a stable fail-closed bootstrap state before the sidecar exists. ## Linked Issues or Issue Description **Agent or provider** The internal ACPX sidecar for qualified ACP-compatible providers. **Why this adapter is useful** The sidecar must process input frames in order. It must drain accepted input before shutdown, continue after an ordinary command error, and reject dependent commands after initialization or session bootstrap fails. **How the agent is invoked** A later pull request will connect this helper to a private sidecar process. This pull request adds no executable, dependency, adapter registration, or process launch. **Additional context** This pull request is stacked on #12388. The helper remains package-local and does not affect direct adapters. ## What Changed - Add a serial asynchronous input queue that remains usable after operation and diagnostic failures. - Add ACPX-specific input sequencing around the shared queue. - Preserve the first `initialize` or `session.open` failure as the bootstrap cause. - Produce a deterministic blocked-command error after bootstrap fails. - Test ordering, EOF-style draining, error isolation, sticky bootstrap failure, and non-sticky turn failure. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — passed, including 4 new sequencing tests. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 3 files and does not change `pnpm-lock.yaml`, a workflow, a dependency, a public export, server selection, or UI behavior. ## Risks The main risk is allowing one failed input operation to reorder or suppress later input. Each operation runs only after the previous promise settles. Both operation and diagnostic failures are contained. Bootstrap failure is recorded separately so an ordinary turn failure does not disable the sidecar session. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the compatibility and failure boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
8cf4c14732 |
feat(runner): normalize ACP form questions (#12388)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runner uses one provider-neutral question contract for user input. > - ACP providers describe form input with provider-specific JSON Schema values. > - Passing those values through would couple the task page to ACP and could bypass the existing response validator. > - This pull request converts bounded ACP forms to the existing Paperclip question contract and converts validated answers back to ACP content. > - The benefit is one question path that does not change any legacy adapter behavior. ## Linked Issues or Issue Description **Agent or provider** ACP-compatible providers that use form elicitation. **Why this adapter is useful** ACP providers need structured user answers during a turn. Paperclip must present those questions through its provider-neutral contract so the existing task experience and validation rules remain consistent. **How the agent is invoked** A later pull request will connect this internal adapter to the ACPX sidecar. This pull request only implements the conversion boundary. It does not launch ACPX, add a dependency, or enable an adapter. **Additional context** This pull request is stacked on #12387. URL elicitation remains unsupported and returns no form projection. ## What Changed - Convert bounded ACP string, enum, multi-select, Boolean, number, and integer fields to `paperclip.question_set.v1`. - Validate every answer with the existing provider-neutral response parser before conversion. - Convert validated answers back to typed ACP form content. - Bound provider-controlled field and option inventories. - Use stable question identities and define arbitrary property names without prototype mutation. - Keep ACP runtime types and dependencies outside this package-local conversion boundary. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — 41 files and 367 Vitest tests passed; 12 Node contract tests passed. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 2 files and does not change `pnpm-lock.yaml`, a workflow, a package dependency, a public export, server selection, or UI behavior. ## Risks The main risk is accepting an ACP form that cannot be represented safely by the Paperclip question contract. Unsupported field types fail closed. Field and option inventories are bounded. The existing question parser validates all text, selection, numeric, and required-field constraints before any response returns to ACP. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the compatibility and security boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting merge |
||
|
|
0834a0c1f7 |
feat(runner): bind ACPX profile boundary (#12387)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Paperclip runner needs a safe boundary before it can launch ACP-compatible agents. > - A caller-controlled command, model, environment, or frame could bypass that boundary. > - The ACPX transport contract in #12386 defines the allowed messages but does not bind a runtime profile. > - This pull request defines closed, versioned profiles and validates the launch inputs around that contract. > - The benefit is a small and reviewable trust boundary before any ACPX process can become available. ## Linked Issues or Issue Description **Agent or provider** ACPX sidecar support for the qualified Pi, Claude, and Codex ACP servers. **Why this adapter is useful** The runner needs one bounded process boundary for ACP-compatible providers. A closed profile prevents an untrusted run from selecting an arbitrary executable, package version, or model. **How the agent is invoked** A later pull request will launch an internal sidecar from an exact profile. This pull request only validates profiles, environment values, and protocol frames. It does not add an executable dependency or enable an adapter. **Additional context** This pull request is stacked on #12386. It keeps the existing direct adapters and the Codex runner path unchanged. ## What Changed - Add a closed profile table for the qualified Pi, Claude, and Codex ACP servers. - Require the exact qualified model and return an isolated profile value to callers. - Add an agent-specific environment allowlist with entry and aggregate size limits. - Add strict parsing for bounded sidecar requests and structured plan values. - Reject unknown fields, unsupported protocol versions, invalid identifiers, null bytes, cyclic values, and oversized input. ## Verification - Runner TypeScript typecheck — passed. - Runner TypeScript tests — 40 files and 362 Vitest tests passed; 11 Node contract tests passed. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - Prettier and `git diff --check` — passed. - The diff contains 6 files and does not change `pnpm-lock.yaml`, a workflow, a package dependency, or a public export. ## Risks The main risk is accepting more launch state than the sidecar needs. The implementation uses an agent-specific allowlist, rejects null bytes, and enforces per-entry and aggregate bounds. This pull request does not launch a process or expose a new adapter, so production and direct-adapter behavior remain unchanged. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 linked an existing public item or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the compatibility and security boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.14 |
||
|
|
e13856eb37 |
feat(runner): define ACPX sidecar contract (#12386)
## Thinking Path > - Paperclip Runner now has a complete guarded Codex vertical slice. > - The next provider series must not start by importing a provider implementation or dependency bundle. > - ACPX needs one bounded, versioned process boundary shared by TypeScript and Rust. > - A schema is the authority; checked-in generated inventories keep both languages in lockstep. > - Unknown versions, commands, event types, and properties must fail closed. > - This pull request therefore lands only the sidecar wire contract and its drift gate. > - No ACPX runtime, dependency, executable, package export, or production selection is added. ## Linked Issues or Issue Description This is the first package-local unit in the post-Codex provider series. **What happened?** The integration branch contains an ACPX provider, but its TypeScript sidecar and Rust client need a small shared authority before either implementation can be reviewed safely. Importing the final integration implementation directly would mix the protocol, runtime, third-party dependencies, and production wiring. **Expected behavior** The schema defines every ACPX sidecar request, response, event, command, event type, and protocol version. Generated TypeScript and Rust inventories must drift-check against that schema. No runtime can select or execute ACPX yet. **Steps to reproduce** 1. Change the protocol version, command inventory, or event inventory in the schema. 2. Run the runner protocol type check without regenerating the language inventories. 3. Observe the drift gate fail. **Paperclip version or commit** Stacked on `runner-server-semantic-codex` at `ebd7f9df7`. ## What Changed - Add the internal ACPX sidecar v2 JSON Schema outside the public PRP v1 schema catalog. - Generate one TypeScript inventory and one Rust inventory from that schema. - Add generate and check hooks to the existing runner protocol-type workflow. - Add fail-closed AJV tests for all three message families, version drift, unknown commands, and extra properties. - Keep the generated Rust module unregistered until the Rust ACPX transport exists. ## Compatibility Boundary - Codex remains the only production runner provider. - `paperclip_runner` selection and the default-off rollout flag are unchanged. - No ACPX package, patch, lockfile, binary entry point, root export, server file, UI file, workflow, or dependency is added. - The schema is shipped with the existing `protocol` directory but is not added to the public PRP manifest. - Existing direct adapters continue through their current paths. - Diff against the actual stacked base: 6 files. ## Verification - Runner TypeScript typecheck and both generated-contract drift gates — passed. - Runner TypeScript tests — 37 files and 355 Vitest tests passed; 11 Node contract tests passed. - Rust provider-bridge regression suite after restacking — 14/14 passed. - `pnpm -r typecheck` — passed for all applicable workspaces. - `pnpm build` — passed, including runner binary, server, UI, and workspace packages. - `pnpm test:run` — attempted; the local host reproduced unrelated workspace/Postgres and port-exposure failures in unchanged server suites. The changed runner contract suites pass, and the repository's serialized/sharded GitHub checks remain authoritative for those host-sensitive suites. - Prettier, rustfmt, generated-source drift checks, and `git diff --check` — passed. - `pnpm-lock.yaml` is unchanged. ## Risks The main risk is allowing schema and generated language inventories to diverge. Build and typecheck now fail on any drift. The sidecar implementation and third-party ACPX packages are deliberately absent, so this PR cannot alter runtime behavior or expand the production attack surface. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 - [x] I have described the issue and expected behavior in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal task identifier - [x] I have run the affected tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have documented the compatibility and security boundary - [ ] All applicable GitHub Actions are green - [ ] Greptile is 5/5 with every actionable comment resolved - [x] I will address all review findings before requesting mergecanary/v2026.830.0-canary.13 |
||
|
|
7a3abb88a0 |
feat(runner): authorize server Codex tools (#12385)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The hidden native coordinator already computes a run-scoped semantic tool projection. > - The durable Codex backend now accepts and enforces that projection. > - The server did not include the projection in its `run.prepare` command. > - Codex therefore received no production semantic tools even when the server authorized them. > - This pull request adds the deterministic wire projection and sends it to runnerd. > - The benefit is one fail-closed authorization catalog from the server through Codex. ## Linked Issues or Issue Description Refs #12384 **What existing behavior does this improve?** This improves the existing flagged Paperclip Runner Codex path. **Current behavior** The server creates a run-scoped list of authorized read tools. It does not pass that list to runnerd, so the production Codex session starts with no tools. **Proposed behavior** The server maps the authorized definitions to the versioned runner contract. It computes a cross-language catalog digest. It includes that immutable contract in `run.prepare`. **Reason and benefit** Runnerd and the server now enforce the same catalog identity. Unknown, duplicate, changed, or malformed tool contracts fail before Codex can use them. **Breaking changes** None. Direct adapters are unchanged. A native run with an empty server projection still starts with no dynamic tools. ## What Changed - Add a deterministic semantic-definition to runner-authorization projection. - Match the Rust canonical digest with a shared test vector. - Include the server coordinator projection in the native Codex `run.prepare` command. - Extend the native Codex vertical slice to require and execute a semantic tool. - Verify the production prepare payload in a host-independent server test. ## Verification - `pnpm --filter @paperclipai/paperclip-runner test:typescript` (354 tests pass) - `pnpm --filter @paperclipai/server exec vitest run src/services/native-runtime/native-codex-runner.test.ts` - `pnpm --filter @paperclipai/server typecheck` - `pnpm -r typecheck` - `pnpm build` - The embedded-Postgres vertical slice is present for CI. This local host reports that embedded Postgres is unavailable, so Vitest skips that host-dependent test locally. - Confirmed that the PR changes 7 files against `runner-codex-durable-tools`. - Confirmed that `pnpm-lock.yaml` is unchanged. ## Risks The main risk is a catalog digest mismatch between TypeScript and Rust. Both implementations use canonical JSON. They share the same fixed digest vector. Runnerd also recomputes the digest and rejects a mismatch. The rollout flag and the existing native runtime selection rules remain unchanged. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
6c85fa060e |
feat(runner): durably reconcile Codex tools (#12384)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Paperclip Runner gives an agent a durable execution boundary. > - The Codex transport can now advertise a run-scoped semantic tool catalog. > - The durable backend did not yet persist tool calls or correlate their results. > - A restart could therefore lose the boundary between a provider call and a Paperclip action. > - This pull request binds authorized calls, durable events, results, replay, and cancellation. > - The benefit is safe semantic tool recovery without duplicate Paperclip actions. ## Linked Issues or Issue Description Refs #12382 **What existing behavior does this improve?** This improves the durable Codex provider backend in `@paperclipai/paperclip-runner`. **Current behavior** The Codex transport can project authorized dynamic tools. The durable backend rejects their calls because it cannot persist and recover their identities. **Proposed behavior** The durable backend records each authorized call before it emits the semantic input event. It records each result before it sends the result to Codex. It reconciles exact provider replays without another Paperclip action. **Reason and benefit** This order prevents duplicate semantic actions after a process restart. It also keeps unauthorized, changed, oversized, and late calls closed. **Breaking changes** None. A run without an authorized tool catalog still starts Codex with no dynamic tools. ## What Changed - Persist the authorized tool catalog with the Codex provider state. - Emit correlated and redacted semantic input, reconciliation, and result events. - Reconcile exact pending and completed calls after a provider restart. - Reject catalog drift, changed replay input, malformed results, and unauthorized operations. - Complete pending tool calls with a durable failure when a turn stops. - Bound retained tool values and validate recovered state before provider startup. - Bind production runner events to the active run, session, turn, and item identities. ## Verification - `cargo fmt --all -- --check` - `cargo test --workspace` - `pnpm -r typecheck` - `pnpm build` - Confirmed that the PR changes 9 files against `runner-codex-dynamic-tools`. - Confirmed that dependency installation did not change `pnpm-lock.yaml`. ## Risks The main risk is a mismatch between recovered provider state and the controller tool catalog. Recovery validates the complete catalog and its digest before Codex starts. The backend persists a call before it emits work and persists a result before it returns the result to Codex. This PR does not enable the server adapter or change any direct adapter path. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.830.0-canary.12 |
||
|
|
9e4be0e60c |
fix(ui): prevent false agent instruction saves (#12502)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Operators edit each agent instruction bundle in the agent detail page > - The rich Markdown editor can normalize content and emit an onChange event while it mounts > - Paperclip treated that editor event as a user edit and retained the dirty state after the tab unmounted > - This pull request accepts rich-editor changes only after real user interaction and clears shared edit state when the instructions tab closes > - The benefit is that opening instructions or moving between agent tabs no longer shows false save controls or navigation warnings ## Linked Issues or Issue Description **What happened?** Opening an agent Instructions page could mark the page as edited without user input. The page showed Save and Cancel controls and warned about unsaved changes during unrelated tab navigation. The shared edit callbacks could remain active after the Instructions tab unmounted. **Expected behavior** Opening an instruction file must not create a draft. Save controls and navigation warnings must appear only after a user changes content. Leaving the Instructions tab must clear its shared dirty, saving, save, and cancel state. **Steps to reproduce** 1. Open an agent Instructions tab with a Markdown entry file. 2. Do not edit the file. 3. Move to another agent tab or navigate away. 4. Observe false save controls or an unsaved-changes prompt. **Paperclip version or commit** Current `master` before this change. **Deployment mode** Self-hosted server and local development. ## What Changed - Ignore rich Markdown editor normalization events until keyboard, pointer, paste, input, drop, or before-input interaction occurs. - Reset the interaction guard when the selected file, agent, or persisted content changes. - Clear the parent dirty, saving, save, and cancel state when the Instructions tab unmounts. - Add regression tests for mount normalization and cross-tab state cleanup. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/pages/AgentDetail.instructions.test.tsx src/pages/AgentDetail.liveRun.test.ts src/pages/AgentDetail.progress.test.ts src/components/MarkdownEditor.test.tsx` — 76 tests passed. - `pnpm -r typecheck` — passed. - `pnpm build` — passed. - `pnpm test:run` — the relevant UI tests passed. The local full runner reproduced unrelated workspace-runtime failures present on `master`; GitHub CI is the authoritative isolated full-suite gate. - `pnpm check:token-gates` — the changed files are clean. The command reports nine existing color literals in `ui/src/components/onboarding/PillGuy.tsx` from `master`. ## Risks - Low risk. The change affects only local instruction-editor dirty-state tracking. - The interaction guard covers keyboard, pointer, paste, input, drop, and before-input events. - There are no API, database, migration, or visual design changes. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5 family. The deployment model identifier and context-window size are not exposed in this session. The agent used reasoning, repository tools, shell execution, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
cf6db7b523 |
feat(runner): bridge Codex dynamic tools (#12382)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The native runner keeps provider execution separate from Paperclip tool authority. > - The Rust authorization bridge can now validate a run-scoped semantic tool catalog. > - Codex still needs a bounded protocol adapter for that validated catalog. > - The adapter must advertise the same catalog after provider recovery. > - The adapter must reject unadvertised calls and mismatched results. > - This pull request adds that Codex-only transport boundary. > - The benefit is a fail-closed provider bridge that remains inactive until durable wiring supplies tools. ## Linked Issues or Issue Description **Subsystem affected** `packages/paperclip-runner` and its Rust Codex app-server provider. **Problem or motivation** The native runner has a validated semantic tool catalog, but the Rust Codex provider cannot project that catalog or correlate Codex tool calls with Paperclip results. A resumed Codex thread also needs the same run-scoped catalog. **Proposed solution** Add an explicit Codex start path that accepts validated tools. Send those tools through `dynamicTools` for both thread start and thread resume. Validate thread, turn, call, operation, result identity, and size before data crosses the provider boundary. **Roadmap alignment** This work supports the shipped governed MCP Tool Gateway and self-healing run milestones. It does not add a user-facing adapter or enable the experimental runner. ## What Changed - Add a Codex dynamic-tool projection for explicit authorized tool sets. - Advertise the same tool set on new and resumed provider threads. - Correlate bounded Codex tool calls and Paperclip semantic results. - Reject calls outside the active thread or turn, unadvertised tools, reused request identities, mismatched results, and oversized values. - Keep the current durable backend on the zero-tool path until the next wiring change. - Extend the fake Codex app server and integration tests for success, recovery, denial, and correlation behavior. ## Verification - `cargo test --manifest-path packages/paperclip-runner/runner/Cargo.toml --workspace` - `cargo clippy --manifest-path packages/paperclip-runner/runner/Cargo.toml --workspace --all-targets -- -D warnings -A clippy::manual_is_multiple_of -A clippy::filter_map_bool_then` - `pnpm -r typecheck` - `pnpm build` - The PR changes 4 files relative to `runner-rust-semantic-tool-bridge`. ## Risks Low activation risk. The existing `CodexProvider::start` path still supplies an empty tool set. The durable backend treats a tool event as an error until a later PR attaches the durable authorization bridge. The new transport rejects unknown tools and invalid provider bindings. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.830.0-canary.11 |