Commit Graph
4030 Commits
Author SHA1 Message Date
Dotta 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
2026-08-30 23:49:01 -05:00
Dotta 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 merge
canary/v2026.831.0-canary.2
2026-08-30 22:09:03 -05:00
Dotta 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
2026-08-30 21:48:14 -05:00
Dotta 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
2026-08-30 21:32:36 -05:00
Dotta 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
2026-08-30 21:11:36 -05:00
Dotta 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 merge
canary/v2026.831.0-canary.1
2026-08-30 20:52:45 -05:00
Dotta 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 merge
canary/v2026.831.0-canary.0
2026-08-30 19:34:24 -05:00
Dotta 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
2026-08-31 00:14:54 +00:00
Dotta 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
2026-08-30 19:02:58 -05:00
Dotta 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
2026-08-30 18:47:14 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.19
2026-08-30 18:11:25 -05:00
Dotta 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
2026-08-30 17:53:31 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.18
2026-08-30 17:51:33 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.17
2026-08-30 15:40:02 -05:00
Dotta 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
2026-08-30 15:30:35 -05:00
Dotta 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
resolved
canary/v2026.830.0-canary.16
2026-08-30 15:11:32 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.15
2026-08-30 13:35:10 -05:00
Dotta 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
2026-08-30 13:18:55 -05:00
Dotta 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
2026-08-30 13:07:45 -05:00
Dotta 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
2026-08-30 12:57:02 -05:00
Dotta 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
2026-08-30 12:47:22 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.14
2026-08-30 12:37:13 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.13
2026-08-30 11:59:14 -05:00
Dotta 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
2026-08-30 11:43:34 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.12
2026-08-30 11:31:36 -05:00
DottaandPaperclip 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>
2026-08-30 08:23:35 -05:00
Dotta 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 merge
canary/v2026.830.0-canary.11
2026-08-30 07:56:17 -05:00
Dotta 3ba0e7f64f feat(runner): add durable semantic tool bridge (#12378)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner package has a reviewed semantic action catalog and
dispatcher
> - The Rust runner process needs the same fail-closed authorization
boundary
> - Provider calls must remain correlated and idempotent across durable
recovery
> - Input and result values must satisfy the authorized operation
schemas
> - This pull request adds a package-local durable semantic tool bridge
> - It does not advertise tools to Codex or enable the Paperclip Runner
adapter

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner/runner` semantic tool authorization and
correlation.

**Problem or motivation**

The Rust runner needs a durable representation of the run-scoped tools
that the control plane authorizes. It must reject unknown operations,
catalog drift, invalid values, and conflicting duplicate calls or
results before a provider integration can use those tools.

**Proposed solution**

Add a serialized provider tool bridge. Validate the authorized catalog
and its JSON Schemas. Validate each call and result. Keep pending and
completed identities so retries are idempotent and conflicts fail
closed.

**Alternatives considered**

Trusting provider arguments would bypass the run-scoped catalog.
Validating only in TypeScript would leave the Rust process without a
recovery-safe authorization boundary. Adding provider behavior in this
pull request would make the review unit too broad.

**Roadmap alignment**

This adds a package-local safety boundary for the Codex-first runner
path. It does not enable a new adapter or change an existing direct
adapter path.

## What Changed

- Added the versioned authorized-tool, pending-call, and result
contracts.
- Added canonical SHA-256 catalog binding and drift rejection.
- Added JSON Schema compilation and input and response validation.
- Added duplicate-call and duplicate-result idempotency with conflict
rejection.
- Added bounds for catalogs, schemas, values, and retained call
identities.
- Added the Rust `jsonschema` dependency and its Cargo lock entries.
- Added focused tests for authorization, recovery, envelopes, bounds,
and conflicts.

## Verification

- `cargo fmt --manifest-path packages/paperclip-runner/runner/Cargo.toml
--all -- --check`
- `cargo test --manifest-path
packages/paperclip-runner/runner/Cargo.toml -p paperclip-runner-core`
(64 tests)
- `cargo clippy --manifest-path
packages/paperclip-runner/runner/Cargo.toml -p paperclip-runner-core
--all-targets -- -D warnings -A clippy::manual_is_multiple_of -A
clippy::filter_map_bool_then`
- `pnpm -r typecheck`
- `pnpm build`
- The repository test runner also reached unrelated server worktree
suites. Those suites fail on the current macOS worktree with database
deadlocks and filesystem fixture assumptions. This pull request does not
change those files. The applicable GitHub checks remain the handoff
authority.

## Risks

The main risks are accepting a tool that the run did not authorize and
replaying a conflicting provider result. The bridge validates the
catalog, operation identity, JSON Schema, call identity, and result
identity before it changes durable state. The new Cargo dependency is
package-local. This pull request changes no GitHub workflow and no pnpm
lockfile.

## 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
canary/v2026.830.0-canary.10
2026-08-30 03:27:37 -05:00
Dotta fd7cb77d8e feat(runner): isolate Codex runtime context (#12376)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner package now has a Codex-only native backend
> - A native Codex process needs an isolated runtime context before it
can start safely
> - Assigned skills, local authentication, and MCP bindings cross
separate trust boundaries
> - Runtime materialization must reject symlink escapes and unsafe
remote bindings
> - This pull request adds the package-local Codex runtime context
boundary
> - It does not start runnerd or enable the Paperclip Runner adapter

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex runtime context materialization.

**Problem or motivation**

The runner needs a private Codex home for each native session. It must
stage only assigned skills, copy local Codex authentication safely, and
validate native MCP bindings before it exposes them to the child
process.

**Proposed solution**

Create an isolated runtime directory. Validate the skill tree before and
after copying it. Make staged skill files read-only. Read authentication
through a no-follow file descriptor with a size bound. Accept only HTTPS
or loopback MCP endpoints and bounded tokens.

**Alternatives considered**

Using the operator Codex home directly would expose unrelated state and
skills. Following symlinks while copying skills or authentication could
escape the assigned source. Accepting arbitrary MCP URLs could send a
bearer token to an untrusted endpoint.

**Roadmap alignment**

This adds a package-local safety boundary for the reviewed Codex runner
path. It does not enable a new adapter or change an existing direct
adapter path.

## What Changed

- Added the native MCP binding contract and strict validation.
- Added isolated Codex home materialization with shell snapshots
disabled.
- Added assigned-skill staging with lexical containment and two-pass
symlink checks.
- Added read-only permissions for staged skill trees.
- Added owner-only authentication staging with no-follow reads and a
size bound.
- Added cleanup for complete and partially materialized runtime
directories.

## Verification

- The focused runtime context suite has 7 passing cases.
- `pnpm --filter @paperclipai/paperclip-runner test:typescript` (36
files, 351 tests)
- `pnpm -r typecheck`
- `pnpm build`

## Risks

The main risks are filesystem escape, secret exposure, and token
delivery to an unsafe endpoint. The materializer rejects symlinks before
and after skill copying, resolves existing source paths, reads
authentication with `O_NOFOLLOW`, applies private permissions, and
restricts MCP URLs to HTTPS or loopback hosts. Existing direct adapters
do not use this package-local runtime context.

## 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
nightly/v2026.830.0-nightly.0 canary/v2026.830.0-canary.9
2026-08-30 03:18:12 -05:00
Dotta 6d358e646d feat(runner): add Codex native backend (#12374)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner package now has a complete Codex session driver
> - The driver needs a package-owned construction boundary before server
code can use it
> - Persisted provider contracts must not make deferred providers
executable
> - Provider selection must fail closed when an implementation is not
included
> - This pull request adds a Codex-only native backend and factory
> - It does not expose or enable the Paperclip Runner adapter

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` native backend construction.

**Problem or motivation**

The runner needs one normalized backend seam that constructs the
reviewed Codex driver. The seam must not route OpenCode, ACPX, Claude
Managed, or AWS AgentCore through an incomplete fallback.

**Proposed solution**

Add a Codex backend constructor and a Codex-first factory. Reject every
deferred provider at the factory and provider-specific constructor
boundaries.

**Alternatives considered**

Routing all provider contracts through the Codex protocol facade would
give deferred providers runtime behavior before their implementations
are reviewed. Including all provider backends would also broaden this
pull request beyond the Codex-first series.

**Roadmap alignment**

This connects reviewed runner package layers. It does not enable a new
adapter or change an existing direct adapter path.

## What Changed

- Added the Codex native backend constructor.
- Added the Codex-first native backend factory.
- Preserved the execution contract, runtime instructions, plan
constraints, dynamic tools, transport injection, and durable identity
requirements.
- Rejected every deferred provider with an explicit error.
- Added tests for lazy transport construction and both fail-closed
boundaries.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript` (35
files, 340 tests)
- `pnpm -r typecheck`
- `pnpm build`
- The focused native backend factory suite has 3 passing cases.

## Risks

The main risk is starting the wrong provider or starting a provider
before its runtime is ready. The factory and Codex constructor both
reject non-Codex inputs. Existing direct adapters do not call this
package-local factory.

## 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
canary/v2026.830.0-canary.8
2026-08-30 01:49:41 -05:00
Dotta 06f8773097 feat(runner): add Codex session driver (#12371)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The package now has bounded Codex transport, security, question,
diff, value, and thread helpers
> - Those isolated boundaries can now be composed into one provider
session lifecycle
> - The driver must preserve controller-owned identity, results,
terminals, and recovery invariants
> - Unsupported or mismatched provider traffic must fail closed without
weakening legacy adapters
> - This pull request adds only the Codex app-server driver and its
package-local tests
> - It does not expose or enable the Paperclip Runner adapter

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex app-server session driver.

**Problem or motivation**

The runner needs a production-shaped Codex session implementation that
turns provider facts into canonical PRP events while keeping task
identity, semantic completion, runtime input, and recovery under
controller authority.

**Proposed solution**

Compose the previously reviewed transport and normalization boundaries
into a Codex-only harness driver with session open/resume, turns,
streaming events, semantic tools, structured questions, goals, lineage,
usage, cancellation, reconciliation, and deterministic persisted
snapshots.

**Alternatives considered**

Keeping the full implementation in one initial transport pull request
would obscure the trust boundaries. Adding the deferred ACPX or OpenCode
paths here would also broaden the provider scope beyond the Codex-first
series.

**Roadmap alignment**

This implements the Codex provider slice inside the package. It does not
enable the runner adapter or change any existing direct adapter path.

## What Changed

- Added the Codex app-server harness driver and session lifecycle.
- Added controller-bound semantic completion and terminal handling.
- Added runtime requests, structured questions, goals, lineage, usage,
steering, interruption, and recovery.
- Added workspace diff and file-reference projection.
- Connected bounded/redacted provider data and notification identity
checks.
- Kept deferred provider identities and replacement behavior out of the
Codex-only driver.
- Added 62 focused driver cases covering lifecycle, security, recovery,
and protocol failures.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript` (34
files, 337 tests)
- `pnpm -r typecheck`
- `pnpm build`
- The focused Codex driver suite has 62 passing cases.

## Risks

The main risks are accepting provider events from the wrong session,
duplicating terminal facts, retaining unsafe provider data, or resuming
a different session. Tests cover pre-turn, cross-thread, stale-turn,
post-terminal, duplicate-result, cancellation, transport loss, provider
identity, workspace, redaction, structured input, and recovery cases.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 01:39:42 -05:00
Dotta a9297c3c07 test(runner): add Codex trace conformance (#12370)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Codex driver needs a controller-owned oracle for semantic
completion and replay
> - Provider proposals are advisory and must satisfy the exact task
envelope
> - Persisted events must be bounded and validated before deterministic
replay
> - Live provider behaviors also need one checked-in, schema-validated
fixture
> - This pull request adds that test and conformance layer before the
full driver
> - The runner adapter remains disabled and no production execution path
changes

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex trace, result-validation, and replay
conformance.

**Problem or motivation**

A provider-completed turn is not sufficient authority to finalize a
Paperclip run. Results must match the controller-owned completion
contract, and persisted provider events must be validated before they
can rebuild controller state.

**Proposed solution**

Add a bounded Codex trace harness that validates result proposals, emits
controller decisions and terminals, verifies live/replay parity, and
rejects malformed persisted streams. Add a validated fixture for runtime
requests, goals, lineage, controls, reconnect identity, and redaction
cases.

**Alternatives considered**

Embedding these assertions only in the production driver would mix
controller authority with provider transport behavior and make
deterministic replay harder to review.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable
the runner adapter or add another provider.

## What Changed

- Added exact task-envelope result validation.
- Added bounded persisted-event validation and deterministic replay.
- Added a controller-owned Codex trace harness and parity assertions.
- Added and validated the checked-in Live console conformance fixture.
- Updated the generated protocol manifest with the fixture source.
- Added focused result and fixture tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused trace-conformance test has 2 passing cases.

## Risks

The main risks are accepting a mismatched semantic result or replaying
corrupted provider history. Validation covers schema, contract revision,
criteria identity, disposition invariants, event identity, uniqueness,
ordering, terminal count, and byte limits.

## Model Used

OpenAI Codex with GPT-5.6 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
canary/v2026.830.0-canary.7
2026-08-30 01:22:50 -05:00
Dotta 6f6415d07e feat(runner): verify workspace file references (#12368)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Runner replies can refer to files produced inside an assigned
workspace
> - The task page needs stable file metadata without trusting arbitrary
Markdown paths
> - File verification must stay within the canonical workspace even
through symlinks
> - Reads and previews also need strict count and byte bounds
> - This pull request adds that provider-neutral file-reference boundary
> - A later pull request will connect it to the Codex session driver

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` workspace file-reference discovery.

**Problem or motivation**

Assistant-authored Markdown can contain external, absolute, escaping, or
symlinked paths. Reading those paths directly could disclose files
outside the assigned workspace or retain unbounded content.

**Proposed solution**

Parse a bounded set of local Markdown references, normalize them
relative to the workspace, verify canonical paths before reading, reject
symlink escapes, and retain bounded previews plus content digests.

**Alternatives considered**

Leaving path handling inside a provider driver would duplicate a
security-sensitive boundary and make it harder to test independently.

**Roadmap alignment**

This supports the Codex-first experimental runner and future
provider-neutral task projection. It does not enable the runner adapter.

## What Changed

- Added stable workspace file-reference records.
- Added local Markdown link extraction and path normalization.
- Added canonical-path and symlink-escape checks.
- Added bounded file reads, previews, and SHA-256 digests.
- Added focused path, preview, and symlink tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused workspace-reference test has 3 passing cases.

## Risks

The main risk is reading outside the assigned workspace or retaining
excessive data. Tests cover absolute and external paths, symlink
escapes, preview bounds, and deterministic metadata.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 01:13:30 -05:00
Dotta ac7f6ec1a3 feat(runner): normalize Codex thread state (#12367)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Codex thread state arrives as provider-specific goals, lineage,
notifications, and workspace paths
> - That data must be normalized before the full driver can retain or
project it
> - Notifications also need run and thread binding so unrelated provider
traffic is ignored
> - This pull request adds pure normalization helpers before the full
driver
> - A later pull request will use these helpers for the Codex session
lifecycle
> - The benefit is a small, independently tested trust boundary for
thread state

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex thread-state normalization.

**Problem or motivation**

Provider thread data can contain unsupported goal shapes, unrelated
notifications, unsafe workspace paths, or unbounded response values.
Passing it through directly would weaken run isolation and durable-data
bounds.

**Proposed solution**

Normalize goals and lineage into stable runner shapes, accept
notifications only when their run and thread identities match, constrain
workspace references to the assigned root, and retain only bounded safe
provider responses.

**Alternatives considered**

Keeping these rules embedded in the full driver would make the trust
boundary harder to review and test independently.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable
the runner adapter.

## What Changed

- Added normalized Codex thread goals and lineage.
- Added run- and thread-bound notification filtering.
- Added safe workspace-relative path and stat projection.
- Added bounded provider-response retention.
- Added focused normalization and isolation tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused thread-normalization test has 3 passing cases.

## Risks

The main risk is retaining data from the wrong provider thread or
accepting an unsafe workspace reference. Tests cover identity binding,
path normalization, response bounds, goal parsing, and lineage
projection.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 01:03:22 -05:00
Dotta 905177c93b feat(runner): bound Codex workspace values (#12366)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Provider data crosses workspace, event, trace, and tool-result
boundaries
> - Codex payloads can contain large or protected values
> - The runner also needs to reject unsafe working directories
> - This pull request adds pure boundary helpers before the full driver
> - A later pull request will use these helpers for Codex event handling
> - The benefit is bounded and redacted provider data with focused tests

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex value and workspace boundaries.

**Problem or motivation**

Raw provider payloads can exceed durable limits or contain credentials.
An invalid working directory can expose host state or escape the
assigned workspace.

**Proposed solution**

Validate the workspace against host and assignment roots. Bound retained
values by depth, count, string length, and byte size. Redact protected
keys and diagnostic credentials.

**Alternatives considered**

Keeping these checks inside the driver would make them harder to review
and reuse at every provider-data boundary.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable
the runner adapter.

## What Changed

- Added assigned-workspace validation.
- Added host home and Codex home overlap checks.
- Added retained payload bounds.
- Added recursive protected-value redaction.
- Added semantic completion tool disposition checks.
- Added focused security and bounds tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused boundary test has 3 passing cases.

## Risks

The main risk is accepting an unsafe workspace or retaining sensitive
provider data. Tests cover root escape, host overlap, size limits,
credential redaction, and completion-tool separation.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 00:53:48 -05:00
Dotta f44f5b1ab1 feat(runner): normalize Codex structured questions (#12365)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Existing adapters already use provider-neutral structured questions
> - Codex emits several provider-specific input and elicitation forms
> - Malformed native forms must fail closed instead of degrading to an
opaque prompt
> - This pull request adds the Codex question adapter without adding the
full driver
> - A later pull request will connect it to provider request handling
> - The benefit is a small compatibility boundary that preserves legacy
question behavior

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex structured input handling.

**Problem or motivation**

Codex user-input and MCP elicitation requests use different shapes. The
runner needs one canonical question set and must map validated answers
back to the correct provider response.

**Proposed solution**

Normalize native forms into `paperclip.question_set.v1`. Preserve
optional answers, select modes, validation bounds, and stable IDs. Map
canonical responses back only after validation.

**Alternatives considered**

Passing provider-native forms through PRP would couple the app to Codex
and would not preserve the existing provider-neutral question boundary.

**Roadmap alignment**

This supports the Codex-first experimental runner and existing
structured-question compatibility. It does not enable the runner
adapter.

## What Changed

- Added request-kind detection for approval, input, and elicitation
requests.
- Added requestUserInput normalization.
- Added JSON Schema elicitation normalization.
- Added canonical runtime request payloads.
- Added response mapping for Codex answers and MCP elicitation content.
- Added malformed-form and multi-question tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused question adapter test has 3 passing cases.

## Risks

The main risk is changing question semantics. Tests verify optional
answers, single and multi select modes, text validation, duplicate IDs,
numeric elicitation, and canonical response mapping.

## Model Used

OpenAI Codex with GPT-5.6 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
canary/v2026.830.0-canary.6
2026-08-30 00:46:00 -05:00
Dotta 9d7d9ea724 feat(runner): isolate Codex security configuration (#12364)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Codex executes commands inside the runner workspace
> - The provider process must not inherit host credentials or broad file
access
> - Planning mode also needs a read-only workspace boundary
> - This pull request defines the isolated launch and thread
configuration
> - A later pull request will use it from the Codex driver
> - The benefit is an independently reviewed security boundary

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex launch security.

**Problem or motivation**

A provider process can inherit host paths, environment secrets, network
access, or write permissions unless the runner constructs a closed
configuration.

**Proposed solution**

Build explicit app-server arguments and thread parameters. Deny host
roots and network access, allow only a small environment list, and use a
read-only profile for plan mode.

**Alternatives considered**

Relying on ambient Codex defaults would make runner safety depend on
each host installation.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable
the runner adapter.

## What Changed

- Added deny-by-default filesystem rules.
- Added separate execution and planning permission profiles.
- Added network denial.
- Added an explicit environment allowlist.
- Disabled host apps, plugins, memories, multi-agent behavior, and image
generation.
- Added security configuration tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused security configuration test has 3 passing cases.

## Risks

The risk is an overly broad provider launch. Tests verify denied host
roots, read-only context roots, workspace permissions, network denial,
and secret exclusion.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 00:35:56 -05:00
Dotta 3942739906 feat(runner): parse bounded Codex turn diffs (#12363)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Runner events need provider-neutral workspace change facts
> - Codex reports one complete unified diff snapshot per turn
> - Provider diff text can be large and can contain unsafe paths
> - This pull request adds only the bounded pure parser
> - A later pull request will connect it to the Codex driver
> - The benefit is an independently tested workspace boundary

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex event normalization.

**Problem or motivation**

Codex turn diffs need stable file operations and statistics. Raw diff
input must not escape the workspace or grow without bounds.

**Proposed solution**

Parse complete unified diff snapshots into normalized file records.
Bound file count and retained text, reject unsafe paths, and represent
binary changes without text.

**Alternatives considered**

Parsing diffs inside the main driver would make provider lifecycle
review larger and harder to test in isolation.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable an
adapter.

## What Changed

- Added create, modify, delete, rename, mode-change, and binary parsing.
- Added workspace-relative path validation.
- Added file-count and per-file text bounds.
- Added focused rename, binary, hostile path, and size tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused parser test has 2 passing cases.

## Risks

Low risk. This is a pure parser with no file-system access and no
production caller yet.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-30 00:27:19 -05:00
Dotta 83243d4b5d feat(runner): add bounded Codex app-server transport (#12362)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The first production runner provider is Codex
> - Codex app-server communicates with JSON-RPC over a child process
> - The process boundary needs explicit resource, environment, and
diagnostic limits
> - This pull request adds only the bounded transport layer
> - A later pull request will add the Codex event-mapping driver
> - The benefit is a small reviewable process boundary before provider
behavior is added

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` Codex transport.

**Problem or motivation**

The runner needs a safe way to start and communicate with Codex
app-server. Unbounded lines, queued notifications, pending requests, and
inherited credentials would make that boundary unsafe.

**Proposed solution**

Add a JSON-RPC process transport with explicit byte and count limits,
sanitized environment construction, process-group metadata,
server-request handling, redacted diagnostics, and deterministic
closure.

**Alternatives considered**

Adding transport and the full Codex driver in one change would create a
much larger review surface. This pull request isolates the child-process
boundary.

**Roadmap alignment**

This supports the Codex-first experimental runner. It does not enable
the runner adapter.

## What Changed

- Added bounded JSON-RPC request and notification queues.
- Added malformed-message and oversized-line fail-closed behavior.
- Added sanitized Codex environment construction.
- Added process-group tracking and deterministic shutdown.
- Added redacted diagnostics and server-request replies.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused transport test has 6 passing cases.

## Risks

The main risk is child-process cleanup. Tests cover closure, pending
request rejection, queue bounds, process metadata, and malformed input.

## Model Used

OpenAI Codex with GPT-5.6 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
canary/v2026.830.0-canary.5
2026-08-30 00:07:50 -05:00
Dotta ea86e780af feat(runner): add authorized scenario tool runtime (#12361)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner action catalog defines what scenario tools can exist
> - A catalog entry must not grant authority by itself
> - Scenario runs need run-scoped discovery and invocation checks
> - Observable results must not expose protected values
> - This pull request adds an authorized package-local scenario tool
runtime
> - The benefit is deterministic tool testing without production service
authority

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` scenario tool runtime.

**Problem or motivation**

Scenario tests need to expose only authorized actions. They also need
stable denial records, redaction, and idempotent command handling.

**Proposed solution**

Project the canonical scenario contracts into a visible catalog. Recheck
policy at invocation. Dispatch allowed operations through the mock
control-plane port and return redacted receipts.

**Alternatives considered**

Direct production bindings are outside this pull request. The runtime
uses only the package-local mock port.

**Roadmap alignment**

This supports runner conformance and scenario testing. It does not
enable an adapter or production service call.

## What Changed

- Added run-scoped scenario tool discovery.
- Added claim, role, task-mode, and policy authorization.
- Added input validation, redaction, and authorization records.
- Added fake-agent and Codex definition projections.
- Added deterministic mock dispatch and idempotency coverage.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused semantic runtime test has 10 passing cases.

## Risks

Low risk. The runtime is package-local and uses the mock control-plane
port. It creates no production binding.

## Model Used

OpenAI Codex with GPT-5.6 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
canary/v2026.830.0-canary.4
2026-08-29 23:50:11 -05:00
Dotta e11b457fd9 feat(runner): complete the canonical action catalog (#12360)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Paperclip Runner needs a stable list of semantic actions
> - Earlier pull requests define the core and collaboration action
groups
> - The remaining domain and administration actions need the same
contract form
> - The complete catalog must remain data only until a later pull
request binds actions to services
> - This pull request completes and validates the canonical action
inventory
> - The benefit is one frozen source of truth for later discovery and
authorization work

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` protocol contracts.

**Problem or motivation**

The runner does not yet have a complete canonical inventory for domain
and administration actions. Later authorization code cannot project a
stable operation catalog without this inventory.

**Proposed solution**

Add the remaining action contracts and aggregate all 41 actions.
Validate every declared live and scenario projection with its own
schema.

**Alternatives considered**

Binding these actions directly to production services would combine data
contracts with authority. This pull request keeps every production
service binding unbound.

**Roadmap alignment**

This change supports the experimental Paperclip Runner. It does not
enable the runner or change an existing adapter.

## What Changed

- Added 14 domain and administration action contracts.
- Added the complete immutable 41-action catalog.
- Added validation for live inputs and outputs.
- Added validation for scenario inputs and capability-result envelopes.
- Kept every production service binding unbound.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The focused catalog test validates 41 actions.

## Risks

Low risk. This pull request adds package-local contract data and tests.
It does not authorize an action or change an adapter.

## Model Used

OpenAI Codex with GPT-5.6 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
2026-08-29 23:23:05 -05:00
Dotta 4eb32d7532 Add collaboration action contracts (#12359)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents collaborate through discovery, delegation, dependencies, and
governed approvals
> - These optional operations need stable contracts before any run may
discover them
> - The core action contracts are already isolated in the lower stack
> - This pull request adds the 13 collaboration and governance action
definitions
> - It does not grant claims or bind production services
> - The benefit is a reviewable contract layer for later run-scoped
authorization

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner protocol action contracts

**Problem or motivation**

Optional collaboration operations need one provider-neutral definition
for policy metadata, documentation, live and scenario schemas, and
canonical examples.

**Proposed solution**

Add one immutable module for each discovery, delegation, dependency, and
governance action. Add a collaboration aggregate and validate all
examples with JSON Schema.

**Alternatives considered**

These contracts could land with executable authorization. That would
make contract review depend on runtime policy and server service
bindings.

**Roadmap alignment**

This supports the existing experimental Paperclip Runner rollout. It
does not make any optional operation discoverable or invocable.

## What Changed

- Add 13 collaboration and governance action definitions.
- Add immutable policy, schema, documentation, and example data.
- Add a collaboration-only aggregate.
- Validate every action example against its declared schema.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The branch changes 15 files relative to its declared base.

## Risks

Low production risk. The declarations do not grant claims or contain
executable service bindings. Tests require optional placement, immutable
metadata, stable identities, and schema-valid examples.

> 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`, with 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 an existing public issue 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
- [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.830.0-canary.3
2026-08-29 23:13:49 -05:00
Dotta 08b5d6bd9b Add core runner action contracts (#12358)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Runner tools need stable provider-neutral action contracts
> - Core task work must use the same names, policy metadata, schemas,
and examples on every provider surface
> - A single large 41-action review would hide contract drift
> - This pull request adds only the 14 always-present core action
definitions
> - It does not grant discovery or execution authority
> - The benefit is a reviewable immutable contract base for later
authorization wiring

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner protocol action contracts

**Problem or motivation**

The runner has an older compact catalog, but it does not single-source
the full policy metadata, documentation, live shape, scenario shape, and
examples for each core action.

**Proposed solution**

Add one immutable definition module per core action. Add an internal
core aggregate and validate every input and output example against its
declared JSON Schema. Keep all production authorization and execution
unavailable.

**Alternatives considered**

All 41 action definitions could land in one pull request. That would
create more than 7,000 changed lines and reduce useful review depth.

**Roadmap alignment**

This supports the existing experimental Paperclip Runner rollout. It
does not enable the adapter or expose any new production tool.

## What Changed

- Add 14 core protocol action definitions.
- Add immutable policy, schema, documentation, and example data for each
action.
- Add a deep-freeze helper and a core-only aggregate.
- Validate all core examples with JSON Schema.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The branch changes 17 files relative to its declared base.

## Risks

Low production risk. These declarations do not contain executable
authorization or service bindings. The main risk is schema drift. Tests
validate operation identity, placement, immutability, and canonical
examples.

> 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`, with 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 an existing public issue 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
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-29 23:05:05 -05:00
Dotta 300b7f4b7e Add deterministic capability control plane (#12355)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Semantic operations need a control plane that owns authorization and
state changes
> - Conformance tests need this authority without a live server or
database
> - The existing in-memory port covers transport facts but not
capability-governed domains
> - This pull request adds a deterministic capability-aware control
plane for tests
> - It keeps the implementation behind the package testing entry point
> - The benefit is repeatable authorization and mutation tests before
production wiring lands

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner testing and semantic capability contracts

**Problem or motivation**

Later semantic action slices need deterministic company, actor, task,
governance, workspace, secret, budget, routine, and audit state. A live
Paperclip server would make those tests slow and environment-dependent.

**Proposed solution**

Add serializable capability fixture types and an in-memory control-plane
adapter. Enforce company scope, claims, roles, idempotency, redaction,
faults, and audit records. Export the adapter only from the testing
entry point.

**Alternatives considered**

The tests could mock each action separately. That would duplicate
authorization rules and would not verify state transitions across
multiple actions.

**Roadmap alignment**

This supports the existing experimental Paperclip Runner rollout. It
does not enable production semantic operations or change app execution.

## What Changed

- Add deterministic capability fixture types and seed state.
- Add an in-memory capability control-plane adapter.
- Enforce run, company, actor, claim, role, and idempotency boundaries.
- Model governed task, document, interaction, workspace, secret,
routine, and audit changes.
- Add deterministic tests and testing-entry-point exports.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The branch changes 5 files relative to its declared base.

## Risks

The main risk is a permissive mock that hides a production authorization
error. The adapter fails closed for missing claims, wrong roles,
cross-company access, duplicate mutations, invalid state, and restricted
secret access. Tests cover each fixture domain and serialized restore
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, `gpt-5`, with 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 an existing public issue 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
- [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
canary/v2026.830.0-canary.2
2026-08-29 22:54:30 -05:00
Dotta 773d357d8a Add deterministic runner conformance core (#12354)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner needs repeatable tests at the provider and control-plane
boundaries
> - Network services and live providers cannot produce deterministic
conformance results
> - Small in-memory adapters can exercise the same public contracts
without production side effects
> - This pull request adds a deterministic harness driver, control-plane
adapter, and fixture runner
> - It exposes these helpers only from the testing entry point
> - The benefit is stable cross-boundary verification for later runtime
changes

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner testing and conformance support

**Problem or motivation**

The public runner contracts have unit tests, but later provider and
server slices need a deterministic way to exercise session, event,
replay, checkpoint, and result behavior together.

**Proposed solution**

Add in-memory implementations of the harness-driver and control-plane
ports. Add a canonical conformance fixture and runner. Export these
utilities only from `@paperclipai/paperclip-runner/testing`.

**Alternatives considered**

The tests could start a real provider or server. That would make the
conformance gate slower, less portable, and dependent on credentials or
network state.

**Roadmap alignment**

This supports the existing experimental Paperclip Runner rollout. It
does not enable a production adapter or change current app execution.

## What Changed

- Add a deterministic harness-driver implementation.
- Add an in-memory control-plane adapter with replay and checkpoint
support.
- Add a canonical provider-neutral conformance fixture.
- Add a reusable conformance runner and contract tests.
- Export the helpers from the package testing entry point only.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- The branch changes 10 files relative to its declared base.

## Risks

Low risk. This pull request adds test-only adapters and conformance
helpers. It does not select a runtime or change production behavior.
Contract tests verify event identity, replay, checkpoints, and
deterministic results.

> 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`, with 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 an existing public issue 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
- [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
canary/v2026.830.0-canary.1
2026-08-29 22:04:18 -05:00
Dotta e18632ebcb Add durable semantic tool receipts (#12353)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Semantic tools cross a trust boundary between a provider and the
control plane
> - Durable runs need exact input, result, denial, duplicate, and
reconciliation receipts
> - Replay must reject unsupported required versions and mismatched
receipt pairs
> - This pull request adds the receipt builders and deterministic replay
fixtures
> - It keeps newer sequence and gap safety limits from the current stack
> - The benefit is auditable semantic activity before more providers use
it

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner

**Problem or motivation**

Semantic tool calls have basic authorization records, but durable replay
does not yet cover reconciled calls, denial redaction, duplicate
receipts, governance targets, or artifact references.

**Proposed solution**

Add bounded semantic receipt builders, a reconciled phase, strict pair
binding, fail-closed version checks, and generated replay oracles for
the important lifecycle cases.

**Alternatives considered**

The runner could store provider-native tool payloads. That would weaken
protocol portability and make redaction and retry behavior
provider-specific.

**Roadmap alignment**

This supports the existing experimental Paperclip Runner rollout. It
does not enable a production adapter.

## What Changed

- Add semantic input and result receipt builders.
- Add optional reconciliation receipts for pending calls.
- Reject unsupported semantic receipt versions.
- Validate receipt correlation, operation, idempotency, and digest
bindings.
- Add deterministic replay fixtures and generated golden outputs.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- Replay golden and protocol manifest checks pass.
- The branch changes 27 files relative to its declared base.

## Risks

The main risk is accepting a receipt that belongs to another call or
replaying a duplicate as a new mutation. Binding checks compare
correlation, operation, idempotency, and content digest fields. Fixtures
cover denials, duplicates, governance chains, optional fields,
artifacts, and unsupported versions.

> 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`, with 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 an existing public issue 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
- [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
2026-08-29 21:48:06 -05:00
Dotta d18e281c33 Add the native runner session runtime (#12352)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Paperclip Runner package needs one provider-neutral session loop
> - Native execution contracts now define the accepted input and output
> - Backends still need bounded execution, recovery, and control-plane
ports
> - This pull request adds that package-local session runtime
> - It does not change server runtime selection or start the
experimental runner
> - The benefit is a tested execution core for later provider and server
layers

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner

**Problem or motivation**

The runner contracts do not yet have a shared session loop. Each backend
would otherwise duplicate event handoff, terminal handling, recovery
cursors, timeouts, and checkpoint behavior.

**Proposed solution**

Add the native session runtime, backend interfaces, control-plane port,
harness driver contract, deterministic conformance helpers, and bounded
tests.

**Alternatives considered**

The server could own this loop. That would mix provider process behavior
with server persistence and authority logic.

**Roadmap alignment**

This is part of the existing experimental Paperclip Runner rollout. It
does not enable a production adapter.

## What Changed

- Add a provider-neutral native session execution loop.
- Add recovery cursor reconciliation and checkpoint hooks.
- Add bounded timeout and governed-wait behavior.
- Add harness driver and control-plane conformance helpers.
- Add deterministic backend and session runtime tests.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- `pnpm build`
- Protocol generation and manifest checks pass.
- The branch changes 14 files relative to its declared base.

## Risks

The main risk is a session that hangs, duplicates an event, or restores
the wrong cursor after reconnect. Tests cover terminal events, timeouts,
durable handoff, duplicate receipts, recovery, continuity breaks, and
checkpoint updates. The change remains package-local.

> 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`, with 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
- [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
2026-08-29 20:42:48 -05:00
Dotta d8dfa27a1e Define native runner execution contracts (#12351)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Paperclip Runner package gives providers one stable execution
boundary
> - Later runner backends need one validated input and result contract
> - Provider-specific shapes cannot leak into server orchestration
> - This pull request adds the provider-neutral native execution
contracts
> - It also keeps legacy input versions readable while it validates new
input strictly
> - The benefit is a stable boundary for later backend and server pull
requests

## Linked Issues or Issue Description

**Subsystem affected**

packages/paperclip-runner

**Problem or motivation**

The runner has protocol transport and Codex support, but later backends
do not have one public contract for execution input, runtime context,
completion output, and recovery state.

**Proposed solution**

Add versioned native execution input parsers, model envelopes,
completion result helpers, runtime context contracts, and durable
recovery types. Keep these changes package-local. Do not change server
runtime selection.

**Alternatives considered**

Each provider could define its own server-facing input. That would
couple server orchestration to provider details and make compatibility
harder to verify.

**Roadmap alignment**

This is part of the existing experimental Paperclip Runner rollout. It
does not enable a new production adapter.

## What Changed

- Add versioned native execution input contracts and strict parsers.
- Add provider-neutral runtime context and completion contracts.
- Add durable recovery and local runner types.
- Add structured question compatibility and parser tests.
- Export only the contracts that exist in this stack layer.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test:typescript`
- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm -r typecheck`
- Protocol generation and manifest checks pass.
- The branch changes 12 files relative to its declared base.

## Risks

The main risk is accepting malformed or future input as a supported
contract. The parsers reject unknown required versions and unknown
fields. The change is package-local and does not select or start the
experimental runner.

> 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`, with 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
- [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.830.0-canary.0
2026-08-29 19:53:41 -05:00
Dotta b1cd261212 feat(runner): normalize provider event contracts (#12350)
## Thinking Path

> - The runner already persists PRP events, but provider-native activity
needs one bounded, provider-neutral vocabulary before additional
providers can be added safely.
> - The protocol catalog must describe capabilities without enabling or
authorizing a provider.
> - Provider normalization must not require an ACPX runtime dependency
merely to compile the shared event layer.
> - This pull request adds the event contract and pure normalizers only;
provider transports and production selection remain unchanged.

## Linked Issues or Issue Description

This is the first follow-up stacked on #12321. Codex, OpenCode, and ACP
runtimes expose different activity shapes. Without canonical
normalization, downstream task threads and traces would need
provider-specific branching and could retain unbounded or unsafe
payloads.

## What Changed

- Expand the PRP provider descriptor and canonical activity event
families.
- Add bounded Codex, OpenCode, and ACP event normalizers for plans,
tools, research, delegation, artifacts, review, safety, waits, and
notices.
- Preserve strict schema validation and regenerate the checked-in schema
bundle and manifest.
- Use a structural ACP event input so the provider-neutral layer does
not introduce or authorize an ACPX runtime dependency.
- Export the provider-event contract from the existing package root.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript`
- `pnpm --filter @paperclipai/paperclip-runner test:typescript` — 11
files and 88 tests passed.
- `pnpm -r typecheck`
- `pnpm build`
- `git diff --check`
- The local full repository runner reached unrelated macOS
workspace-path fixture failures; the affected runner suites pass and the
repository CI shards are the handoff authority.
- Diff against the declared base: 8 files.

## Compatibility Boundary

- No provider transport, adapter, server route, feature flag, or runtime
selection changes.
- Catalog presence does not authorize discovery or execution.
- Existing Codex execution continues through its current path.
- No dependency, migration, workflow, or lockfile change.

## Risks

The main risk is accepting malformed or unbounded provider payloads.
Schema validation remains fail-closed, text/output fields are bounded
and redacted, unsafe paths and URLs are discarded, and representative
variants for every declared event family are covered by tests.

## Model Used

OpenAI Codex, GPT-5 family. The client does not expose the exact
deployment ID or context window. Agentic reasoning, tool use, and code
execution were enabled.

## 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 described the issue in-PR following the relevant template
- [x] I have not referenced internal/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 local tests and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated the compatibility notes for this change
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open actionable comments
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-29 19:44:24 -05:00
Dotta bc9ba7cd26 feat(runner): project native runs into task threads (#12321)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The experimental Paperclip Runner can execute a guarded Codex run
and persist provider-neutral events.
> - The task page still reads direct-adapter transcripts and cannot
present those native events.
> - Structured runner questions must also use the existing task
interaction experience.
> - Runtime selection must use the persisted run mode, not an adapter
name or a current feature flag.
> - This pull request projects native events and questions into the
existing task thread.
> - Direct adapters keep their existing transcript, composer,
interaction, and finalization paths.
> - The benefit is a complete native Codex task thread without a
behavior change for existing adapters.

## Linked Issues or Issue Description

Refs #12202. This pull request replaces that stale implementation on
current `master`.

**What happened?**

The server persists native runner events and structured input requests.
The task page only consumes direct-adapter transcripts. A native run
therefore cannot present a complete transcript, usage, or question flow
through the normal task experience.

**Expected behavior**

Native runs project persisted provider-neutral events into the existing
task thread. Native structured questions use the existing interaction
card. Direct adapters retain their current behavior.

**Steps to reproduce**

1. Enable the experimental runner.
2. Start a native Codex run that emits progress, usage, a structured
question, and a final reply.
3. Open the task page.
4. Observe that the direct-adapter transcript path cannot project the
native event records.

**Paperclip version or commit**

`master` at `67f9867bc`.

## What Changed

- Add the canonical structured-question validator and shared contract
exports.
- Materialize native input requests as existing task interactions.
- Validate native answers and deliver them through the durable
question-response receipt.
- Resume the original PRP request with an idempotent `request.resolve`
command.
- Project native messages, tool activity, cumulative usage, and final
replies into the existing transcript model.
- Propagate persisted `runtimeMode` to the task page and select native
handling only for `runtimeMode: "native"`.
- Expire pending interactions through the shared issue service on every
terminal transition, including decisions, stalled reviews, tree control,
and pipeline retry cleanup.
- Queue native run cancellation while a transaction is open and execute
it only after the owning transaction commits.
- Keep nonterminal and non-runner issue paths on their existing service
call shapes and behavior.

## Verification

- `pnpm --filter @paperclipai/server typecheck` — passed, including the
Rust runner release build and protocol/catalog drift gates.
- Focused native-thread and lifecycle suites — 18 files and 481 tests
passed during review.
- `issue-execution-policy-routes.test.ts` — 19/19 passed after the final
transactional-queue expectation update.
- `issue-agent-mutation-ownership-routes.test.ts` — 87/87 passed in the
final isolated compatibility rerun.
- GitHub Actions — policy, build, canary, typecheck/release registry, 5
serialized server shards, 8 general-test shards, 3 browser shards, and
both aggregate gates passed on `7793f3193`.
- Security — Snyk, Socket Project Report, Socket PR Alerts, and
Superagent passed.
- Greptile — 5/5 on `7793f3193`; all actionable review threads resolved.
- `git diff --check` — passed.
- Diff against `master`: 44 files.

## Compatibility Boundary

- Native transcript polling only runs when the persisted run reports
`runtimeMode: "native"`.
- Missing or legacy runtime modes continue through
`useLiveRunTranscripts`.
- Legacy questions keep the existing optional free-text choice.
- Native closed select sets can suppress that legacy fallback.
- Terminal cleanup uses the same issue service for native and legacy
interactions; only a bound native question schedules a native run
cancellation.
- Native cancellation happens after transaction commit, so failed or
rolled-back writes do not cancel a still-valid run.
- The durable delivery service checks the original native request before
it considers a continuation run.
- This pull request adds no migration, dependency, workflow, manifest,
or lockfile change.

## Risks

The main risk is routing a direct-adapter task through native handling
or changing terminal issue behavior. The implementation selects the
native path only from persisted runtime facts, retains the existing
nonterminal call shape, and schedules native cancellation only for a
validated bound native question after commit. Focused and
repository-wide tests cover both paths. Native requests remain bound to
the company, issue, run, and agent; answers are validated, durable, and
idempotent across reconnects.

## Model Used

OpenAI Codex, GPT-5 family. The client does not expose the exact
deployment ID or context window. Agentic reasoning, tool use, and code
execution were enabled.

## 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
- [x] I have run the affected local tests and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated the compatibility notes for this change
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I addressed all Greptile and reviewer comments before requesting
merge
2026-08-29 19:26:20 -05:00