Commit Graph
316 Commits
Author SHA1 Message Date
DottaandPaperclip ad861a7f94 fix(runner): allow bounded controller admission before welcome (#17735)
## Thinking Path

> - Paperclip manages AI agents and preserves their work across
execution failures.
> - Native Runner authentication exchanges a one-use bootstrap ticket
for a connection lease.
> - The controller must admit the connection and persist that lease
before it sends welcome.
> - Runnerd waited only two seconds for welcome, even when its
connection setup budget allowed more time.
> - A slow valid welcome therefore looked like a consumed-ticket failure
before provider work could start.
> - This pull request uses the existing ten-second connection setup
budget for welcome.
> - The benefit is reliable startup during bounded controller delays,
with the same authentication and replay checks.

## Linked Issues or Issue Description

**What happened?**

A valid native Runner bootstrap can fail while the controller completes
admission. The runner then reports `bootstrap connection failed closed;
provide a fresh one-use ticket`. A later recovery attempt can report an
indeterminate authority and hide the startup error behind a finalization
deadline.

**Expected behavior**

A valid welcome can arrive within the connection setup budget. An
earlier execution or reconnect deadline still ends the wait. A missing
or invalid welcome never permits bootstrap-ticket replay.

**Steps to reproduce**

1. Run the real Runner WebSocket transport against an authenticated
controller.
2. Hold the welcome for three seconds after the client proof arrives.
3. Before this change, authentication fails with `WebSocket
authentication message deadline elapsed` and `bootstrap_maybe_consumed:
true`.
4. With this change, the runner accepts the bound lease and restores the
normal read timeout.

**Paperclip version or commit**

Reproduced against `a1f77821b9` before the production change.

**Agent adapter(s) involved**

Native Paperclip Runner. The transport is shared by its provider
drivers.

Related: #17401 reduces repeated work in warm-recovery admission. This
change covers delayed welcome delivery for fresh authentication too. It
does not replace that optimization. #17594 addresses a separate lifetime
failure after controller outages.

## What Changed

- Use the ten-second connection setup budget for the authenticated
welcome.
- Keep the execution/reconnect deadline as an earlier bound.
- Add real WebSocket regressions for a delayed welcome and a shorter
lifecycle deadline.
- Add a real Runner process test proving a delayed admission starts one
provider and keeps it through two turns.
- Document the startup contract and its recovery verification scope.

## Verification

- Red: the delayed-welcome regression failed against unchanged
production code with a message deadline and `bootstrap_maybe_consumed:
true`.
- Green: all 402 Runner core library tests pass. The suite includes
authentication, ticket fencing after a lost welcome, identity rejection,
replay, and no repeated provider effects.
- Map and module checks pass.
- Workspace `pnpm -r typecheck` and `pnpm build` pass. The new process
integration test passes (one provider process, one thread, two turns,
suspended with an empty outbox).
- Live acceptance at this branch's production Runner build passes on
macOS arm64 with pinned OpenCode 1.18.34 and
`openrouter/deepseek/deepseek-v4.1-flash-1017`: delay admission by three
seconds, create a file, suspend, resume the same provider session under
a fresh run authority, read the first file, and write a second file.
Both useful outputs match exactly; final runner state is suspended.
- Preserved setup failures: a non-pinned executable was rejected, and
the debug binary exceeded cold provider startup admission. The pinned
executable and release binary passed. The first harness also tried to
reuse a completed task object; the follow-up used the normal resume
path. Exactly two paid model turns ran.
- The full local `pnpm test:run` was attempted and stopped after the Mac
exhausted PostgreSQL semaphore capacity (`could not create semaphores`);
it is not a local full-suite pass.
- Current-head CI is green at
`df5d5494c9f9f444114aaf12e095a554110d2e14`: all checks passing or
non-applicably skipped, zero failures or pending checks. The additional
Superagent security scan triggered by ready-for-review also passed.
These include all general/serialized test shards, Runner Rust/Vitest,
E2E, typecheck, build, and the final verify gate. Greptile reviewed that
exact commit at 5/5 with no findings or inline comments.
- This proves the actual native Runner/provider path locally. It does
not prove rollout or recovery on a hosted Linux/amd64 execution
environment.

## Risks

- A stalled welcome can take up to eight seconds longer to fail when the
configured lifecycle allows it. Shorter execution/reconnect deadlines
still take precedence.
- Authentication proofs, credential expiry, identity binding, and
one-use-ticket fencing remain enforced.
- This does not repair provider-side grammar errors or authorize replay
of an indeterminate historical run. Recovery of existing work requires
the normal stopped-owner and retained-state checks.
- No schema or migration change. A new Runner binary must reach the
execution host before this change affects remote runs.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository inspection, code
execution, and browser tools. The exact serving submodel identifier and
context window were not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 10:25:59 -05:00
DottaandPaperclip bbe1016d81 feat(evals): retain bounded native tracing in the Runner controller (#17493)
Retain bounded native tracing in the Runner controller with attempt-bound relays, private export receipts, offline cost replay, conservative holds and bounded failure diagnostics.

Verified exact head 5cb991421e: full hosted CI, fresh Greptile 5/5, zero unresolved threads, 70 local controller tests including actual Codex/Claude CLI observability validators. Secondary review has no must-fix or should-fix findings and records optional coverage follow-ups. No paid evals or schedule changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-26 10:22:42 -05:00
DottaandPaperclip 3f91d58dd5 fix(ci): provide Copilot auth only to protected paid eval cells (#17743)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Paid runner evals test real provider integrations.
> - Copilot cells use the saved-token connection path.
> - The two trusted workflows did not pass the Copilot credential to
those cells.
> - This PR supplies it only when the selected cell needs it.
> - Existing environment and actor gates protect access in this public
repository.

## Linked Issues or Issue Description

Related: #15705 and #15706. A search found no open PR that adds this
workflow credential binding.

**Describe the bug**

Copilot Product and direct-protocol eval cells require
`COPILOT_GITHUB_TOKEN`. The protected paid workflows do not currently
pass that environment secret to the selected execution step.

**Expected behavior**

Only a selected Copilot cell receives this credential. Ordinary PR,
build, catalog, image and reporting jobs receive none.

**Steps to reproduce**

Dispatch the trusted full-stack workflow for one Copilot cell.
Credential validation fails before the task starts, although the
protected environment can hold a valid token.

**Environment**

GitHub Actions in the public `paperclipai/paperclip` repository, with
the reviewed workflow on `master` and the `runner-e2e-paid` environment.

## What Changed

- Pass `COPILOT_GITHUB_TOKEN` in the paid Product and direct-protocol
execution steps, only when `matrix.credentialName` selects it.
- Add the missing Copilot protocol-catalog credential mapping and verify
it reaches the selected execution matrix.
- Add security checks for the selected-cell binding and bounded
protected-job scope. Extend the scan that rejects provider credentials
in unrelated workflows.
- Document the Copilot credential scope. No secret values, account data
or private test evidence are in this PR.

## Verification

- Product workflow security: 16 tests passed on this head.
- Protocol catalog and workflow security: 21 tests passed, including the
Copilot matrix regression reproduced red before its fix.
- Current-head required `ci / verify` and `ci / e2e` are green. Greptile
is 5/5 with zero unresolved review threads.
- The first CI attempt retained runner-shutdown failures; one failed-job
retry passed on the unchanged head. Both attempts remain in [the CI
run](https://github.com/paperclipai/paperclip/actions/runs/40342429106).
- `git diff --check` passed.
- A selected-credential scan found zero matching secret values in the
seven changed files.
- The environment setting was separately checked: `master` only,
required approval from existing allowlisted code owners, and
administrator bypass disabled. The new secret exists only at environment
scope; no repository-wide duplicate was created.
- The packaged Copilot runtime verified the selected token and the
explicit model without a model prompt. A fresh local UI journey then
created an agent, completed its first task and verified the downloaded
artifact and cleanup.

## Risks

The selected paid cells gain access to one additional environment
credential. Missing credentials still fail closed. Default-branch
checks, initiating/rerunning actor checks, protected environment access
and per-cell credential selection remain in place. This PR adds no
trigger and gives no credential to builds or ordinary PR checks.

## Model Used

OpenAI Codex, based on GPT-6, with repository tools and browser
regression tests. The exact runtime model identifier is not exposed in
this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 10:17:14 -05:00
DottaandPaperclip 49bd7a4ba6 feat(evals): retain portable Runner controller evidence (#17469)
Retain private Runner request evidence for offline cost reconciliation. Bound post-child reads, reject hidden paid tools, exclude configured credentials, bind incomplete results, and replace redacted proof atomically.

Verified at f5c1791623: full hosted CI, Greptile 5/5, secondary review summary 5/5, no unresolved threads. No paid evals or schedule changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-26 09:50:58 -05:00
DottaandPaperclip 41c42895fa feat(evals): enforce fixed Runner request allocations (#17452)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Runner evals execute real provider harnesses against maintained
fixtures.
> - Turn-level usage arrives after requests have already spent money.
> - Parallel cells need distinct allowances before requests start.
> - Missing output must preserve the remaining allowance and any known
charges.
> - This pull request adds a controller that reuses the existing request
ledger and gateway.
> - It makes a bounded local Runner attempt reviewable before hosted
scheduling is enabled.

## Linked Issues or Issue Description

Refs #17440. That PR added the explicit Runner gateway route. This PR
owns request admission and retained campaign accounting for that route.

The existing hosted matrix is not enabled or changed here. Its global
allocation, rerun rejection, and private evidence archive remain
separate integration work.

## What Changed

- Validate a trusted manifest with exact request, CLI, package, daemon,
model, and source identities. Assign each selected cell a distinct
allowance. Count operating overhead once. Reject allocations above the
campaign limit before launch.
- Run native Codex or ACPX Claude through the shared request proxy and
append-only ledger. Pass only the proxy credential to the child. Refuse
local attempt reuse and preserve existing output files.
- Close gateway admission on cancellation. Retain the ledger, receipts,
route descriptor, child result, and cleanup evidence outside the
disposable workspace.
- Recompute campaign accounting from retained ledgers. Missing or
invalid final evidence holds the full cell allowance while preserving
known charges. Reports distinguish provisional and incomplete costs.
- Accept namespaces containing only local function/custom tools. Disable
web search in the controlled Codex profile. Continue to reject hosted
tools, including tools hidden inside a namespace.
- Add controller tests to the existing Runner static test path and
document this source-checkout entry point.

## Verification

- 20 controller tests pass. They use real child processes, local HTTP,
and the actual ledger. Cases cover reservations before dispatch,
concurrent cell isolation, caps, cancellation, replay rejection, lost
artifacts, changed receipts, and Braintrust Claude routing. Upstream
responses are synthetic.
- 52 shared gateway tests and 55 Runner CLI tests pass. The namespace
acceptance and web-search configuration regressions failed before the
repair and pass afterward.
- Runner TypeScript/Rust checks, Runner build, shared E2E typecheck, and
`git diff --check` pass.
- The first actual-harness probe found that Codex advertised both a
local tool namespace and web search. It reached no upstream transport.
That failure is retained; the compatibility repair does not allow paid
hosted tools.
- An earlier test failure showed that separate dynamic imports created
different admission-error classes. The shared runtime bridge now loads
one module graph. Another regression showed that a missing final report
hid known ledger charges; the collector now preserves those charges.
- The repaired actual-harness probe passed its control checks for native
Codex and ACPX Claude: each reached exactly one synthetic upstream
request after the ledger reservation; both retained the unresolved hold
and route evidence; both recorded clean process exit. A scan of 41
retained files found no synthetic upstream credential. Deliberate
provider rejection preserved the failed Codex turn and Claude timeout;
these are not semantic passes. Prices, operating bounds, and the package
archive identity in this probe were synthetic.
- Review regressions reproduced lost request/receipt evidence, lost
admission metadata, executable replacement after verification, and a
SIGTERM-resistant descendant surviving the CLI. The repairs now pass.
Executable bytes are staged before launch; a trusted Node resolution
hook preserves relative imports. A symlink-path regression also failed
before its repair and now passes. The final staged native probe repeated
both one-request checks successfully.
- Full current-head
[CI](https://github.com/paperclipai/paperclip/actions/runs/40115932485)
passed on `4781487215116afd10a415d4db53b1ec8e004dd5`: all 58 check runs
and the legacy status are successful, neutral, or skipped. Greptile and
Paperclip both reviewed this commit at 5/5. All five finding threads are
fixed and resolved. No paid provider request ran during this change.

## Risks

- This is a trusted source-checkout controller, not a published package
command. It needs the repository's installed shared cost dependencies.
- The manifest declares reviewed prices and full-lifecycle bounds.
Synthetic tests do not qualify real prices, invoices, storage, or
Braintrust metering.
- The attempt-directory guard is local. Hosted fanout still needs unique
global allocations, rerun rejection, and durable private retention. Do
not enable the existing matrix on this change alone.
- Forced child termination can leave cleanup unverified. That attempt
remains incomplete and holds its full allocation. These checks do not
claim a host security boundary against an adversarial target.
- The current private publisher does not archive the separate controller
directory. Native trace relay, private report integration, and live
qualification remain open.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. This runtime does not expose the exact model ID or
context-window size.

## 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-10-26 07:53:57 -05:00
Devin FoleyandPaperclip 34409a92c4 fix(native-runtime): stop failover backups from carrying throwaway provider state (#17618)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Native runner sessions on managed sandboxes keep a failover backup
of provider state, so a replacement sandbox can resume the session
> - Each backup copies the provider's runtime directory, with a
per-directory sha256 manifest, minus `excludeEntries`
> - Codex already excludes credentials and re-downloadable plugin
caches; OpenCode excluded nothing, and ACPX excluded only per-agent
credentials
> - OpenCode also leaked a temporary HOME on every launch, because
removing it failed on the read-only skill snapshot inside and the error
was swallowed
> - So every backup carried every earlier launch's HOME (with its npm
cache) plus re-installable plugin `node_modules`
> - This pull request removes those homes correctly, sweeps homes left
by earlier versions, and excludes the throwaway entries from OpenCode
and ACPX backups
> - The benefit is much smaller backups and live session directories,
while session history is still backed up and restored

## Linked Issues or Issue Description

Bug report described in-PR (bug report template).

**What happened?**
On one instance, current native failover backups totalled 24 GB across
about 300 sessions. For OpenCode sessions:
- `opencode/<session>/home-XXXXXX/`: 170 per-launch HOME directories
across 67 sessions, 9.3 GB. Each held `.npm` (about 111 MB of npm
cache), `.claude` (the skill snapshot) and `.local`.
- `opencode/<session>/config/opencode/node_modules`: 68 sessions, 4.3 GB
of OpenCode plugin installs.

One ACPX session also carried `acpx/<session>/data/pnpm/store` (229 MB
in the current backup, several GB in older copies).

Cause of the leaked homes: `startRuntime` in the OpenCode driver creates
a fresh `mkdtemp` HOME for each launch and seals the assigned skills
inside it (directories `0555`, files `0444`). `close()` and the
startup-failure paths removed it with `rm(..., { recursive: true, force:
true }).catch(() => undefined)`. That fails with `EACCES` on the sealed
directories, and the failure was ignored, so each launch left its HOME
behind.

**Expected behavior**
Per-launch homes are removed when the runtime closes, and backups hold
only state needed to resume a session. Caches that the provider
re-creates are left out.

**Steps to reproduce**
1. Run an OpenCode native session with at least one assigned skill on a
managed sandbox, over several turns or runs.
2. Inspect `<session>/` in the OpenCode runtime directory: one
`home-XXXXXX` per launch remains.
3. Inspect `failover-backups/current/opencode/<session>/`: the same
homes and `config/opencode/node_modules` are in the backup.

**Paperclip version or commit:** `master` at e335265568.
**Deployment mode:** any with native OpenCode/ACPX sessions on managed
sandboxes.
**Agent adapter(s) involved:** OpenCode (native), ACPX.

## What Changed

- OpenCode driver
(`packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts`):
- `removeIsolatedHome` unseals the skill snapshot with the existing
`releaseMaterializedNativeRuntimeSkills`, then removes the HOME. Close
and every startup-failure path use it. It only unseals when `.claude` is
a real directory, not a symlink.
- Per-launch homes are now created under `<session>/homes/home-XXXXXX`,
so one exact path can be excluded.
- When a session opens, `home-*` directories left at the session root by
earlier versions are removed. History is not in them: OpenCode keeps it
in `XDG_DATA_HOME` (`<session>/data/opencode/opencode.db`), and HOME
only holds caches, state locks and the skill copy.
- Exports `opencodeRuntimeSessionDirectoryName` (the existing
session-directory naming) and `OPENCODE_ISOLATED_HOMES_DIRECTORY` for
the server.
- `resolveNativeHarnessPersistenceProfile`
(`server/src/services/native-runtime/native-session-executor.ts`):
- OpenCode excludes `<session>/homes` and
`<session>/config/opencode/node_modules`.
- ACPX (every agent) excludes `acpx/<session>/home/.npm` and
`acpx/<session>/data/pnpm/store`, in addition to the existing per-agent
entries.
- `excludeEntries` are matched as exact relative paths (wildcards are
rejected), so the session directory is computed in the same way as the
existing ACPX entries.
- Exposes the two new exports through the server's runner vendor shim.

No code comments were added.

## Verification

- `pnpm exec vitest run src/drivers/opencode
src/drivers/runtime-context-materializer` (in
`packages/paperclip-runner/`): 108 passed. The 1 failure, `uses provider
structure rather than prose length to select a post-tool answer`, also
fails on unmodified `master`.
- The existing skill-tree test, with and without a startup retry, now
asserts that homes are created under `homes/` and that `homes/` is empty
after close.
- New test: a sealed legacy `home-*` at the session root is removed when
the session reopens, and `data/opencode/opencode.db` is kept.
- `pnpm exec vitest run src/services/native-runtime/
src/__tests__/native-harness-backup-expiration.test.ts` (in `server/`):
5080 passed. `plugin-runner-probe` could not run locally because of a
cargo manifest-path problem in this environment; it is unrelated to this
change.
- Profile tests cover the new OpenCode and ACPX exclusions, including a
session id that needs sanitizing.
- New checkpoint/restore round-trip tests for OpenCode and ACPX. They
use `syncRemoteRunnerDirectoryOut` for the backup and
`stageRemoteRunnerDirectory` for the replacement. Excluded caches are
absent from both the backup and the replacement, while history, config
and workspace files are restored and the live directory is unchanged.
- **Mutation checks**, each failing its test:
- removing the skill unsealing (homes leak again; 3 runner tests fail);
  - removing the legacy sweep (1 test fails);
  - emptying the OpenCode/ACPX exclusion lists (4 server tests fail).
- Checked by hand against the bundled OpenCode 1.18.34 binary, with the
driver's environment:
- launching with a fresh HOME and no `config/opencode/node_modules`
still lists earlier sessions;
  - OpenCode reinstalls the plugin dependencies on launch.
- `pnpm run typecheck` in `server/` and `packages/paperclip-runner/`:
pass.
- Not run: server build and boot smoke.

## Risks

- **Rollout:** existing backups still contain legacy `home-*`
directories. After a restore, the sweep removes them when the session
opens, and the next backup no longer carries them.
- **First launch after restore:** OpenCode reinstalls its plugin
dependencies and npm repopulates its cache. This needs network access to
the npm registry, the same as a brand-new session.
- **Crash leftovers:** a HOME left behind by a hard crash (the runner
killed before `close()`) stays under `homes/` until the session
directory is removed. It is still excluded from backups. Homes under
`homes/` are not swept on open, to avoid touching a HOME that a
concurrently running runtime might still use.
- **pnpm store:** dropping the pnpm store from ACPX backups means the
next `pnpm install` in a replacement sandbox downloads packages again.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), 1M context, through Claude Code
with tool use (shell, file edits, tests, and running the real OpenCode
binary to check what state it reads on resume).

## 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
- [ ] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-25 08:51:39 -07:00
DottaandPaperclip aec86c794b fix(runner): preserve native work through controller outages (#17594)
Keep remote native work under its authenticated connection lease through controller outages. Hold durable ACPX tools through reconnection, align the native Claude HTTP MCP client budget, and wait for the recovered handler before dispatch. Preserve Stop, cancellation, exact identity and artifact checks.

Verified with real-process regressions and a real Claude Opus 5.5 Daytona workflow: 125 seconds offline during useful work, original process and lease retained, no failed native tool calls, queued follow-up completed, independently verified ZIP and committed workspace receipts. All current-head CI gates pass and Greptile is 5/5 with all findings resolved.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 09:01:24 -05:00
DottaandPaperclip 044628f59e Add explicit native tracing to the Runner eval CLI (#17483)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Runner Evals exercise real providers against a mock control plane.
> - The controlled gateway route creates a disposable provider home.
> - That route had no explicit native trace configuration.
> - Codex skips normal home preparation for a preconfigured home.
> - This change validates and applies the existing observability launch
contract before provider creation.
> - Operators can collect native evidence without passing vendor keys to
the child.

## Linked Issues or Issue Description

Refs #17440. Related: #17452 and #17469. This PR is based directly on
master and does not include those pending controller changes.

**Current behavior**

The eval-session CLI cannot pass an explicit native observability
launch. Passing environment alone cannot configure Codex in the
disposable gateway home.

**Proposed behavior**

Accept an opt-in descriptor bound to the gateway attempt. Validate the
existing provider launch contract, add a scoped relay token in memory,
and apply it only to the owned provider home and environment.

**Reason and benefit**

A controller can route native evidence through its bounded local relay
while the CLI keeps configuration distinct from verified ingestion. This
is the CLI contract; hosted controller integration remains separate
work.

## What Changed

- Add a strict, bounded descriptor reader for native Codex and ACPX
Claude. Bind campaign, execution, attempt, project, trace, span, and
mock authority identifiers.
- Reuse Runner observability materialization and redaction. Preserve the
model gateway route. Reject upstream destinations, extra environment
fields, credentials in headers, and unknown exporter settings.
- Add `--observability-config`, requiring an explicit gateway. Keep
direct and unconfigured paths unchanged.
- Retain secret-free configured/unverified metadata in success and
failure artifacts.
- Document the contract and controller responsibilities. No workflow,
runtime dependency, paid schedule, or public report changes.

## Verification

- Eval CLI regression selection: 81 passed before the test-only
relocation. The 17 new cross-package observability tests now pass from
`tests/runner-e2e/runner-eval-observability.test.ts`; their
integration-suite typecheck also passes. They use the actual shared
launch generator, real disposable homes, CLI success/failure paths, and
credential redaction. The first run exposed two test setup references
introduced by a broad edit; both were corrected and its failure log
remains retained.
- Runner TypeScript build and release daemon build passed. Full `pnpm -r
typecheck` passed.
- Actual native Codex and ACPX Claude reached a local receiver with
authenticated OTLP protobuf and the expected Braintrust parent. Codex
sent four log and two trace batches; Claude sent three log and one trace
batch. All recorded processes exited, disposable homes were removed, and
29 retained files contained neither synthetic credential.
- The local model endpoint deliberately returned 401. Codex retained a
failed terminal turn; Claude retained a provider timeout. These are
route/export proofs, not semantic eval passes. Native retries reached
only the fake endpoint. No paid provider or Braintrust request was made.
- The first local probe failed before provider launch because its
TypeScript loader path was wrong. It was corrected to the installed
loader; both attempts remain retained.
- Full repository build passed at initial head 7b75c0349f. The full
local test suite encountered repeated embedded PostgreSQL startup
failures before database-backed test bodies. It was stopped after five
affected suites (exit 143), so it is incomplete. Its log remains
retained. The same host had independently demonstrated PostgreSQL
semaphore exhaustion earlier in this task; this run did not collect that
lower-level error. Full hosted workflow 40131255078 passed on final head
23a172af32, including the database-backed
suites, Runner, build, typecheck and browser checks. Greptile is 5/5
with zero open threads. The secondary Paperclip reviewer ended neutral
without an assessment; it is not counted as a successful review. A
follow-up header-validation repair uses a map without a prototype and
passes the added negative regression. No exporter behavior changed.
- The CLI still reports native ingestion as unverified. No complete
capture, destination indexing, vendor billing bound, hosted admission,
or paid recurrence qualification is claimed.

- Package-boundary validation found two new imports from the standalone
Runner tests into other repository packages. Those tests now live in the
repository integration suite and use the actual launch generator there.
Its first run failed on a TOML parser resolved from the wrong package;
resolving that dependency from its Runner owner fixed the test. Three
pre-existing boundary/tracked-import findings remain in unchanged files;
this PR adds none.

## Risks

- This descriptor is intentionally narrow. Changes to the shared launch
contract must be reviewed against its validator and integration tests.
- The local relay receives native content under the selected capture
policy. Its controller must enforce ingestion quotas, shutdown, private
retention, and qualified cost bounds.
- Descriptor validation runs once before launch. It reads at most 128
KiB and refuses symlinks and non-regular files. Existing owned-home
config writing remains synchronous and small.
- Relay credentials are held in child memory. Persisted diagnostics and
artifacts use the existing redactor. The descriptor itself must remain
secret-free.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. This runtime does not expose the exact model ID or
context-window size.

## 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-10-24 14:07:28 -07:00
DottaandPaperclip d1fdfced9d feat(evals): route Runner sessions through a controller gateway (#17440)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Runner Evals test provider behavior against a mock control plane.
> - A campaign budget needs to observe and admit each provider request.
> - The existing eval CLI does not select the provider-home mode needed
for a controller-assigned route.
> - A proxy URL alone therefore cannot establish controlled Codex
routing.
> - This change adds an explicit route with an isolated home and
retained identity.
> - The controller can use that route as the basis for request
accounting and admission.

## Linked Issues or Issue Description

**What happened?**

The direct Runner eval CLI passes the ambient environment to the native
transport. The transport deliberately removes an environment-only
preconfigured-home marker unless its explicit option is also set. This
prevents a controller from assigning a Codex gateway through that marker
alone.

**Expected behavior**

A controller can explicitly route a supported eval attempt through its
local proxy. The provider receives the proxy token and isolated
configuration. The artifact identifies the assigned route on success and
failure. Ordinary direct runs keep their current path.

**Steps to reproduce**

Run the new CLI tests for `--gateway-config`. They validate the
descriptor, inspect the actual transport inputs and provider sanitizers,
and check retained artifacts and owned-home cleanup. The local probe
also ran built native Codex and ACPX Claude against a fake loopback API
using only synthetic credentials.

Related request-accounting work:
https://github.com/paperclipai/paperclip/pull/17432.

## What Changed

- Add an explicit gateway descriptor bound to the requested provider,
exact model, campaign, execution, and attempt.
- Accept only the controller's IPv4 loopback URL and a separate proxy
token.
- Create a fresh provider home for native Codex and ACPX Claude. Exclude
ambient provider credentials, subscription logins, proxies, and startup
hooks.
- Retain route identity and descriptor hash in successful and failed
artifacts. Remove the owned home in finalization.
- Document the CLI contract and its limits.

The Runner eval CLI owns this behavior. It uses the existing native
preconfigured-home contract. Production routing, permissions, and
provider protocols are unchanged.

## Verification

- Initial verification passed 56 focused gateway/CLI tests and 246 CLI
and adjacent provider-isolation tests. After the admission repair, all
247 CLI and adjacent provider-isolation tests passed, with TypeScript
checks and build passing again.
- Runner TypeScript checks and build passed.
- The native daemon rebuilt from the candidate base with locked, offline
dependencies.
- Local fake-API probe: six authenticated Responses requests from native
Codex and six authenticated Messages requests from ACPX Claude reached
the assigned endpoint. Claude also made an unauthenticated hello check.
The final commit retained both route artifacts. All 27 retained files
were scanned for the synthetic proxy token and contained none. Both
temporary homes were removed, and all four recorded provider/daemon PIDs
were absent after exit.
- The fake API intentionally rejected inference. Codex retained a failed
turn; Claude retained a timeout. These are route observations, not
passing semantic evals or live provider qualification. No paid provider
calls ran.
- The first focused command used the wrong directory and discovered no
tests. It was corrected before the successful runs above.
- Full Runner validation: 3,967 tests passed, 13 skipped, and five
failed in three unchanged installation and native-settlement files. The
failures were two installation timeouts and three retained-cleanup
settlement failures. One isolated run passed all 109 applicable tests
with six skips. This shows recovery, not a proven cause for the original
five failures; those remain retained. Hosted [CI
40111220754](https://github.com/paperclipai/paperclip/actions/runs/40111220754)
passed on final commit `a5c47b64e56c1228fca718b72a81ddc3b1d185a4`,
including repository typecheck, build, tests and Runner checks. All 57
checks passed or were neutral/skipped, and the legacy status passed.
Greptile and Paperclip reviews both scored 5/5 on that commit; no
findings remain unresolved.
- Rebased onto current master
`71c04c0bfb205cc9e7f7bc20c29fd76051b44cc4`. Its added change concerns
server cleanup; Runner source is unchanged.

- An actual ACPX Codex probe failed before reaching the fake API. Review
and source inspection confirmed that Runner deliberately rejects its
preconfigured home to protect Runner state. This route is now rejected
before service creation. Both explicit and default ACPX Codex admission
regressions failed before the repair. The unsupported lane is not
presented as qualified.

## Risks

This is an explicit new CLI route. Unsupported providers fail before
service creation. Upstream route is a controller declaration, not
independent billing evidence. The local probe saw six Codex requests
where legacy usage counted one, so the controller's request ledger must
remain the budget source. Campaign allocation, proxy lifecycle, hosted
workflow wiring, dedicated OTLP relay routing, and paid qualification
are separate remaining integration steps. This PR enables none of those
schedules.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact serving model ID and context-window size are not
exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used, including the information
available in this session
- [x] I checked ROADMAP.md; this is eval infrastructure, not a competing
core feature
- [x] I searched for duplicate PRs for this exact route change
- [x] I described the issue in-PR using the bug template labels
- [x] I have not referenced internal or instance-local issues
- [x] My branch describes the change and contains no internal issue ID
- [x] Relevant focused tests pass
- [x] I added tests for the new contract and lifecycle
- [x] I updated the relevant documentation
- [x] I described the risks and unqualified behavior
- [x] All current-head Paperclip CI gates are green
- [x] Current-head Greptile is 5/5 with no unresolved findings
- [x] I will address review findings before merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-24 09:34:10 -07:00
Nicky Leach aa0037a137 Support Codex warm plugin task reuse and recovery (#17390) 2026-10-23 19:14:14 -07:00
cc127f5516 fix(runner): drop unusable musl builds and duplicate Copilot from provider packs (#17387)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runner release builds a Linux "provider pack". The pack is a
self-contained runtime with Node, Claude Code, Codex, and OpenCode. The
Daytona runner image and SSH hosts use it.
> - The release artifacts for this pack are large: 1,182 MB for
linux-x64 and 543 MB for linux-arm64.
> - Most of that size is necessary. But about 20–30% of it is code that
the pack can never run.
> - pnpm 9 installs all libc variants of optional platform packages.
Thus the pack includes the musl (Alpine) builds of Claude Code and
OpenCode. The pack runs only its copied glibc Node, so these builds are
never used.
> - On linux-x64, the npm Copilot package is also a byte-identical copy
of the verified Copilot provider asset (162 MB).
> - This pull request removes these unused bytes from the pack at build
time.
> - The benefit is smaller release artifacts and Docker images, and
faster uploads and downloads.

## Linked Issues or Issue Description

**What happened?**
The runner release workflow uploads `runner-provider-packs-linux-x64`
(1,182 MB) and `runner-provider-packs-linux-arm64` (543 MB). The darwin
daemon artifacts are about 10 MB. The darwin artifacts are a different
artifact type, so the comparison is not direct. But inspection of the
extracted Linux packs found real waste:
- `@anthropic-ai/claude-agent-sdk-linux-*-musl` (about 225 MB
uncompressed)
- `opencode-linux-*-musl` and `opencode-linux-x64-baseline-musl` (about
180 MB each)
- on linux-x64,
`node_modules/.pnpm/@github+copilot-linux-x64@1.0.88/.../copilot`, which
has the same SHA-256 (`0059754c…`) as
`provider-assets/copilot/linux-x64/copilot`

**Expected behavior**
The pack contains only code that its copied Node and its launch shims
can run.

**Paperclip version or commit**
`master` at `e0d9033`. The inspected release run built commit `837add0`.

**Steps to reproduce**
1. Install `@agentclientprotocol/claude-agent-acp@0.73.0` and
`opencode-ai@1.18.34` with pnpm 9.15.4 on a glibc Linux host.
2. List `node_modules/.pnpm`.
3. See the `*-musl` entries. Their `package.json` declares `"libc":
["musl"]`.

## What Changed

- `provider-pack-runtime-tree.mjs`: add `providerPackLibc()`. It reports
the libc of the Node that the pack copies (`glibc` or `musl` on Linux,
none on other platforms).
- `provider-pack-runtime-tree.mjs`: add
`removeForeignLibcPackagesFromProviderPack()`. It removes each pnpm
virtual-store entry whose own `package.json` declares a `libc` list
without the pack libc. Packages without a `libc` field stay (for example
`@openai/codex-linux-*`, which holds Codex's static musl binary).
- `provider-pack-runtime-tree.mjs`: add `removePnpmStoreEntries()`. It
removes store entries and every symlink that resolves into them, so no
dangling link stays in the pack. It refuses names outside
`node_modules/.pnpm`.
- `provider-pack-executable-shims.mjs`: when
`provider-assets/copilot/<platform>/copilot` has the same bytes as the
npm Copilot executable, the `copilot-<platform>` command now points at
the asset and the npm copy is removed. If the bytes are different, the
old behavior stays.
- `build-provider-pack.mjs`: run the libc prune immediately after `pnpm
deploy`. Log the removed entries.
- No file bound by `provider-pack.json` changes. Thus the manifest
digest and the qualification and digest pins do not change.

## Verification

- `node --test
packages/paperclip-runner/scripts/provider-pack-runtime-tree.test.mjs
packages/paperclip-runner/scripts/provider-pack-executable-shims.test.mjs
packages/paperclip-runner/scripts/candidate-provider-pack.test.mjs
packages/paperclip-runner/scripts/release-provider-pack.test.mjs`: 40/40
pass.
- The new Copilot test fails with the old
`provider-pack-executable-shims.mjs` and passes with the new file.
- A real pnpm 9.15.4 tree with the pack's provider dependencies, on
linux-x64 (glibc):
- The prune removed `@anthropic-ai+claude-agent-sdk-linux-x64-musl`,
`opencode-linux-x64-musl`, and `opencode-linux-x64-baseline-musl`. The
Copilot dedupe removed the npm Copilot entry.
  - `node_modules` changed from 1.9 GB to 1.1 GB.
  - `find node_modules -xtype l` found no dangling links.
- The claude-agent-acp SDK still resolves
`@anthropic-ai/claude-agent-sdk-linux-x64/claude`.
  - `opencode --version` prints `1.18.34`.
- The rewritten `copilot-linux-x64` prints `GitHub Copilot CLI 1.0.88.`
- Earlier measurement: we pruned the same paths from the extracted pack
artifacts and compressed them again with `tar -czf`. linux-x64 went from
1131 MB to 876 MB. linux-arm64 went from 519 MB to 360 MB.
- Not run locally: a full `build-provider-pack.mjs` build. This sandbox
has 10 GB of disk, which is not sufficient for a full workspace install
and a 3 GB pack. The `release-verify.yml` provider-pack step and the
Daytona image `RUN claude/codex/acpx --version` checks run the full
build.
- `test/acpx-codex-package-contract.test.mjs` has 1 failure in this
sandbox, and the failure is the same on `master`. The cause is that this
checkout has no `node_modules`.

## Risks

- Low risk. All pack builds run on glibc hosts (Debian bookworm images
and Ubuntu CI). On a musl build host, the prune removes the glibc
packages, and the existing Claude executable resolution fails at build
time. Before this change, that build gave a pack with a Claude binary
that could not run.
- The `copilot-linux-x64` command now runs the binary from
`provider-assets/copilot/linux-x64/`. The bytes are identical. Runtime
admission already uses this asset, through the descriptor-pinned lease.
- The pack content changes but the manifest digest does not. The remote
verifier checks only the bound artifacts, `dist`, and provider asset
trees. None of these change.
- Not in this pull request: Pi's bundled Node is byte-identical to the
pack Node (121 MB, about 43 MB compressed). A fix for it changes the
qualified Pi closure digest. Also, the `release.yml` publish jobs
download the full packs, but they read only `provider-pack.json`. These
are possible follow-ups.

## Model Used

- Claude Opus 5.5 (Anthropic), model ID `claude-opus-5-5`, used through
Claude Code with tool use (shell, file edit) and code execution in a
sandbox.

## 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 (no
doc change is necessary: build behavior and commands do not change)
- [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
- [ ] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 16:41:14 -07:00
Nicky Leach 2e38649341 perf(run-logs): skip durable log restore for a proven-new run (#17367) 2026-10-23 14:30:06 -07:00
DottaandPaperclip 3bd709df8b Operationalize Product E2E accounting, tracing, and scheduling (#17009)
## Thinking Path

> - Paperclip manages agents and the work they perform.
> - Product E2E tests exercise real agents, tools, setup and cleanup.
> - Repeated runs need retained costs and traces, including failed
attempts.
> - A passing retry must not hide earlier spending or feedback.
> - Recurring work also needs admission limits, private reports and
failure detection.
> - This change supplies those controls while keeping paid activation
behind existing gates.

## Linked Issues or Issue Description

Refs #16996 and #17158. This is the consolidated landing of the reviewed
eval operations stack: #17019, #17024, #17025, #17027, #17030, #17033,
#17035, #17038, #17043, #17044, #17048, #17050, #17051, #17092, #17096,
#17100, #17107, #17109, #17112, #17115, #17117, #17121, #17123, #17127,
#17130, #17133, #17134, #17137, #17140, #17143, #17154. The repository
permits squash merges only. A local rehearsal showed that squashing each
slice into master causes repeated conflicts in dependent slices. This PR
preserves their commits and lands their combined implementation in one
reviewed integration. Superseded slices will close after this merge.

## What Changed

- Retain every attempt's cost receipt, including setup, failures,
interruptions and retries. Separate reported amounts, estimates, missing
costs and reserved capacity in reports and dashboards.
- Add bounded request admission, exact model pricecards, gateway error
accounting, cache policy and reconciliation evidence. Refuse unsupported
routes and requests that cannot fit the allowance.
- Integrate Braintrust gateway traces and OTLP correlation, with secret
filtering and experiment imports. Record phase timing, including setup,
feedback capture and cleanup.
- Collect complaint and suggestion evidence after each attempt,
including recovery after failures. Retain explicit review dispositions
independently from the product grade.
- Add gated daily and weekly selections, measured forecasts,
setup/readiness checks, wall-time limits and retained monitor
notifications. Include declared non-model overhead in admission while
reporting the existing subscription separately.
- Keep recurring history private, bound uploads and retention, and use
isolated archive environments. Keep public publication an explicit
operation. Report and publication jobs install only the committed
lockfile, with scripts disabled and isolated stores; stale pins fail
closed.
- Integrate current master, preserve its Product E2E journey billing and
privacy checks, and test that shared setup receipts do not double-count
estimated agent usage. Preserve upstream fixture repairs.

## Verification

- Complete integration baseline
`0649a5ce7544ab20825c2183d2f421157db49f24` includes master
`a3e1d915a7110a4e115b46396a3f79e6dfb4d05e` and every original stack head
as ancestors.
- On that integration baseline, `pnpm test:e2e:runner:unit`: 4,012
Vitest tests passed, two skipped, across 193 files; all 137 Node
source-contract tests passed.
- Focused billing and Product E2E journey contract checks: 24 tests
passed. They cover estimates, unknown receipts, single-owner setup
costs, browser-only execution and private publication guards.
- Monitor and workflow wiring: all 96 Node tests passed. `node
scripts/check-token-gates.mjs`: all gates clean.
- `pnpm test:e2e:runner:typecheck` passes after the standard Runner
TypeScript build refreshed local declarations. The first attempt
rejected the new master `runner_prepared_launch` union member because
this checkout retained an older generated declaration; the source union
already contained that member.
- Current head `492b0708a1c531a023d9ac10f0f3dc6383cc1754` removes
dependency re-resolution from archive-authorized reporting jobs after
the security scan flagged it. All 15 workflow-security tests pass after
updating the old two-install assertion.
- Hosted [CI run
39965460180](https://github.com/paperclipai/paperclip/actions/runs/39965460180)
passes on the current repaired head, including typecheck, build, general
tests, Runner checks, browser shards and canary dry run. Greptile is 5/5
on this exact head with no unresolved threads. The security scan passes
after the fixed lockfile-resolution thread was resolved.
- Paperclip Review returned a terminal neutral check but an incomplete
0-file assessment on the repaired head: its platform blocked both diff
responses as prompt-injection content. This is not a successful code
review. No bypass or fabricated pass was attempted; current-head
Greptile, security and hosted CI are independent gates.
- No paid test, reservation release or recurring-run activation
accompanies this landing. Live route qualification and invoice
reconciliation remain separate evidence.

<details>
<summary>Retained earlier validation failures</summary>

Earlier broad local runs had two 15-second test timeouts (CLI poll
cadence and Retry validation), one embedded-database setup timeout, and
later PostgreSQL semaphore exhaustion. The exact timed-out tests passed
separately without larger timeouts; the broad-run causes were not
established. Those local failures remain distinct from subsequent hosted
CI results. The independent #17158 fix records its Muse fixture
collision, its UUID correction and hosted verification. Local Muse
execution was also blocked by macOS embedded-PostgreSQL startup. No
historical failure is treated as a successful paid qualification.

</details>

## Risks

- Admission is a local control, not a provider invoice cap. Missing
provider receipts or resource charges retain unknown amounts and holds;
estimates do not become billed dollars.
- The bounded path admits only documented local suites and provider
routes. Ordinary legacy or separate Runner protocol campaigns have
different controls. Merging this code does not qualify additional
routes.
- Recurrence still needs the existing enable gates and current
qualification/allowance evidence. Archive permissions and resources must
match the documented private-environment contract.
- Legacy reports may lack complete attempt or phase evidence. Reports
preserve that limitation and do not infer zero usage from missing data.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools and code
execution. The exact deployment variant and context-window size are not
exposed by this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (targeted checks;
full-suite host limitation disclosed above)
- [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-10-23 07:18:37 -07:00
DottaandPaperclip a3e1d915a7 fix(evals): preserve unknown Codex provider cost (#17158)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Direct Runner evals report usage and costs for each attempt.
> - Codex App Server supplies token counts without a provider USD
receipt.
> - The legacy Runner ledger fills an absent cost with zero.
> - The eval result exposed that ledger value as provider-reported cost.
> - This fix keeps provider cost unknown and preserves the estimate and
budget stop.

## Linked Issues or Issue Description

Refs #17009 and #17154. This is a separate direct Runner accounting fix
based on master.

## What Changed

- Codex direct eval usage now reports null provider USD cost with
unavailable provenance. Token counts and the pinned price estimate
remain available.
- Preserve the original ledger amount as optional
`legacyLedgerCostNanodollars`. Keep the original snapshot receipts
unchanged.
- Apply the existing budget ceiling to the retained ledger amount as
well as the token estimate. Correcting a label does not relax admission
or settlement checks.
- Use the unique operator UUID for Muse test company prefixes,
eliminating collisions from the previous 24-bit random suffix.
- Document the cost distinction in the Runner/Evals integration
contract. Other provider behavior and historical artifacts remain
unchanged.

## Verification

- Reproduced both zero and nonzero legacy amounts being labelled as
provider USD cost before the fix.
- The current eval-session contract and entrypoint tests pass (39
tests). The new regression uses the bounded usage consumer and actual
campaign cost projection. It checks unknown provider cost, the separate
estimate, unchanged raw evidence and the legacy ledger budget stop.
- All 15 Runner report, campaign and metrics Node tests pass. Four
adjacent CLI entrypoint/runtime tests also pass.
- Runner TypeScript validation passes with its standard dependency-build
prerequisite; `git diff --check` passes. Both Runner TypeScript
configurations also passed during the original accounting verification.
- Hosted CI run
[39960367674](https://github.com/paperclipai/paperclip/actions/runs/39960367674)
passes on `7d84f138044bac58cdced6baa2d0ec3d63767bb8`, including
typecheck, build, server tests and browser checks. Greptile and
Paperclip Review both report 5/5 on that commit with no actionable
findings.
- The previous CI failure was a PostgreSQL unique-index collision on
`companies_issue_prefix_idx` during Muse fixture setup. Local Muse
verification could not reach test execution because embedded PostgreSQL
timed out during macOS startup (initially reporting a missing zstd
library). The corrected fixture passed in hosted Linux CI.
- Verification used no model calls. Full repository checks were
performed by hosted CI; local verification was scoped to the changed
contracts and fixture.

## Risks

Consumers that assumed Codex always had a numeric provider cost must
handle null. The contract already permits null for other profiles, and
the report consumer retains missing-cost coverage. The legacy amount
remains available as unverified evidence and still triggers the existing
budget stop. Neither the estimate nor that ledger amount proves an
invoice charge. This change does not rewrite old artifacts or qualify
other provider routes.

## Model Used

OpenAI GPT-6 through Codex, with repository tools and code execution.
The exact deployment variant and context-window size are not exposed by
this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-23 06:36:34 -07:00
Nicky Leach f5b6721ae0 Use the admitted session directory in native task prompts (#17310) 2026-10-23 05:48:09 -07:00
Nicky Leach 412914cfa7 Read native plugin task output files on the execution host (#17285) 2026-10-22 23:38:09 -07:00
Nicky Leach 2cd6eb27c7 fix(runner): record the plugin-prepared working directory (#17243) 2026-10-22 20:42:26 -07:00
Nicky LeachandPaperclip 0081863463 Fix isolated ACPX admission for assigned PRP tools (#17149)
## Thinking Path

- Paperclip uses Runner to execute agent tasks under Core's selected
policy.
- The ACPX sidecar can receive assigned MCP tools in its PRP catalog.
- Isolated admission still requires a separate native MCP endpoint for
those assignments.
- This check rejects a valid PRP route before the provider can start.
- This PR identifies the sidecar's PRP transport at the runtime-host
boundary.
- The benefit is that assigned tools work with the existing isolated
permission policy.

## Linked Issues or Issue Description

**What happened?**

An isolated Claude task with an assigned MCP binding fails with
`assigned native MCP launch binding is unavailable` when Core delivers
its tools through PRP.

**Expected behavior**

The sidecar must accept its authenticated PRP tool bridge as the
assigned-tool route. Callers that use the native gateway must still
supply its complete binding.

**Steps to reproduce**

1. Open an isolated Claude sidecar session with `deny-all` permissions
and a read-only policy.
2. Supply an assigned MCP binding in the runtime context and its tools
in the PRP catalog.
3. Omit native gateway environment variables. Admission fails before
provider startup.

**Paperclip version or commit**

Reproduced against `92cfd701c39bb1ea394a796023481a21decb2532`.

**Deployment mode**

Runner with an ACPX sidecar and controller-owned tool delivery. Related
contract work: #16978. The search found no existing PR or issue for this
failure.

## What Changed

- Let runtime-host callers select PRP delivery when they supply the
semantic tool bridge.
- Select that route in the sidecar. Keep native gateway validation and
direct callers' default behavior.
- Preserve exact controller operation names in PRP mode, including the
compact assigned-MCP catalog. Keep existing aliases for other bridge
callers.
- Preserve the selected permission and read-only policies.
- Add one process-level sidecar regression and one host admission
regression. The host test calls the real authenticated MCP bridge.
- Document the route and refresh the generated Copilot source hashes.
The provider and profile versions stay the same.

## Verification

- Passed 11 focused tests after the rebase across the runtime host,
sidecar, tool bridge, and Copilot identity tests. They cover both
compact catalog operations, restricted and approve-all policies, legacy
aliases, missing and invalid gateway bindings, and the existing direct
gateway path.
- The process-level test crosses the real sidecar dispatcher and stops
at workspace validation before provider startup. The host test uses real
ownership sockets and MCP HTTP, with a fake provider port.
- The generated identity tests match the current source hashes. The
historical fixture stays unchanged.
- The standard review passed on the rebased commit. [Apex passed the
required 5/5
threshold](https://github.com/paperclipai/paperclip/runs/119513362214)
on `e63a223`, with 11 files reviewed and no findings.
- Rebased onto master `734c265`. The conflicts affected generated source
identities and their test expectations. All reviewed behavior files
remain byte-for-byte unchanged. The user authorized retaining the Apex
result for this rebase. [CI passed on
`3facef5`](https://github.com/paperclipai/paperclip/actions/runs/39685163239).
The final PR checks contain 56 passes and four expected skips. The
branch is current with master, has no conflicts, and has no unresolved
review comments.
- `node packages/paperclip-runner/scripts/copilot-profile-identity.mjs
--check` passed.
- Initial local runs exposed missing test dependencies and sandbox
denial of loopback sockets. After the scoped dependency install and
socket permission, the selected tests passed.
- Broad typecheck, build, and test verification runs in GitHub CI, as
requested. No live provider or model request was made.

## Risks

- PRP callers must supply the assigned tools in the controller-owned
catalog. The existing bridge still enforces its closed catalog and
authentication.
- An explicit PRP selection without a semantic bridge still fails.
Invalid native gateway bindings still fail.
- No database, protocol-frame, provider-version, or credential-storage
change is required.

## Model Used

OpenAI GPT-6 through Codex, with source inspection, editing, and command
execution. The exact served model ID and context-window size are not
exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-21 16:00:14 -07:00
DottaandPaperclip 734c265339 Default new Pi agents to Paperclip Runner (#17142)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Users choose a harness during agent setup.
> - Claude, Codex, and OpenCode already receive their qualified Runner
default.
> - Pi has a qualified native integration but new Pi agents still use
the direct adapter.
> - This change gives new Pi agents the native default on supported
targets.
> - Saved agents keep their runner and compatible settings. Legacy
remains available in Advanced.

## Linked Issues or Issue Description

Refs #17120, #14921, #14922, #14923, #14924, and #14956. Related generic
default work: #15422. This PR is the separate Pi follow-up to the merged
OpenCode change.

**Current behavior**

Choosing Pi for a new agent saves the direct Pi adapter. The native Pi
integration remains behind the generic experimental flag.

**Proposed behavior**

Default new Pi agents to ACPX Pi on macOS ARM64/x64 and GNU/Linux x64
with supported glibc. Keep unsupported targets and explicit Legacy
selections on the direct adapter. Require an explicit provider/model
before test or hire. Permit model-free inactive setup drafts.

**Reason and benefit**

Users choose Pi once and receive its qualified runner. Saved agents
retain their identity and settings. Conversions reject unsupported
legacy thinking and launch settings instead of dropping them.

## What Changed

- Add Pi to the shared platform/default contract and server creation
selection.
- Admit native Pi without the generic experimental flag.
- Preserve provider models, credentials, workspace settings, exact
thinking, and saved native policies.
- Add Pi runner controls, branding, setup resume, onboarding, built-in
configuration, and import handling.
- Add managed Pi OpenRouter routing and matching native provider API-key
accounts. Keep subscription and custom gateway exclusions. Clear
alternate credentials and reject custom Pi provider overrides.
- Keep Pi draft models empty instead of applying Claude's default model.
- Verify setup against the pinned Pi runtime. For native Pi on the
official OpenRouter route, reverify the API key live without requiring a
global Legacy Pi CLI.
- Match Pi’s bounded controller close window to its native snapshot
cleanup and lifetime verification, preserving explicit caller deadlines
and the mandatory drain/suspension proof.
- Bind Pi sidecars to the package that owns the pinned native assets,
including source and vendored server layouts. Other providers retain
their existing package authority.
- Keep protocol-owned finish/block tools out of the ACPX forwarded
catalog. The trusted bridge installs these tools itself; the complete
Rust authorization catalog and terminal receipt ledger remain intact.
This fixes actual Pi session startup and applies to other ACPX
consumers.
- Advance Copilot’s shared-source attestation to v58 because it pins the
shared files touched by Pi. Preserve immutable v57 bytes and historical
decoding; Pi’s own release identity is unchanged.
- Add regression coverage and update the paired maps and developer
documentation.

## Verification

- Passed: full repository typecheck and full production build on final
head 656d304783, including the generated attestation repair.
- Passed: focused shared/server/UI suites covering default selection,
platform fallback, conversion preservation, inactive drafts, managed
account compatibility, credential isolation, OpenRouter routing/model
IDs, exact thinking controls, and saved-account selection. Relevant
batches include 375 server/conversion tests, 267 account/routing tests,
and 110 UI setup/account tests.
- Passed: 179 attestation, historical-profile, qualified-profile, and
native-execution contract tests after CI identified stale Copilot source
hashes. The identity generator check passes; the only delta after the
passing Pi browser run is this Copilot attestation/history repair.
- Passed: 145 managed-account tests, including actual service
preparation and API-key adoption/rejection for native Pi without the
Legacy CLI; 6 pinned-installation probe tests.
- Red then green: an actual task failed session.open because its
54-operation catalog included the bridge-owned terminal tools. The
regression with those tools failed before the filter; all 399 Rust
library tests pass after it. The full product retry exposed an
additional package-authority mismatch. Four authority tests failed
before that repair; 11 authority checks and 14 installation/asset checks
pass afterward. Direct real Pi session initialization with the corrected
package root and catalog succeeds. No model prompt was sent by that
diagnostic.
- Red then green: real Pi posted Hello from Pi but its controller closed
before native cleanup could finish. The cleanup-budget test failed with
the old default and passes with the bounded Pi window. All 46 selected
suspension, drain, and package-authority tests pass after building their
native fixture.
- Passed: token gates, paired map checks, Rust formatting, and git diff
--check.
- Passed real browser acceptance on macOS ARM64, generic native runner
flag disabled, source a433748a12 (Pi code unchanged afterward): the UI
selects Paperclip Runner by default, retains Pi and the selected
model/account, and verifies the pinned runtime plus live OpenRouter key.
A fresh UI-created task, assigned to the UI-created native Pi agent,
posted exactly `Hello from Pi` and reached Done without retry or
restart. The native run and workspace finalization succeeded; the
response and Done persisted after Reload.
- Evidence: 8 preserved browser attempts, including the final passing
18-step journey with all screenshots. Prior failures remain recorded.
The earlier failed checkpoint run recovered on server restart; that
recovery is separate from the fresh final task’s clean success.
- Preserved browser failures: missing account control/inherited Claude
draft model; incompatible managed-account/model-prefix handling; generic
npm probe for Pi; Legacy CLI hello check; duplicate terminal tools and
wrong provider-package authority at actual native session.open; a real
Hello from Pi comment followed by premature checkpoint cleanup timeout.
Each failure has retained screenshots/logs and a corresponding focused
repair. The fresh final task proves these repairs end to end.
- The exact Runner Vitest shard was also run locally after the
attestation fix: the stale-hash failure is gone; 1,833 tests passed, 10
skipped, and two Codex retained-control settlement scenarios failed with
`native_cleanup_maintenance_unproven` during terminal ACK/suspension
replay. Both scenarios passed in an isolated rerun (2/2), and the same
19-test file passed in the preceding Linux CI run. The precise
full-shard timing cause is not established. These Codex scenarios are
outside the changed Pi paths; the original local failures are retained;
no complete local Runner-shard pass is claimed. The corresponding Runner
shard now passes on the final head in hosted Linux CI. All 60 final-head
check runs are now terminal and clean (55 successful, 1 neutral, 4
skipped), and the legacy Snyk status is successful.
- Local full repository tests were attempted but not completed:
provisioning briefly confused a workspace symlink, then a later run was
stopped before browser-driven repairs. No full local-suite pass is
claimed. Final-head hosted CI is green and fresh Greptile review is 5/5
with all review threads resolved; earlier jobs canceled by runner
shutdown are not counted as a pass.

## Risks

- Pi cleanup has a finite 45-second default window, accounting for the
native 30-second snapshot cleanup and 5-second lifetime fence. Other
providers and explicit caller deadlines retain their prior behavior.
- Pi requires explicit operator setup with `paperclipai runtime setup
pi` on the execution host. This PR does not add automatic downloads.
- Linux ARM64, Windows, musl, and unqualified targets retain Legacy.
- Legacy thinking levels minimal, medium, and xhigh cannot be translated
exactly. Native max thinking, warm lifecycle, or restricted permissions
cannot be dropped during a return to Legacy.
- Copilot’s bound profile advances to v58 with exact current launch
admission; v57 remains decodable for recovery. No historical identity is
rewritten.
- Existing agents and immutable run descriptors are not migrated. Cloud
Pi availability is unchanged.

## Model Used

OpenAI GPT-6 through Codex with reasoning, code editing, command
execution, and browser use. The exact serving model ID and
context-window size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-21 17:10:00 -05:00
DottaandPaperclip 0a5f1546ee feat(cases): add reusable prompt workflows (#17114)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Cases keep facts, documents, and one primary task across agent
handoffs.
> - Each case currently needs its own procedure text.
> - Agents need to reuse procedures and move cases between them without
replacing the task.
> - This change adds company workflow definitions with a name and
Markdown prompt.
> - Existing handoff and document transactions preserve authority,
revisions, and recovery.
> - Cases remain behind `experimental.enableCases`.

## Linked Issues or Issue Description

Refs #16959. Related proposal: #3951 uses task graphs and a visual
editor. This change extends existing Cases with prompt definitions and
keeps its current handoff model.

**Problem or motivation**

Agents cannot share a reusable procedure across cases or inspect a
case's movement between procedures.

**Proposed solution**

Add name-and-prompt workflow definitions. Adopt a prompt into the
primary task's revisioned workflow document through a handoff. Keep
phases as free text.

**Alternatives considered**

Defer graphs, workflow versions, run entities, role schemas, authoring
screens, and Spec Kit integration.

**Roadmap alignment**

This extends the existing Cases experiment and same-task review flow. It
adds no work queue or new execution engine. The maintainer approved this
scope in the implementation plan.

## What Changed

- Add company-scoped definition storage, shared request schemas, REST
routes, and four optional Cases tools.
- Accept a workflow ID at kickoff. Agent handoffs can adopt, refresh,
preserve, or detach a workflow.
- Capture prompt text and the document base revision at acceptance.
Apply workflow, phase, and document revision together after outgoing
execution settles.
- Hold conflicting document edits for recovery. Preserve cancellation,
replay, and restart behavior.
- Show current workflow names and captured transition names/phases in
Work, history, and Audit.
- Update instructions, API/tool contracts, capability maps, and the
isolated workflow journey.
- Pin bounded workflow prompt reads to a content fingerprint;
continuation conflicts on edits and can restart safely.
- Remove experimental Cases/workflow/Mermaid guidance from the always-on
native prompt. Extract runtime-context prompt strings into a
CODEOWNERS-protected constants file while preserving the public imports.
- Refresh Copilot’s pinned source identity to v57, including the
extracted prompt file and retaining historical identities.

## Verification

Local checks: repository `pnpm -r typecheck` and `pnpm build` pass on
the prompt-extraction tree (`88222d45d8`). Full repository coverage
previously completed through the supported isolated shard groups (1,082
general server suites, 161 serialized suites, and all three workspace
groups). The earlier default serial run was interrupted and remains
incomplete. The first sharded run retained the failures described below;
targeted corrections and separate limited-concurrency reruns pass. All
CI jobs, security checks, and the 5/5 Greptile review passed on
`fc1bd79c28`. Fresh CI and review are pending for the prompt extraction
in `88222d45d8`. Focused verification passes: real-database handoff
recovery and reuse; 2,002 native-tool/API contract checks; 144 Runner
catalog/discovery checks; 27 Runner context/coverage checks; 37
case/Audit UI checks; and Product E2E oracle calibration. Token gates,
migration safety/numbering, module boundaries, capability maps, and
generated tool/Storybook catalogs pass. The final route/context
corrections pass 49 API/native-tool tests, 90 real-database handoff
tests, and server typecheck; 142 Copilot installation/sidecar tests pass
with the refreshed identity.

Greptile’s first review found that successive prompt pages could mix
definitions after an edit. The fix returns a content fingerprint,
requires it for continuation, and rejects edits with 409. Strict
live/catalog schemas pass (171 Runner checks). The 2,005 API/OpenAPI
tests pass; the initial native regression caught compression’s weak ETag
prefix, and all 23 native integration tests pass after handling it. The
regression covers same-length edits and a four-byte restart window. No
stored version fields or entities were added.

The prompt extraction passes all 462 checks across six focused suites,
including persisted-context recovery and provider transport. The first
local transport attempt lacked the required debug Runner binaries (102
failures, retained); after building the normal prerequisites, all 283
tests in that suite pass without source or assertion changes. Existing
saved snapshots retain their recorded prompt text, and new executions
use core-only prompt v7. The extracted prompt source is now covered by
both CODEOWNERS and Copilot’s source fingerprint.

Live-provider evidence is separate from those simulated checks: the
isolated API-key campaign `reusable-workflows-api-final-2026-10-21`
passed with local code matching `a1d73b4652`. Four actual Codex API runs
read the adopted task documents, moved one case A → B → A on the same
task, completed normally, and passed all nine durable checks. Browser
assertions verified the current workflow/phase, historical names/phases,
five handoff records including terminal completion, and the completed
original task. Cleanup passed. The local report remains under
`tests/runner-e2e/results/reusable-workflows-api-final-2026-10-21/`; no
credentials or screenshots are committed.

CI initially caught an omitted route-inventory entry and a stale pinned
instruction-source hash; both are corrected and separately verified.
Local serialized coverage also recorded an unrelated environment-route
socket disconnect and activity-route timeout; their separate 11-test and
17-test suites passed without code or timeout changes. An unchanged
chunked-webhook check also passed its separate four-test rerun. The
initial adapter/database workspace groups hit time and resource limits
under default worker counts; complete reruns with `VITEST_MAX_WORKERS=2`
pass, including all 55 database files and 211 tests. The UI/CLI groups
passed 837 files and 9,442 tests in the original run. Original failures
remain retained and are not regraded.

Earlier failed live campaigns remain unchanged: subscription HTTP 429
before agent execution; an obsolete exact-four-row oracle that rejected
the valid terminal fifth row; and a chat-marker expectation that did not
account for the existing explicit-comment presentation policy. The final
fixture requires terminal completion and places the marker in its
authoritative comment. Positive/negative oracle tests and the fresh live
campaign pass.

## Risks

- The additive migration adds a table and nullable case/handoff fields.
Existing rows keep null workflow metadata; no assignments are inferred.
- Adoption can wait on an intervening task-document edit. Recovery must
cancel the old intent and accept a new one after readback.
- Shared definition edits affect future adoptions. Existing case copies
keep their revisions.
- The feature remains experimental. This PR does not merge or deploy the
change.
- Live acceptance covers native Codex before the prompt extraction; this
cleanup has contract/transport verification rather than a new
live-provider campaign. The refreshed Copilot identity has static
compatibility evidence, not new live-provider qualification.

## Model Used

OpenAI Codex, configured model ID `gpt-6-astra`, xhigh reasoning. Used
terminal execution, file editing, and tool calls. The active
context-window size is not exposed.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 15:00:12 -05:00
eece07a747 fix: repair the complete projectless repository setup chain (#17088)
## Thinking Path

> - Paperclip lets people manage agents that do useful work.
> - A projectless task can prepare an authorized repository in its
retained workspace.
> - Setup must hand work to a later run without user supervision.
> - Real task attempts exposed gaps across admission, completion, and
queue dispatch.
> - A successful provider exit did not prove that the requested result
was delivered.
> - This PR repairs the existing lifecycle and checks the complete
repository journey.

## Linked Issues or Issue Description

Refs #17047. This PR includes the preserved repairs from #17049, #17052,
and #17082.

**What happened?**

A projectless native task could stop after requesting a repository. It
could also continue through a timer or generic recovery path and lose
its saved conversation lineage. The latest real Codex and Claude
attempts delivered correct files, but the native continuation had been
folded into the finishing predecessor. Both attempts remain failed
measurements.

**Expected behavior**

Prepare the authorized repository, retain the original context, and
dispatch one saved continuation after its predecessor finishes. Deliver
the verified result in the originating conversation. Stop, current
access, approval, and real blocker rules remain authoritative.

**Steps to reproduce**

Run the explicit automatic-repository suite for native Codex or Claude.
Inspect the downloaded result, original context artifact, both committed
run records, and continuation receipts. The suite uses one attempt and
does not widen the default paid selection.

## What Changed

- Resolve the retained local-board identity through current company
membership and workspace authority.
- Prepare required source dependencies before the isolated server
imports native tool authority.
- Explain the saved repository continuation in production completion
tools. Correct only the exact pending-checkout blocker backed by a live
receipt. Reject an unfinished response wait without a real response
source.
- Preserve the persisted task-session workspace source and its explicit
absence of root repository context. Permit Git's exact no-repository
result only for a validated plain task directory. Keep other Git errors
and linked metadata strict.
- Revalidate server-resolved same-agent continuation values against
current ownership and the saved kind, summary, and key. Carry this shape
through the internal bridge schema. Keep provider-facing schemas
restrictive.
- Preserve terminal result authority after a correlated successful
controller response. Controller rejection creates no result authority.
Bind the shared guidance and transport source in Copilot v55 and
preserve historical identities.
- Admit native status wakes with the existing no-coalescing contract.
The existing deferred queue retains a distinct future dispatch instead
of retagging the finishing run.
- Recover deferred conversation lineage through the actual admitted
dispatch. Accept a null outbox run binding only with matching decision,
effect, dispatch actor, idempotency, task, company, agent, and requester
evidence. Reject a conflicting nonnull binding.
- Independently grade retained random context, actual checkout bytes and
HEAD, accessible output, distinct continuation receipts, and admission
order.

## Verification

- Real database and Git regressions fail before their repairs. Prior
focused cohorts cover local-board authority, optional repository waits,
plain task directories, and first/reused workspace provenance.
- The new valid decision/effect-backed assembled-heartbeat regression
reproduces coalescing into its active predecessor before the queue
repair. With the repair, it dispatches one successor after the
predecessor finishes. Duplicate sweeps create no extra run.
- The deferred-outbox conversation regression fails before its repair.
The repaired test also rejects a conflicting predecessor binding.
- The current queue, continuation, publication, cancellation,
stale-admission, and domain cohort passes 344 checks across 11 suites.
Server and Product E2E typechecks pass. The strengthened
automatic-repository oracle passes 34 calibration checks.
- Three omitted/null/resolved forms pass through the compiled Rust
runner and controlled provider. The prior shared bridge cohort passes
492 TypeScript checks and 399 Rust core checks. Runner source identity,
TypeScript, Rust formatting, and locked Rust typechecks pass.
- Six real local development cells passed ordinary repository,
conversion, and necessary-question journeys. Independent artifacts and
rendered question/result evidence agree. They do not qualify staging or
Slack.
- Both latest automatic-repository attempts delivered correct files but
failed the strict continuation check. They remain failures. A fresh
replay of this queue repair is pending.
- On the combined candidate `380047f4b923807a8c4f7ef6016e4fe130ab4a3a`,
`pnpm -r typecheck` and `pnpm build` pass. Product E2E support passes
3,525 checks with two existing skips, plus 128 source checks. The
complete local `pnpm test:run` is running and is not yet a pass.
- The first replay selection failed catalog validation due to an
operator profile-ID error. A second selection used the wrong
default-model suite and was cancelled before any provider job existed.
Both setup attempts remain recorded. The corrected campaign selects the
recorded GPT-6.1 and Opus 5.5 models plus the local Stop/resume journey.
- Exact-head CI, review, and deployment acceptance remain pending.
GitHub reports delayed PR updates and webhook delivery; the current head
and checks have now propagated. No earlier-head green badge establishes
acceptance of this commit.

## Risks

This changes several boundaries of repository setup. Full product and
deployment acceptance remain required. The queue uses the existing
deferred admission and delivery contracts. Batch deduplication remains
in place. The provenance repair requires the actual bound dispatch and
does not grant publication authority. Current authorization is still
checked at publication. No accepted provider result is rewritten, and
completed provider work is not rerun to repair persistence or delivery.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools and code execution.
The runtime does not expose its exact deployment ID or context-window
size. Those values are not inferred.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Paperclip <paperclip@paperclip.ing>
2026-10-21 11:21:55 -05:00
DottaandPaperclip dff63551fe fix: resume unfinished work after repository preparation (#17047)
## Thinking Path

> - Paperclip manages agents that perform work for a company.
> - Task repositories are prepared at normal run admission.
> - A running native task can stage a repository while its work remains
unfinished.
> - The controller did not offer that saved setup as a continuation.
> - The agent could add a timer or wait for a user restart.
> - This change uses the existing same-agent continuation and status
ledger.
> - The accepted explanation and proven conversation remain available
after setup.

## Linked Issues or Issue Description

Refs #17045. That prerequisite has merged. This PR targets master.

**What happened?**

A projectless native task can request a repository for the next
admission. An unfinished task has no server-selected repository
continuation. An explicit same-agent continuation also loses chat
provenance.

**Expected behavior**

An unfinished standard task can yield and resume through the existing
admission queue. Its explanation and final result retain the authorized
conversation. A task that only stages a repository can complete without
another run.

**Steps to reproduce**

1. Start a native standard task in a task directory.
2. Request an authorized repository through prepare_repository.
3. Yield with unfinished work and no explicit continuation.
4. Observe that the former driver rejects the yield, although the
pending repository is saved.

## What Changed

- Offer a saved same-agent continuation for the current task's pending
repository.
- Accept that current server continuation in the shared provider driver.
- Resolve chat provenance through applied status decisions, delivered
effects, and admitted wakes.
- Preserve accepted setup explanations without repeating an owned
question card.
- Document optional reproduction details and configured repository
discovery.
- Extend database regressions and workspace access maps.
- Preserve Copilot profile v52 and bind the shared continuation source
in v53. Include the active identity in the QA image fingerprint.

## Verification

- Five focused server suites: 100 checks pass.
- Shared continuation driver: 12 checks pass.
- Server typecheck passes.
- Map contract and whitespace checks pass.
- Existing API and driver assertions fail on the former implementation.
- Real dispatcher and queue cohort: 43 checks pass. The original
reply-loss regression fails before the dispatch receipt fix.
- Continuation driver and installation identity cohort: 62 checks pass.
- Regenerated capability inventory and contract checks pass.
- Final response precedence cohort: 109 checks pass. The stale-comment
case fails on the former implementation.
- All required CI checks, build, and both source reviews pass on
b9c8677635.
- Live provider journeys and deployed acceptance remain pending. No live
qualification is claimed.

## Risks

A pending repository now offers a next admission when unfinished
standard work yields. Incorrect eligibility could create unwanted work.
The lookup requires the current workspace and task. Explicit completion
does not use it. Existing Stop, admission, approval, and transport
authorization remain authoritative. No schema or public task-status
change is included. The shared continuation change requires a new
Copilot source identity. This PR preserves v52 history and does not
claim fresh Copilot live qualification.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools and code execution.
The runtime does not expose its exact deployment ID or context-window
size. Those values are not inferred.

## 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-10-21 07:17:50 -05:00
Nicky LeachandPaperclip e5351b240a Verify native Runner setup through plugin tasks (#17029)
## Thinking Path

> - Paperclip manages work for AI agents.
> - An environment plugin can own a Runner task.
> - The merged launch-preparation contract lets the execution owner
build the provider configuration.
> - Core still needs a task process owner and a setup test that uses
that configuration.
> - This PR connects the task API to the Runner process-owner contract.
> - Operators can test a plugin environment before Core sends it task
work.

## Linked Issues or Issue Description

**Subsystem affected**

Runner, plugin SDK, and agent environment tests.

**Problem or motivation**

A task-only environment cannot use the shell-based setup path. Core must
verify the Runner hello exchange and process cleanup through dedicated
task operations.

**Proposed solution**

Add a lease-bound task driver and use it for a bounded setup probe. Keep
heartbeat admission and task execution in #16978. This PR follows the
merged launch-preparation contract in #16997.

**Alternatives considered**

A provider declaration alone cannot prove that Runner and the provider
connect. A shell bridge would give the plugin an unnecessary command
interface.

## What Changed

- Pass structured Runner launch data to process owners. Support an
external connection and explicit detach.
- Add typed launch authentication checks and checkpoint operations.
Check lease, run, project, and retained-task authority.
- Connect launch preparation, PRP, termination proof, and credential
handoff to the task driver. Reject local environment overrides during
installed-account setup. Pass saved-account identity and credential home
directly from Core.
- Run a short-lived setup probe through the existing agent environment
test API. Require a verified provider hello and cleanup. Keep saved
Copilot account checks metadata-only through a dedicated task operation.
- Update the Copilot source identity because the shared transport source
changed. Keep provider behavior and the earlier identity fixture.

## Verification

- CI passes on `f987adec7`: 55 successful checks and 5 expected skips.
Standard Greptile and Apex are both 5/5 with no open findings. The
branch merges cleanly with current master.
- Repository typecheck and build pass after the rebase onto the
workspace-provider contract. Server typecheck and build also pass after
the final setup fix.
- The 110 focused lease, SDK, setup, Copilot, and route cases pass after
the rebase. All 14 setup cases pass after the final change. These
include a real local Runner with a test provider. The saved-agent
model-discovery case also passes.
- Apex found that Core's relative workspace marker failed the driver
path check, and non-Codex sessions omitted the observed model. Both
failures were reproduced and fixed. The probe leaves physical workspace
selection to plugin preparation. The transport reads each provider's
observed model and exposes it to the driver. All 14 setup cases, 6
transport peer cases, and both existing real Runner/OpenCode cases pass.
Runner build and server typecheck pass.
- The coverage audit removed two redundant cases, repeated fixture code,
and two extra real Runner launches. It kept authorization, credential
selection, cancellation, lost replies, termination proof, checkpoint
identity, and provider setup checks.
- The Copilot source-identity check passes. The added-line secret and
PII scan passes. The unmerged v52 attestation was regenerated after the
shared transport fix.
- CI on `13faeff02` caught one stale Copilot digest assertion after
attestation regeneration. The literal now matches the candidate
attestation, and all 49 installation cases pass. That CI lane otherwise
passed 1,818 cases.
- An earlier CI run hit an unchanged UI toast timing test. The separate
fix is tracked in #16952. Current CI passes that shard. CI also caught a
stale model-discovery assertion in this change; the assertion is fixed.
- The local full-suite run was stopped when master changed. The final CI
run supplies exact-head full-suite validation. No live Cloud or provider
test was run.

## Risks

- Native hello tests require a saved Core account or the installed
account. Local environment overrides are unsupported for
installed-account probes and fail before the provider runs.
- A native task provider must declare launch preparation and
authentication-check version 1. It must keep the checked configuration
fixed through submission. Core rejects providers that cannot make this
guarantee.
- A lost task reply does not prove process termination. Core retains
grants until the provider proves termination and Core saves required
state.
- This PR does not enable native heartbeat dispatch through plugin
environments. Cloud deployment and live provider validation remain
separate.

## Model Used

OpenAI Codex, GPT-6. The exact model ID and context window are not
exposed in this session. Tool use includes code editing, local tests,
and the GitHub CLI.

## 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 issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal issue
details
- [x] I have run focused 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-10-20 18:13:09 -07:00
DottaandPaperclip d33b40a5c3 fix: recover saved work and provide reliable task Retry (#16965)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The control plane must retain work when an execution or workspace
export fails.
> - Retained-workspace holds can leave saved input waiting with no
usable Retry action.
> - Users cannot verify process ownership or repair provider
allocations.
> - This pull request gives system recovery a durable budget and gives
each deliberate Retry a durable intent.
> - Safe recovery can preserve files, settle an accepted result, or
prepare an independent workspace.
> - One task state keeps infrastructure diagnostics out of the ordinary
conversation while preserving real permission and approval gates.

## Linked Issues or Issue Description

**What happened?**

A task with a retained workspace can show recovery, failed-run and
saved-message warnings at the same time. Historical runs without native
workspace descriptors cannot use the native restore path. Old recovery
metadata can prevent a new attempt even when an independent workspace
would be safe.

**Expected behavior**

Paperclip owns bounded infrastructure retries and file preservation. A
user can request another attempt with ordinary Retry. Thinking appears
immediately. The service preserves completed effects and current user
controls. It does not claim that starting fresh recovered the old files.

**Steps to reproduce**

1. Retain a failed run and its workspace after export or process-stop
failure.
2. Save a follow-up while the recovery hold is active.
3. Open the task and try to continue without infrastructure credentials
or operator certification.

Refs #16906, #16835, #16883. This extends their recovery and receipt
contracts. Related work: #16962 and #16963.

## What Changed

- Add task-level Retry with company-scoped authorization, all-status
idempotency and durable admission before physical work. Keep exact-run
Retry compatible.
- Add typed recovery phases, finite persisted backoff, historical
adoption and durable local failure diagnostics.
- Preserve native workspaces or verified historical snapshots. Admit an
independent fresh workspace only after execution containment. Keep
old-source preservation and cleanup obligations separate.
- Carry completed publication and API receipts forward. Fence uncertain
mutation retries across replacement runs. Preserve connected-chat
identity and authorization.
- Re-enter normal dispatch for saved input. Reuse accepted results
through the existing finalizer.
- Use one task interruption projection across the thread, composer and
task list. Show optimistic Thinking, ordinary Retry and genuine user
gates.
- Add PostgreSQL, filesystem, API, browser-fixture and controlled
provider coverage. Document the behavior and update the feature/access
maps.

## Verification

- All GitHub Actions CI jobs pass on
`6d8c6d27d50586d8548b31d03b47f6d73a0ee11d`: typecheck, all
server/chat/workspace and serialized suites, Runner checks, eight
browser shards, canary and build. The required merge gate passes.
- Greptile reviewed the final commit at 5/5, with no actionable findings
or unresolved review threads. Its two earlier P1 findings are fixed.
- Full recursive typecheck and build pass locally on the final commit.
All 16 task Retry cases pass against isolated real PostgreSQL. The
unrelated-success case and both stale Retry cases fail on the previous
code and pass after the fix.
- The corrected gateway fixture passes its uncertain-mutation and
independent-read case. Four real HTTP API cases pass for definite
403/422 rejection, completed-effect reuse, and uncertain-effect fences
across deliberate and automatic retries. These focused gateway/API
checks used a temporary database lifecycle harness on an existing
healthy local PostgreSQL process. The standard repository helper is
unchanged.
- Earlier qualification covers 291 task UI cases, saved-file copyback
and ancestry, current Agent Chat ownership races, nine chat Retry API
browser cases, and six assembled browser recovery fixtures. A real
API/PostgreSQL/native-runner journey showed Thinking in 25 ms despite a
delayed response, admitted one successor in a separate workspace,
retained original files, and survived reload.
- The controlled Daytona test interrupts export, joins the controller,
restarts it in a separate process, and verifies one agent start, one
external sentinel operation, retained file contents and no premature
cleanup. It does not establish abrupt-kill or live LLM/GitHub
acceptance.
- The full local `pnpm test:run` was attempted and was not green: an
OAuth row-lock timing assertion failed, and a later suite exhausted
macOS PostgreSQL semaphores. The ten OAuth timing cases passed on rerun
against a separate database. Later embedded database initialization
failures remain recorded; the final CI matrix passes.
- Security scanning passed on production-code commit
`63953edf069b111c6becc3144dffa6deb52f68b5`. Its only successor changes
one test-fixture identity line. The final scan is neutral/inconclusive
because its pinned merge-base checkout failed or timed out. Both rerun
API requests returned 404, so no fresh successful scan is claimed.
Socket and Snyk checks pass on the final head.
- The optional Paperclip Review remains queued behind an earlier run in
workspace finalization. Its prior completed assessment was incomplete
because a comparison tool was blocked by the platform filter. It is not
counted as a completed code review. GitHub does not require this check
for merge.
- Hosted acceptance remains pending deployment. Local and CI results do
not establish recovery of a hosted task or its retained files.

## Risks

- Recovery changes span admission, physical ownership and dispatch.
Incorrect evidence could permit overlapping work. Existing physical
locks and authoritative stop requirements remain in place.
- The migration adds concurrent indexes. It requires the existing
top-level migration runner and retries incomplete index creation safely.
- A fresh attempt can complete while old-source preservation remains
unresolved. The service retains that obligation and does not report
those files as recovered.
- Unknown tool mutations remain blocked until their authoritative
receipt owner resolves them. Generic upstream tools have no universal
result-query protocol.
- Recovery and diagnostics stay inside the stack. No Cloud incident
endpoint, notification worker or new outbound reporting channel is
included.

## Model Used

OpenAI Codex, GPT-6 family. The runtime does not expose a more specific
model version or context-window size. The model used reasoning, shell
execution, source editing and browser tools. No model subagents were
used for this implementation.

## 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 (focused suites; the full
local run limitation is documented above)
- [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-10-20 19:58:53 -05:00
Nicky LeachandPaperclip 2a5a323e57 Add execution-owned Runner launch preparation (#16997)
## Thinking Path

> - Paperclip manages work for AI agents.
> - Runner can execute in a different environment from Core.
> - Core owns provider selection, policy, and resource assignments.
> - The execution environment must prepare its own files and paths.
> - A shared contract must keep these responsibilities separate.
> - This PR adds that contract to the Runner execution driver.

## Linked Issues or Issue Description

**Problem or motivation**
Runner transport prepares provider files on the controller before
launch. An execution owner cannot prepare those files in its own
environment through the existing driver.

**Proposed solution**
Add `prepareLaunch` to the execution driver. Supply versioned Core
requirements. Accept a configuration ID, requirements digest, and
ordinary provider descriptor. Validate Core policy and assignments
before launch. Keep existing provider session checks.

**Alternatives considered**
Provider-specific ownership flags would spread the boundary across
backends. Shell preparation would expose process details in the plugin
API.

Refs #16993, #16977. Both prerequisites are merged. This PR now targets
master. Native plugin integration and execution-host preparation follow
separately.

PR #16978 contains an earlier, unmerged prototype. Its
`persistentAgentHome` mode and skill path-map call will be replaced by
this preparation contract before activation. This PR preserves current
master callers of the skill helper.

## What Changed

- Add the optional preparation callback and an explicit Runner artifact
identity.
- Keep the built-in preparation path as the default.
- Validate provider policy and resource assignment identity. Preserve
instruction text when resource locations change.
- Persist the attachment seed after an authority epoch rotation, so a
later controller restart can recover the same run.
- Preserve explicit context removal on a new run. Only an omitted
context can reuse the saved context. Remove its registered instruction
framing when context is removed.
- Save exact requirements and configurations in a private file outside
Runner commands. Retain the active record across failed attachments. Use
current grants for new runs. Keep incompatible session changes rejected.
- Join delayed preparation during startup and warm attachment cleanup.
Retain an unsettled checkpoint after a timeout. Prevent work after
cancellation.
- Use the supplied Runner artifact for interrupted handoff recovery.
Restore the exact target configuration at each handoff crash boundary.
Check the Runner state when the final ACK may be lost.
- Bind the changed shared sources to Copilot profile v51. Preserve the
v50 receipt and current integrity checks.

## Verification

- Workspace typecheck passed.
- All 487 affected Runner transport, control-plane, preparation store,
builder, policy, and profile tests passed on commit `eaf8ae8d1`.
- Workspace build and typecheck passed again on commit
`eaf8ae8d12c7ef2d22d226e4b3f05fdbf79ef4cb`.
- Both warm attachment cleanup regressions fail before the fix. They
pass after the fix. The tests cover delayed preparation, timeout
retention, and concurrent attachment rejection.
- The routed handoff regression fails with a missing controller binary
before the fix. It passes after the fix. The execution owner launches
the real fixture Runner.
- The 200,000-byte instruction regression fails before the fix and
passes after it. Four prepared handoff crash cases verify exact request
and configuration recovery. The store tests verify private file mode,
conflicting records, corrupt data, and active-run retention.
- A real Runner with a controlled fake provider verifies execution-host
paths, exact recovery, warm reuse, incompatible profile rejection, and
cancellation. It does not contact an external provider.
- The regression found undefined settings in strict PRP command hashing.
Requirements now contain only JSON values. The warm transition test
passes without changing PRP validation.
- The broader root suite on the prerequisite finished with 22,420
passing tests, seven failed tests in unchanged Git and diagnostic code,
and two suite setup errors because Cargo was absent from its PATH. This
PR does not claim a passing full root suite.
- The CI Build job passed compilation and production runtime boot, then
its runner received a shutdown signal during the clean public install
check. Other jobs reported lost communication with their self-hosted
runners. The failed jobs passed on retry on the same commit; successful
jobs kept their results.
- The current Superagent security scan is inconclusive because its
pinned merge-base checkout failed or timed out. GitHub rejected the
check rerun request through the available API. This is not a passing
security scan.
- Standard Greptile and Greptile Apex each returned 5/5 on `eaf8ae8d1`.
All review threads are resolved. CI passed on attempt 2. Current checks
have 55 successes, four optional skips, and the inconclusive security
scan described above. The branch is ready, mergeable, and current with
master.
- No live provider qualification or deployment was run.

## Risks

- A preparation owner must store configurations and keep retries bound
to the same task and requirements.
- Copilot source binding requires a new profile identity. This PR does
not claim fresh live qualification.
- The callback is an SDK extension. This PR does not connect it to a
plugin task process owner or add a Launcher endpoint.

## Model Used

- OpenAI Codex, GPT-6. Reasoning and repository tools. The exact serving
model identifier and context size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-20 14:24:13 -07:00
Nicky LeachandPaperclip 05f7079ecb Extract Runner provider launch preparation (#16977)
## Thinking Path

> - Paperclip manages work for AI agents.
> - Runner starts providers in local and remote environments.
> - Core selects the provider and task policy.
> - The execution environment supplies paths and installed files.
> - The transport currently combines these inputs in one large method.
> - This PR extracts provider descriptor construction before a separate
plugin preparation change.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Runner provider launch preparation.

**Current behavior**
The PRP transport constructs each provider descriptor inside startup.
This couples provider configuration to transport lifecycle code.

**Proposed behavior**
The transport calls one built-in descriptor builder. The builder takes
Core provider requirements and execution-environment locations as
separate inputs. File staging, provider validation logic, and session
rules keep their current behavior. The required Copilot source-identity
update changes profile admission metadata.

**Reason and benefit**
This gives launch preparation a separate unit of code. A later PR can
add plugin-owned preparation without adding ownership flags to each
provider backend.

Refs #15406, #16486. This replaces the earlier installed-home
implementation in this PR. #16978 remains a draft.

## What Changed

- Extract provider descriptor construction and its existing permission
helpers.
- Keep helper exports at their previous import path.
- Add focused tests for selection, permissions, locations, and managed
profile rejection.
- Update the Copilot source identity. Bind the extracted file and retain
the v49 history. The source attestation requires v50 after this move.
This changes the admitted profile identity even though no execution
behavior changes are intended.
- Document the boundary and its current limits.

## Verification

- 338 focused builder, transport, Codex security, and Copilot identity
tests passed on the rebased head.
- `pnpm -r typecheck` passed. `pnpm build` passed.
- The full root `pnpm test:run` on the pre-rebase head is still in
progress. It has reported five failures in unchanged server tests. One
isolated failure rejects the word `private` from this checkout's
`/private/tmp` stack path. The full root suite is not reported as
passing.
- All 56 CI checks passed on the rebased head. Four optional checks were
skipped. The branch is mergeable. Workspace typecheck and build passed
on this head.
- Standard Greptile and Apex each scored commit
`47f631883d8f417f6a818500ebe4e77e22cc70b8` 5/5. The rebase onto master
changed only Copilot identity metadata, history handling, and related
tests. `git range-diff` confirms that the launch-preparation
implementation is unchanged. The existing Apex result remains the review
evidence; it did not review the new commit hash.
- No live provider calls or Cloud deployment were run.

## Risks

- A moved field could change provider startup. Existing transport tests
and the new boundary tests check the projection.
- Copilot source binding requires a new identity after the move.
Existing artifacts and retained sessions must match the new admitted
profile. This PR does not claim fresh live qualification.
- This PR does not enable plugin-owned preparation. File materialization
remains in the existing SDK path.

## Model Used

- OpenAI Codex, GPT-6. Reasoning and repository tools. The exact serving
model identifier and context size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-20 11:20:49 -07:00
DottaandPaperclip 505e1a5582 feat(cases): add persistent workflows with same-task agent handoffs (#16959)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - An agent workflow needs persistent facts and a safe way to transfer
work.
> - Creating a task for each phase splits the objective, discussion,
workspace, and review policy.
> - A case can retain the facts while one primary task moves between
agents.
> - Transfers must survive process failure and preserve private access,
budgets, and completion gates.
> - This pull request adds durable case handoffs, native case tools, and
read-only case pages.
> - Prompts describe the workflow. Existing task controls decide when
work can run and finish.

## Linked Issues or Issue Description

**Problem or motivation**

Prompt-driven agent teams need a persistent record that can move through
triage, implementation, verification, and correction. Ordinary
reassignment does not provide a durable instruction, safe release
barrier, or recoverable delivery receipt for an agent handing off its
own running task.

**Proposed solution**

Extend standalone cases with one primary task, a descriptive phase,
retained access sources, and a handoff ledger. Apply assignments after
source execution and workspace settlement. Deliver each transfer through
the existing durable wake queue. Provide `create_case`, `read_case`,
`update_case`, and `handoff_case` in the native runner. Creation
requires kickoff and explicit workflow text. An explicit handoff to
`done` closes the case when normal task completion is accepted.

**Alternatives considered**

Do not add a workflow engine, filesystem queue, configured state graph,
or one task per phase. The workflow document combines transition prose
with an optional Mermaid `stateDiagram-v2` map. The server does not
execute the diagram. The Pipelines experiment removed on master stays
removed.

**Roadmap alignment**

This extends Agent Reviews and Approvals, Enforced Outcomes, Bounded Run
Recovery, and Activity Log attribution. Existing approval, review,
budget, privacy, workspace, and responsible-user rules remain
authoritative.

Related work: [ordinary handoff wake
recovery](https://github.com/paperclipai/paperclip/pull/15019). This
feature adds a separate persisted case-handoff receipt and release
barrier.

## What Changed

- Add case routing fields, retained access sources, durable handoff
history, delivery leases, and replay-safe migrations.
- Keep the same primary task across agent phases. Preserve each
returning agent's own session and the task's workspace.
- Fence outgoing mutations, wait for provider and workspace release, and
recover delivery without duplicate task comments or runs. Recheck
current assignment permissions as the original caller before applying a
delayed transfer. Scope a run Stop to that run’s own handoff intents, so
repeated old Stop requests preserve newer work. Cancelling terminal
intent without a source run also requires fenced current task ownership,
including native retries and preparation with an old checkout. For Cloud
callers, revalidate current stack membership with an uncached Cloud RPC
and derive owner elevation from the current managed setting.
- Keep case reads, documents, assets, Audit, and live events inside
retained task/project permissions.
- Add native case creation/read/update/handoff tools. Store required
workflow text and initial documents on the first task. Page oversized
case facts and referenced document bodies through the dedicated tool
with bounded UTF-8 JSON, current routing versions, snapshot conflicts,
and current source authorization on every page.
- Add read-only case lists and detail pages, task-style list controls,
compact dotted field tables, linked handoff tasks, and case filters in
Audit.
- Add native/legacy integration tests, migration/restart tests, browser
coverage, and bounded live receipt fixtures. Extend the trusted sandbox
condition to cover the new subscription fixture profile.
- Hide obsolete paused-agent warnings on completed or cancelled task
threads.
- Synchronize the company-switch settings test with React effects after
a CI failure. Preserve its security assertions and production remount
behavior.

## Verification

The branch directly includes master `9ef434fe79`. The required `ci /
verify` and `ci / e2e` gates pass on head `765fccd67c`. [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39464348614)
passes typecheck, build, tests, and all eight browser shards. Security
checks pass. [Greptile gives this exact head
5/5](https://github.com/paperclipai/paperclip/pull/16959#issuecomment-6291156549),
with no unresolved review threads. The optional Paperclip Review check
remains queued because its assigned agent is paused. It is not a
required branch check. No check result was overridden.

Local workspace typecheck and build pass after the master merge, along
with database migration checks, token gates, map checks, Storybook
catalog checks, and the Copilot profile identity check. Standard builds
refresh Runner vendor output. Focused checks pass 2,008
API/paging/context tests and 7 strict case protocol tests. The final
commit changes one test fixture only; its ten tests, UI typecheck, and
token gates pass. No production source changed in that commit.

On current head `765fccd67c`, all **194 critical workflow tests**
executed and passed with no skipped tests in those files:

- 38 Stop/ownership tests, including board completion intent, native
retries, stale Stop, and preparation with an old checkout.
- 2 actual legacy process/HTTP handoff tests, including scratch failure,
a closed-stdio child that continues writing, and recovery through a
fresh worker after the process group stops.
- 5 migration tests, including SQL column metadata, preserved null
authority context, and all six prior-numbering receipts.
- 3 process-settlement and 5 scratch tests.
- 88 handoff-service, 18 heartbeat handoff, and 21 native case-tool
integration tests.
- 7 bounded case/document-read projection tests and 7 strict
protocol-contract tests.

The current CI checkout was `fed65d49`, merging `765fccd67c` into master
`9ef434fe79`. Its new document regressions reconstruct exact
Unicode/escaped bodies and revisions through real native authority and
authenticated HTTP with generic API tools disabled. They cover
case-owned, primary-task, and linked-task documents; routing on every
page; stale document snapshots; access loss and unlinking;
unrelated/foreign/private sources; system documents; and quarantined
content. Active-task document tools retain their existing behavior.
These are current-head test results from the first CI attempt; the
browser-only retry did not rerun these suites.

The full `64fdd3403f` CI failed one separate settings test: after a
company switch, it observed an unsettled API-key draft. The production
component and test were unchanged from prior green source. Production
switches remount both keyed settings layers; the test directly reused an
unkeyed view and used a timer tick instead of waiting for React effects.
The final commit replaces that fixture synchronization with React `act`.
The exact secret-clearing assertions and all timeouts remain unchanged.
The original assertion failure remains recorded; no unchanged retry was
used. The narrow unchanged baseline and fixed fixture each pass 10
tests.

The upstream result-paging merge preserves case capture namespaces and
current asset privacy. Its API integration suite executed 39 of 41 tests
successfully, with two skipped; the optional assigned-result PRP
integration test was skipped. Neither skipped suite is counted in the
194 critical tests or as live provider proof.

All 361 upstream migration entries and SQL bodies remain unchanged. Six
case migrations follow master as 0363–0368 with identical SQL hashes.
Official Drizzle generators produced the combined metadata and five
retained snapshots. Generation reports no schema changes, and the
snapshot drift test passes. The earlier `ce361ae5d0` CI passed on
attempt 1, including its then-current 179 critical tests. Fresh review
later identified unusable document references with generic API tools
disabled; the bounded document reads and ten additional authenticated
HTTP tests address that finding.

The full local `pnpm test:run` attempt was cancelled after this Mac
exhausted PostgreSQL semaphore capacity; it is **not** counted as a
pass. Later database attempts also stopped before assertions or skipped,
including one sandbox socket denial. Two original stale-Stop regressions
did reproduce the bug against the old source. A REST serialization
assertion passed after two preserved database-startup failures. No test
timeout was increased. All 194 assertions listed above executed and
passed in current-head CI. The complete 385-file, 3,963-test UI shard
also passed after the fixture repair.

A configured-provider receipt workflow passed 13 backend checks across
triage → implementation → verification → correction → done, using one
task and four work runs. The saved receipt is revision 2 with total 6
USD; case and task both closed. The original canonical attempt remains
failed because its browser assertion confused the terminal destination
with completed-task tooltips. The corrected full browser verifier passed
on the same retained database and original runs, with no additional
provider calls. The last clean-build browser readback is on
`6a86c54a53`; later changes affect recovery, authorization, bounded
reads, and settlement. Accounted work cost is a $1.010574 rate-card
estimate; provider billing and setup-probe usage are unavailable.

Copilot profile 49 passed the unchanged seven-fixture private protocol
pack (46/46 checks, no retries) and the product file-edit canary after
master's completion-replay change. All 60 bound implementation hashes
remain unchanged on the current source. Historical profile-47/48
identities and results remain intact. See the [profile-49 compatibility
record](https://github.com/paperclipai/paperclip/blob/codex/persistent-case-handoffs/doc/plans/2026-10-20-copilot-completion-recovery-compatibility-v49.json).
This is bounded compatibility evidence, not a fresh full matrix,
installed-package product test, or Daytona rollout.

Preserved CI failures and retries:

- On `20662930ac`, Slack managed setup failed a five-second success
assertion after reload. Its test/application path was unchanged from a
prior green head. One unchanged-source retry passed all 25 tests in that
shard; no source or timeout changed.
- On `9402b4f17a`, two CI workers received shutdown signals at 15:24:19
UTC. Neither log had an assertion failure before interruption. One
unchanged-source retry of each passed all Runner static checks and all
32 tests in browser shard 6; both aggregates passed. The next head,
`7b4374edaf`, passed all CI without retries.
- On `295f289b5a`, serialized shard 9 timed out during its first
device-login test, then the next test found an active login lease.
Direct login/test paths were unchanged from a prior green head. Cold
import plus a timed-out async body using the next test's mutable
actor/store is the supported fixture-race explanation; no request trace
proves that sequence. The original failure remains recorded. One
unchanged-source retry passed all 294 tests in 19 files, including all
41 device-login tests. No login source or timeout changed. The
subsequent `ce361ae5d0` CI passed without retries.
- On `64fdd3403f`, one company-switch settings assertion observed an
unsettled draft. The final test-only commit uses React `act` without
changing assertions, timeouts, or production code. On `765fccd67c`, all
ten settings tests and the complete 385-file, 3,963-test UI shard
passed.
- On `765fccd67c`, browser shard 3 completed the split-handoff
assertions, then cleanup received HTTP 500 from run cancellation after a
one-second PostgreSQL row-lock timeout. The extra chat run was reporting
completed work while teardown began. Cleanup stopped before restoring a
global experiment flag, causing a later assertion to fail. Relevant
production and test paths are unchanged from an earlier green commit.
Stop's lock order is consistent, and no nested self-lock was found; the
exact PostgreSQL blocker was not recorded. One unchanged-shard retry
passed. The original failure, trace, and downstream flag failure remain
recorded. No Stop implementation, cleanup assertion, or timeout changed.
The retry supports intermittent cleanup contention; it does not identify
the original blocking transaction.


## Risks

- Local process transfers require host-owned PID/group absence. Missing
or uncertain termination evidence keeps delivery pending, independently
of scratch setup.
- Handoff admission and task cancellation share execution ownership. New
regression tests cover temporary holds, late source writes, and
uncertain provider termination.
- Retained private sources use an intersection of existing permissions.
This intentionally fails closed when a source is missing or an existing
task cannot preserve that boundary.
- Migrations add tables and indexes. They preserve master history and
can replay over prior feature installs. Migration 0368 adds nullable
internal authorization provenance with no default or authority backfill.
Historical transfers still awaiting release without this context fail
closed; an operator must cancel them and request a new handoff.
- Delayed Cloud handoffs depend on the current Cloud membership RPC. An
unavailable, ambiguous, expired, or mismatched response holds the
handoff for retry; it does not reuse cached authority or grant access.
- Bounded reads reload and reauthorize the selected projection per page.
Underlying work grows with the data size and number of pages. Changed
data or routing requires restarting from offset zero without the old
snapshot.
- Phase names and workflow diagrams remain advisory. They do not satisfy
review or approval gates.
- This is a large, cross-cutting PR. The maintainer requested one PR for
the whole feature; the commits separate data, runtime, UI, and
qualification work.

## Model Used

OpenAI Codex, GPT-6 family, with tool use, code execution, and delegated
code review. The exact deployment model ID and context-window size were
not exposed in the session. Live fixture agents used the explicitly
configured provider model recorded in their test evidence.

## 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-10-20 12:46:14 -05:00
Nicky Leach 34be1b831b Fix duplicate ACPX skills cleanup in test teardown (#16937) 2026-10-20 07:44:28 -07:00
DottaandPaperclip d84061b923 fix(runner): recover journaled completion proposals (#16962)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native runs preserve provider sessions across controller restarts.
> - A completion event can reach durable storage before the next session
checkpoint.
> - Recovery advanced the event cursor but lost the saved completion
proposal.
> - The completed turn then appeared to need another provider turn to
report its result.
> - This change restores the exact active turn's proposal before
advancing the cursor.
> - Recovery can finalize completed work without repeating its external
actions.

## Linked Issues or Issue Description

**What happened?**

After a controller restart, a native run could fail with
`native_finalization_missing` even though `run.result.proposed` was
already durable. The recovered driver skipped that event when its cursor
advanced, so the result was absent from its state. Automatic disposition
retries could then encounter outstanding tool receipts and exhaust
recovery.

**Expected behavior**

Restore the saved result for the exact active turn. Wait for provider
termination, then use normal finalization. Do not start another provider
turn to repeat completed work.

**Steps to reproduce**

1. Start a native Codex task and save its active-turn checkpoint.
2. Persist its completion proposal, then lose the controller before
another checkpoint.
3. Recover the same run after the provider completes. Before this
change, finalization reports a missing result.

**Paperclip version or commit**

Reproduced on `92b238137b`. The repair is based on `7c247243e5`.

**Deployment mode**

Native Runner with Codex. The incident used a remote sandbox; the
regression covers controller event recovery.

Related: #12845 and #15297. The older #12241 addresses provider process
continuity; this change repairs the controller's saved event projection.

## What Changed

- Restore valid completion proposals for the checkpoint's exact active
turn during event replay.
- Reject conflicting, invalid, or incorrectly bound proposals. Ignore
proposals from another turn and prevent adoption after a newer turn
starts.
- Keep provider termination and normal finalization as separate
requirements.
- Add eight behavioral cases using the real Codex driver and a simulated
transport, and document the recovery contract and verification scope.

## Verification

- Red: the new restart regression failed with
`native_finalization_missing` before the production change.
- Green: 254 tests passed across the native runtime, backend adapter,
and Codex recovery suites. The new cases check no repeated provider
work, no early finalization, duplicate proposals, conflicts, invalid
proposals, and stale turn/session bindings.
- `node scripts/check-maps.mjs` and `git diff --check` passed.
- `pnpm -r typecheck` and `pnpm build` passed locally. All CI gates
passed on `2ac025a15c`; Greptile rated that commit 5/5 with no
outstanding findings. The full local `pnpm test:run` was started after
completing the embedded PostgreSQL installation, then stopped while
still running once the complete CI test matrix passed; it is not
reported as a completed local run.
- Real local acceptance passed on `2ac025a15c` with the production Rust
Runner transport, Codex CLI `0.160.0`, and `gpt-6.1-sol` on macOS arm64.
Persisted the completion proposal while retaining the older active-turn
checkpoint; let the provider finish without persisting its later
controller events; stopped the exact owned runner/provider; recovered
the same provider session and turn. Observed one accepted result, one
durable `turn.start` command, and one line in the receipt file. Hosted
sandbox restart and recovery of the original stopped task have not been
performed.
- Initial setup failures are retained: dependency drift caused
diff-viewer type errors, and skipped PostgreSQL postinstall links
prevented database startup. Dependency alignment and the package
postinstall repaired those local prerequisites. Probe setup iterations
failed on a direct-provider response schema, invalid probe input fields,
and an original provider that still held its writer lock. Acceptance
uses the production transport, validated input, and exact-owner
shutdown. No production code changes were made for those probe setup
failures.

## Risks

- A stale proposal could finalize the wrong work. Recovery requires the
checkpoint's active turn and matching run, session, and source. It
rejects conflicting results and waits for provider termination.
- The change uses the existing paginated recovery scan. It adds no
database query per event or new retry allowance.
- No schema migration or change to task authorization is included.

## Model Used

OpenAI GPT-6, running as Codex with reasoning, tool use, and code
execution. The exact served model snapshot and context-window size are
not exposed in this session. The live acceptance probe uses
`gpt-6.1-sol`.

## 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-10-20 09:09:22 -05:00
628993fc59 fix(runner): name the tool receipts that block the next provider turn (#16961)
When a resumed run cannot start a turn because the semantic tool bridge
still holds pending or unsettled completed receipts, the error now names
each blocking receipt by operation and call ID (bounded to four per set).
Tool input and result content stay inside the bridge. Adds an integration
test covering the four-receipt limit and the trailing "...".

Co-Authored-By: Paperclip <Paperclip-Paperclip@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 06:49:17 -07:00
DottaandPaperclip df80616d98 Preserve Copilot historical runtime attestations (#15703)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Runner recovery must distinguish old profile identities from the
current launch identity.
> - The long integration produced historical attestations that must
remain inspectable after consolidation.
> - The release must preserve saved-token access and task lifecycle
guarantees.
> - This pull request will retain the historical Copilot profile records
without granting old profiles launch access.
> - The benefit is a reviewable part of the Copilot production release.

## Linked Issues or Issue Description

Refs #15701. Supersedes the provenance work in #15561. Base: #15701.
Next: #15705.

## What Changed

- Retain historical Copilot profile attestations as separate immutable
records.
- Preserve the mainline and candidate histories when version numbers
overlap.
- Keep exact current-profile launch checks in the runtime PR.

## Verification

Final reviewed source
[`4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5`](https://github.com/paperclipai/paperclip/commit/4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5)
includes master `cde944ed75648adfb569e86133adc8b118b55dd6`. The combined
four-part PR tree matches it except for the CI-owned lockfile. Every
prior public PR head remains an ancestor. Released master migrations
remain unchanged; Copilot adds migration361. No unrelated provider is
enabled.

Copilot CLI1.0.88 and profile47 retain digest
`sha256:55044aa235e88b3fe36ec8a556ee1e3382590870aab907e4462ef7d64af49cea`.
The pending qualification marker is removed. The [qualification
record](https://github.com/paperclipai/paperclip/blob/4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5/doc/plans/2026-10-20-copilot-qualification-v47.json)
reports **20/20 Product cells,154 assertions;7/7 protocol cases,46
assertions** against frozen installed application
`c2616370800f5f6df45246b0890ba35a7cd2faab`. Both environments use the
exact authenticated model `gpt-5.6-luna`. Every passing Product case
confirms cleanup. Automatic behavior retries are disabled. Original
failed attempts remain recorded.

The ordinary installed remote journey passed saved-token selection,
authenticated model discovery, normal UI save/reopen, metadata-only
Test, task completion, accepted receipt and an exact19-byte browser
download. An open model catalog caused no new discovery requests
during117seconds. Actual installed runtime smokes passed on macOS ARM64,
macOS x64 under Rosetta and native Linux x64 on Daytona. Raw token
browser entry was not exercised; the encrypted connection was created
through the normal API.

The original Daytona file attempt timed out during delayed semantic
dispatch. Its precise stalled layer remains unresolved. Independent
ordinary delivery and the other19 cells passed before one instrumented
recheck passed8/8 with unchanged source,prompt,assertions and deadlines.
No causal latency repair is claimed.

After current-master reconciliation,129 connection tests,59 runner
tests,72 shared eval tests and88 recovery/workspace tests pass.
Migration generation/safety, unchanged profile identity and UI token
gates pass. Prior required CI was green. Fresh exact-head required CI
and E2E are green for all four updated heads. Each has a fresh
Greptile5/5 review and zero unresolved review threads. The [final
normal-package cloud
build](https://github.com/paperclipai/paperclip/actions/runs/39414239704)
is running. Recursive typecheck,full CI test shards,build and all8
browser shards pass. These checks cover the final source; no additional
local full-suite pass is claimed.

The [frozen image
build](https://github.com/paperclipai/paperclip/actions/runs/39334401638)
and [original normal package
build](https://github.com/paperclipai/paperclip/actions/runs/39334407471)
passed. The exact image is published and independently retrieved
anonymously. No separate full-image scan is claimed. All18 original
normal archives were scanned with zero selected credentials. Docker
builds run in the cloud. Provider USD remains unknown and
GitHub-attributed.

**Qualification is complete on the recorded frozen build. Normal
protected merge, automatic master canary publication and final
shipped-package local/Daytona canaries remain. No production deployment
is claimed.**

## Risks

Historical records are evidence only. They must not be treated as
current qualification or as permission to launch an old provider
profile.

## Model Used

OpenAI Codex, based on GPT-6. The exact serving model ID and context
window are not exposed in this task. Used for code changes, review and
tool-assisted verification.

## 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 11:44:30 +00:00
DottaandPaperclip d855e550ad Finish Copilot native runtime on current master (#15701)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Runner controls provider processes, permissions and task
completion.
> - Copilot needs its pinned distribution, native message identities and
accepted semantic completion receipts.
> - The release must preserve saved-token access and task lifecycle
guarantees.
> - This pull request will keep the current completion and recovery
fixes while adding the Copilot runtime.
> - The benefit is a reviewable part of the Copilot production release.

## Linked Issues or Issue Description

Refs #14434. Supersedes the runtime work in #15560. This is the first PR
in the stack; #15703, #15705 and #15706 follow. Related alternative
adapter work: #15881. This change uses the shared Runner path.

## What Changed

- Pin Copilot CLI 1.0.88 and bind the integrated implementation as
profile45.
- Keep native instruction, permission, receipt, process ownership and
cancellation boundaries.
- Preserve current master completion continuation and remote
verification behavior. Other provider release identities stay unchanged.

## Verification

Final reviewed source
[`4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5`](https://github.com/paperclipai/paperclip/commit/4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5)
includes master `cde944ed75648adfb569e86133adc8b118b55dd6`. The combined
four-part PR tree matches it except for the CI-owned lockfile. Every
prior public PR head remains an ancestor. Released master migrations
remain unchanged; Copilot adds migration361. No unrelated provider is
enabled.

Copilot CLI1.0.88 and profile47 retain digest
`sha256:55044aa235e88b3fe36ec8a556ee1e3382590870aab907e4462ef7d64af49cea`.
The pending qualification marker is removed. The [qualification
record](https://github.com/paperclipai/paperclip/blob/4f3f1af807d2ed21adabb04c2f27f4df9c4bc8d5/doc/plans/2026-10-20-copilot-qualification-v47.json)
reports **20/20 Product cells,154 assertions;7/7 protocol cases,46
assertions** against frozen installed application
`c2616370800f5f6df45246b0890ba35a7cd2faab`. Both environments use the
exact authenticated model `gpt-5.6-luna`. Every passing Product case
confirms cleanup. Automatic behavior retries are disabled. Original
failed attempts remain recorded.

The ordinary installed remote journey passed saved-token selection,
authenticated model discovery, normal UI save/reopen, metadata-only
Test, task completion, accepted receipt and an exact19-byte browser
download. An open model catalog caused no new discovery requests
during117seconds. Actual installed runtime smokes passed on macOS ARM64,
macOS x64 under Rosetta and native Linux x64 on Daytona. Raw token
browser entry was not exercised; the encrypted connection was created
through the normal API.

The original Daytona file attempt timed out during delayed semantic
dispatch. Its precise stalled layer remains unresolved. Independent
ordinary delivery and the other19 cells passed before one instrumented
recheck passed8/8 with unchanged source,prompt,assertions and deadlines.
No causal latency repair is claimed.

After current-master reconciliation,129 connection tests,59 runner
tests,72 shared eval tests and88 recovery/workspace tests pass.
Migration generation/safety, unchanged profile identity and UI token
gates pass. Prior required CI was green. Fresh exact-head required CI
and E2E are green for all four updated heads. Each has a fresh
Greptile5/5 review and zero unresolved review threads. The [final
normal-package cloud
build](https://github.com/paperclipai/paperclip/actions/runs/39414239704)
is running. Recursive typecheck,full CI test shards,build and all8
browser shards pass. These checks cover the final source; no additional
local full-suite pass is claimed.

The [frozen image
build](https://github.com/paperclipai/paperclip/actions/runs/39334401638)
and [original normal package
build](https://github.com/paperclipai/paperclip/actions/runs/39334407471)
passed. The exact image is published and independently retrieved
anonymously. No separate full-image scan is claimed. All18 original
normal archives were scanned with zero selected credentials. Docker
builds run in the cloud. Provider USD remains unknown and
GitHub-attributed.

**Qualification is complete on the recorded frozen build. Normal
protected merge, automatic master canary publication and final
shipped-package local/Daytona canaries remain. No production deployment
is claimed.**

## Risks

Shared Runner behavior can affect active tasks. Exact profile admission
rejects stale runtime identities. The final campaign and installed
canaries remain release gates.

## Model Used

OpenAI Codex, based on GPT-6. The exact serving model ID and context
window are not exposed in this task. Used for code changes, review and
tool-assisted verification.

## 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 06:31:47 -05:00
DottaandPaperclip 7ec6e1a237 fix(runner): explain invalid arguments for assigned tools (#16905)
## Thinking Path

> - Paperclip coordinates agents through authorized tools.
> - The native runner validates arguments before it dispatches a tool
call.
> - Schema failures give repair guidance for only five built-in tools.
> - Assigned-tool discovery receives a generic rejection, so an agent
can mistake invalid arguments for missing access.
> - This PR applies the existing safe schema feedback to every
authorized tool.
> - Agents can correct their calls while authorization, approval, and
replay checks remain in force.

## Linked Issues or Issue Description

**What happened?**

An invalid `paperclip_search_assigned_tools` call returned only
`Paperclip rejected this semantic tool call`. The call never reached the
assigned-tool gateway. The same feedback gap affects arbitrary assigned
app tools.

**Expected behavior**

Identify argument validation as the cause. Return bounded schema
locations and ask the provider to correct its arguments. Do not expose
submitted values or grant access to unassigned tools.

**Steps to reproduce**

Prepare an authorized discovery tool. Submit an invalid query or
optional argument through the native runner. Observe the generic error
before this fix. Correct the arguments and confirm one dispatch after
this fix.

**Paperclip version or commit**

Reproduced on master at `4970d5ed3d`. The incident did not retain its
rejected arguments, so the tests cover representative invalid inputs
rather than claim to replay that exact payload.

**Deployment mode**

Native runner with the Codex app-server driver. Local verification uses
macOS ARM64 and controlled provider fixtures.

Related: #16868 added bounded monitor validation feedback. #16723
changes runtime MCP catalog loading; this PR changes the Rust runner
validation response and does not depend on that work.

## What Changed

- Supply generic repair guidance for any authorized tool whose arguments
fail JSON Schema validation. Preserve specific built-in hints.
- Keep the existing three-location and 512-byte limits. Do not include
input values or unknown keys. Preserve generic authorization failures
and the existing retry flag.
- Cover missing fields, wrong types, null optional fields, bounds,
unknown fields, unchanged rejected-call state, corrected calls, and
completed-call replay protection.
- Exercise rejection, correction, one dispatch, and successful
completion through the real Codex driver with a controlled provider
subprocess.
- Document the behavior and its verification scope in execution
semantics and the agent access map.

## Verification

- Red: both new runner regressions failed on the original generic
rejection. The existing API-validation regression passed.
- Green: all seven selected validation tests passed. The new Codex
transport regression passed with one rejection and one corrected
dispatch.
- `cargo fmt --manifest-path packages/paperclip-runner/runner/Cargo.toml
--all -- --check`, `node scripts/check-maps.mjs`, and `git diff --check`
passed.
- Full Rust workspace tests, the repository build, and sequential
repository typecheck passed. The existing assigned-tool gateway suite
passed all 30 tests. All hosted test and end-to-end jobs passed on this
head. The duplicate local `test:run` was interrupted after the hosted
suites passed; its local result is incomplete. The hosted build and
clean public npm installation check also passed. All current-head CI
gates are green, including the final verify and e2e aggregates.
- Greptile reviewed commit `3e2743e1e15b3b13a7d803ce4d828510e41fb22a`:
5/5, no actionable findings.
- Setup evidence: master has a stale dependency lockfile. Dependencies
were resolved with the pinned pnpm 9.15.4; lockfile changes are
excluded. The first full typecheck overlapped the build and failed
copying a generated shared-package file. The sequential rerun passed
with no source change. The initial copy failure remains recorded here;
the concurrent build-output race was not separately reproduced.
- The provider is simulated. This proves runner validation and transport
recovery, not that a live model always retries or that GitHub
credentials work.

## Risks

The provider now sees schema locations for all authorized tools. The
existing sanitizer and bounds still apply. Unknown input keys and values
remain excluded. No schema, permission, approval, automatic tool replay,
database, or connection-auth changes are made. Unauthorized tools still
get a generic rejection.

## Model Used

OpenAI Codex (GPT-6), with reasoning, source inspection, and tool
execution. The exact runtime model ID and context-window size are not
exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-19 17:03:42 -05:00
DottaandPaperclip 6f045207bb fix(runner): explain rejected API response windows (#16889)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use the API fallback when dedicated tools cannot express an
operation.
> - Large responses can be read in bounded text windows.
> - The declared schema rejects windows larger than 24576 bytes.
> - The runner hid the rejected field behind a generic semantic tool
error.
> - This pull request returns safe schema locations and the accepted
byte range.
> - Agents can correct a call without guessing or changing route
permissions.

## Linked Issues or Issue Description

Refs: #16868, which added repair guidance for task monitor arguments.

**What happened?**

A native call_api request with responseText.limitBytes set to 60000
returned invalid_tool_call with no field or size guidance. The declared
4..24576 byte range already matches the server validator. The missing
repair guidance is in the runner bridge.

**Expected behavior**

Reject invalid input before dispatch. Show bounded schema locations and
the accepted window range. Do not echo submitted values or unknown field
names. A corrected request can reuse the rejected call ID.

**Steps to reproduce**

1. Use the generated call_api tool contract to request a GET text window
with limitBytes 60000.
2. Read the semantic tool error. Before this fix, it contains only a
generic rejection.
3. Retry with limitBytes 16000. The corrected call must be admitted.

**Paperclip version or commit**

Reproduced on master 5739a53f5f.

**Deployment mode**

Built from source. This affects the native runner bridge.

## What Changed

- Add call_api to the existing provider-safe schema guidance path.
- Name the text-window byte range and pagination field.
- Exercise the actual generated production schema through the provider
bridge and its error result.
- Keep private values, unknown property names, authorization errors and
response-size limits unchanged.
- Document the response window and repair behavior.

## Verification

- Red: api_window_rejection_explains_limits_and_allows_corrected_call
failed on master because the provider error did not name
responseText.limitBytes.
- Green: the same regression passes with a corrected same-ID call,
unknown-key privacy checks and unchanged authorization rejection.
- Passed: the existing runner-api.test.ts suite, 1935 tests, including
server window validation before dispatch.
- Passed: all 394 Runner core Rust unit tests, cargo fmt --check and the
generated protocol manifest check. The focused test also passed after
extraction into its own Rust test module.
- Greptile: 5/5 with no actionable issues on the final head
95d65e1646.
- The first CI release-registry run found that a compile-time test
fixture was outside the release-cache input set. The fixture now reads
the same generated schema at test runtime. The Rust regression and all
10 runner-release-crate-cache tests pass after that repair.
- This pure error mapping adds no dependency calls, provider retries or
network work. No live provider or staging deployment was needed.
- Full current-head CI passed, including repository typecheck, tests,
build, Runner verification, canary and browser suites. At
95d65e1646 there are 56 successful and
four skipped checks. The separate Paperclip Review bot completed with a
neutral check and a 5/5 static assessment with no findings. It did not
run current-head Rust, full repository or live-provider tests; its older
local cache run is not counted as current-head test evidence. No check
remains pending or failed. No local full-suite or full-build pass is
claimed.

## Risks

- Feedback must not disclose submitted values. The regression checks
private values and unknown field names, a 512-byte bound and unchanged
generic authorization errors.
- Guidance names the current byte range. The regression uses the
generated production schema so a contract change must keep this repair
guidance accurate.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use and code execution.
The exact runtime model suffix and context window are not exposed to
this session.

## Checklist


- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 16:10:58 -05:00
DottaandPaperclip ac9459bae3 feat: configure company agent observability (#16874)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Companies use several agent harnesses and execution environments.
> - Operators need one place to select where native agent logs and
traces go.
> - An inference proxy would add a dependency to the agent request path.
> - This pull request supplies native OpenTelemetry settings to managed
Codex and Claude Code processes.
> - Company secrets protect destination credentials. Export failure does
not change the task result.

## Linked Issues or Issue Description

**Subsystem affected**

Company settings, shared contracts, database, server, adapters, and
runner.

**Problem or motivation**

An operator cannot configure a company destination for native agent logs
and traces. Manual harness configuration is hard to apply across local
and remote execution.

**Proposed solution**

Add one company destination: Braintrust or a custom OTLP HTTP/protobuf
endpoint. Apply a transient snapshot when execution preparation starts.
Keep credentials out of API reads, task environment manifests, recovery
files, and command arguments. Replace a warm process when its export
settings change and preserve its conversation.

**Alternatives considered**

Multiple destinations can use a user-operated collector for fan-out.
This change does not add a collector, an inference proxy, or transcript
scraping.

**Roadmap alignment**

This extends company settings, secret management, and support for
multiple harnesses. The maintainer requested this implementation.
Searches for observability and Braintrust found no duplicate company
destination feature. Related infrastructure tracing work in #16236 has a
separate content-free contract.

## What Changed

- Add strict schemas, revision checks, encrypted secret storage,
activity records, and board-only settings routes.
- Add explicit synthetic logs and traces tests with a bounded HTTP
request and sanitized results.
- Supply native Codex configuration and Claude Code environment values
through local and remote launch paths.
- Preserve Codex login refresh through the existing managed credential
link. Retain unsaved drafts across background reads. Require complete
custom header re-entry when the endpoint origin changes.
- Separate process export compatibility from conversation identity.
Isolate generated Codex configuration and preserve resumable sessions,
including remote home refresh after export changes.
- Advance the immutable Pi/Copilot source attestations for shared
environment and sidecar code changes. Keep their provider payloads
unchanged and retain prior identities for decoding.
- Redact destination credentials throughout launch diagnostics and HTTP
logs.
- Add the production settings form, Storybook states and journey,
documentation, and feature/access map entries.

## Verification

- Real managed local Codex 0.160.0 and Claude Code 2.1.286 tasks
exported to Braintrust. API readback and the Braintrust UI showed the
test records. A real remote Daytona Codex task exported through the
legacy `exec` path.
- Live tests exercised content capture off, export disabled, warm
conversation reuse, and a destination that accepted connections but
never replied. Agent work succeeded and export requests stopped at the
configured three-second timeout. The UI connection test returned “Test
payload accepted”; the saved API key stayed masked after reload.
- All current-head CI test lanes, typechecks, packaging/build checks,
and required aggregates passed on
`71e994b2be9c8fb6d6e938a4ad7cf4c95fdafe31` ([CI
run](https://github.com/paperclipai/paperclip/actions/runs/39319194318)).
Greptile completed on that exact commit at 5/5, with zero unresolved
review threads. The additional optional Paperclip Review check remains
queued waiting for its assigned agent.
- Local workspace typecheck and build passed. Focused verification
included 239 combined runner tests, 789 API/native-session tests, 107
Codex home/ACP/sandbox-site tests, 204 feature/privacy tests, and the
affected Rust suites. Migration, token, map, Storybook catalog, and
Storybook build checks passed during acceptance. These checks ran at the
relevant implementation or merge boundary; the current-head CI is the
complete final gate.
- Managed AI credential projections now receive enabled and disabled
company export settings; genuine caller-owned Codex homes remain
untouched. Two regressions reproduced the skip before the repair. All
276 engine/lifecycle tests and adapter-utils typecheck pass afterward.
The launched TOML retains provider/MCP settings, credential continuity,
and redaction.
- Settings saves, removal, and the real company-deletion owner acquire
secret mutation ownership before database locks. PostgreSQL NOWAIT
probes cover all three paths; concurrent save/rotation/removal/deletion
requests settle correctly. The affected suites passed 137 tests,
followed by all 32 service/connection cases after expanded deletion
coverage. Server and Codex adapter typechecks pass.
- Codex source profiles use the effective CLI argument list. A spawned
fixture CLI reproduced both ignored-argument failures; all three
precedence/fallback cases now pass.
- Real tar staging reproduced remote conversation loss in both API-key
and subscription modes before the repair. Both now pass: changing
managed settings preserves sessions, archives, native indexes, and
refreshed subscription credentials. A corrupt upload preserves the prior
config and conversation.
- Preserved failure evidence: initial CI caught stale Pi/Copilot source
attestations, a missing test-harness helper, and packaging fixture/probe
mismatches; those were corrected and covered by focused checks.
Superseded heads had intermittent attachment-composer timeouts despite
successful uploads; [the original trace and screenshot remain
available](https://github.com/paperclipai/paperclip/actions/runs/39309701089/artifacts/12215109203).
The same attachment case passed on the final head: [25/25 tests in shard
3](https://github.com/paperclipai/paperclip/actions/runs/39319194318/job/118288637051).
- A connection-fault fixture also exposed a stale pooled socket after
its hang case; closing fixture responses isolated scenarios and the full
affected suite passed.
- The broad local test run was not clean: database resource failures,
timeouts, an older cached module graph, and a stale optional-resource
manifest assumption were recorded. Focused checks passed after the
documented fixes. This does not establish a clean full local pass.
- Native remote Codex, remote Claude, and the full ACPX Codex bridge
remain unqualified. The direct Codex resume test does not establish full
bridge acceptance.

## Risks

- Native exporters perform network requests from each execution
environment. A server connection test does not prove remote
reachability.
- Prompts, assistant responses, and tool content are enabled by default
when supported. Native caps and harness-specific controls still apply.
- Caller-owned Codex homes are unsupported for automatic configuration
and remain untouched.
- Native harnesses and their tool processes can inspect export
credentials. The settings form and documentation advise using
ingestion-scoped credentials. Retained headers remain bound to their
saved scheme, host, and port; changing origin requires fresh values or
removal.
- Migration 0357 adds a company-scoped row and secret reference. It is
safe to reapply. Secret removal and company deletion use the existing
secret lifecycle.
- Slow or unavailable destinations must not block task settlement.
Export settings take effect at the next execution preparation boundary.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and
browser verification. The exact serving model ID and context window size
are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-19 15:36:04 -05:00
DottaandPaperclip 06d4fe3121 perf(runner): preload essential Claude task tools (#16885)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner exposes assigned tools to Claude through an authenticated
MCP bridge.
> - Claude can defer these tools and search for them before a simple
task can finish.
> - Title and terminal tools are common requirements for a task turn.
> - This pull request marks those three tools for immediate loading by
Claude.
> - The remaining tools keep the SDK deferral policy and the existing
access checks.

## Linked Issues or Issue Description

Refs #15993, #15994, #15997.

**What existing behavior does this improve?**
Claude Runner tool discovery during task execution.

**Current behavior**
Claude can use ToolSearch to discover the mandatory title and terminal
tools before it answers a simple task.

**Proposed behavior**
Expose `set_task_title`, `paperclip_finish`, and `paperclip_block` in
the first Claude request through per-tool `anthropic/alwaysLoad`
metadata. Keep other tools deferred under the SDK policy.

**Reason and benefit**
Remove an avoidable tool discovery step without changing the model,
effort, or authorization. Repeated product measurements will check the
latency benefit.

## What Changed

- Add closed metadata for the three essential tools only in Claude
runtime hosts.
- Keep incoming metadata discarded and private tools hidden. Keep other
providers unchanged.
- Test real bridge catalogs and provider routing. Check the pinned
Claude SDK request against a loopback fixture with no paid calls.
- Advance the pending Copilot source binding because it attests the
shared bridge file. Preserve historical profile readers and
qualification limits.

## Verification

- Focused bridge, admission, profile, and effort controls: 185 passed,
one skipped. Three provider-routing cases pass.
- Runner TypeScript compilation passes.
- The production SDK fixture loads exactly three essential tools with
the change and zero in the controlled baseline. The document tool stays
deferred.
- Six real API-key tasks used Opus 5.5 / High in alternating order A B B
A A B. Median first assistant receipt was 22.021 s baseline vs 17.060 s
candidate (22.5% lower). Median total was 24.119 s vs 19.150 s (20.6%
lower). ToolSearch was 3/3 baseline vs 0/3 candidate. All six tasks
saved a title and accepted finish. A separate candidate follow-up
resumed the same provider session and finished without ToolSearch.
- Median startup was 4.786 s baseline vs 5.381 s candidate. This change
does not improve startup. Three samples per version give directional
evidence only.
- Estimated cost for the six tasks was $0.850900800. Candidate total was
$0.450341800 vs baseline $0.400559000; the first candidate wrote a new
cache prefix. These rate-card estimates are not invoices.
- The benchmark used source `5aed3c6a083cf8e6246815455abde3b29ecbbbac`.
Rebuilding both bundles at master-reconciled head
`d2da07259048c0a2bebd210c35cc0ebb3ff42c67` produced identical SHA-256
values. Baseline bundle SHA-256:
`10a92c373bba4fb630bf4fefeab953d850a77cf8258bc2e94711410a73a78ecd`.
Candidate:
`40348fc67a3b1ae5cc1f27f933f369981d31bcdf5d1bdc7b1797968ddfe53938`.
Baseline differs only by compiling the Claude preload selector as false.
Fresh task sessions avoid checkpoint changes.
- Full local runtime-host runs exposed credential lease collisions in
existing cases. A later complete host run passed 67 cases and timed out
in an existing admission-abort case; that case passes in isolation. All
failures are retained. Focused controls pass. Complete Runner suites,
repository typecheck, tests, browser checks, and build pass in cloud CI
on this head.

## Risks

- These three tool schemas add input to Claude requests. Measurements
must include token usage and cost.
- Copilot source identity changes because it includes the bridge source
hash. It remains pending qualification. Its catalog and executable
closure do not change.
- The test fixture proves request shape. It does not prove real-provider
latency or platform package qualification.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact serving model ID and context window are not exposed
in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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 (focused controls and
isolated cancellation check; broad local failures are retained above)
- [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-10-19 14:29:22 -05:00
d747752496 fix(runner): record why an OpenCode turn fails when opencode serve stops (#16863)
When `opencode serve` stops during a turn, the OpenCode driver now fails the
active turn itself with a closed-vocabulary cause (server exit code or known
signal, allowlisted socket error code, HTTP status, or closed stream) instead
of leaving runnerd to close it with `error: null`. The proxy flushes stdout
before a fatal exit so the failed turn reaches runnerd, and the server records
OpenCode failed turns as `nativeTurnFailure` (live and persisted-recovery
paths) so the run-failure diagnostic names the cause. Provider text is never
copied. Run status, retries and recovery behaviour do not change.

Co-Authored-By: Paperclip Sentry triage <Paperclip-Paperclip@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 12:20:24 -07:00
DottaandPaperclip 8193abb936 feat(claude): default qualified macOS and Linux targets to Paperclip Runner (#15997)
## Thinking Path

> - Paperclip must run the selected agent on its selected host.
> - Claude needs verified packages for each supported target.
> - A Mac controller must select the correct Linux provider pack.
> - New defaults must follow package and execution evidence.
> - This PR adds Claude platform packaging and target-specific pack
selection.
> - Existing Codex Linux ARM64 behavior remains intact.

## Linked Issues or Issue Description

Refs #15683. This PR depends on #15993 and #15994. Related scope: #15422
and #15224.

## What Changed

- Reuse the merged four-target daemon producer/consumer matrix. Add
target-owned Linux provider packs and carry their immutable identities
through release assembly and vendoring.
- Reuse master’s landed pinned Claude SDK ARM64 executable admission and
retain package-integrity, architecture and no-follow admission.
- Select target-specific remote packs so Mac controllers can use Linux
hosts without a development pack override.
- Preserve read-only runtime context on SSH startup and resume without
accepting unverified old content.
- Check ordinary installed Claude readiness without injected package
authority. Retain Codex and Linux x64 consumer checks.
- Extend Claude automatic target selection for the remaining qualified
package targets. Retain unsupported-platform and external-override
behavior.
- Qualify managed Daytona snapshot names through provider IDs during
Claude Connect. Pin native acquisition to the measured ID. Preserve a
revocation marker after failed probes or target edits, and block native
acquisition until requalification instead of falling back to a mutable
name. Preserve immutable-image proof, company and account boundaries,
and Legacy acquisition.

## Verification

- Reconciled with master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb`
through the prerequisite stack, retaining the merged startup fix and
latest Codex Linux ARM64 behavior.
- [Four-target exact-source package
qualification](https://github.com/paperclipai/paperclip/actions/runs/39267321383)
passed on source `04e0202ca81387b17cbe7fd094a8338648356fe9`: all four
native builds, public-package assembly, Linux x64 verification and clean
installed consumers on Apple Silicon, Intel Mac and Linux ARM64. The
later master reconciliation adds shared OpenRouter attribution and
changes runtime source. This historical result keeps its original source
identity; [later
qualification](https://github.com/paperclipai/paperclip/actions/runs/39281100929)
passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. It predates the
subsequent TypeScript startup fix.
- Fresh local product acceptance on integrated source
`b2c9fe43f9cd3bc5dd9d22552da0148845ba71a4` completed a useful file and
follow-up through native Claude/Opus 5.5, High effort and the API-key
connection. Both actual browser downloads were independently checked;
the revision preserves the original body and session continuity. Total
task estimates: $0.518432800. Ordinary web and API creation saved
defaults with the native experiment disabled.
- Local focused verification passed 993 startup/session tests, 243 UI
tests, 12 workflow security tests, direct server/UI TypeScript checks,
and token/palette gates before the last review changes. Initial
DB-backed snapshot pin/revocation coverage passed 18 cases; the final
serial route suites pass 122 credential/permission and 232
snapshot/environment cases after correcting a test hook timeout.
Current-head cloud suites pass.
- Preserved the failed pre-provider local fixture and its full pending
reservation. The successful fixture has no unpriced or pending usage.
Historical failed Cloud journeys, accounting holds, source identities
and subscription limitations remain in the dated plan.
- All Docker/Rust release production was performed in cloud CI. No local
Docker image was built. An inadvertently invoked local Rust prerequisite
was stopped.
- Current-head cloud CI is green. All three stack PRs have fresh
Greptile 5/5 reviews and zero unresolved review threads. Required
typecheck, test and build gates ran in cloud CI; Docker work stayed
remote. Earlier failed checks remain in their original runs.

- The final master merge preserves task-loading, permission,
skill-retention and OpenRouter changes. Pi uses a fresh combined profile
27, preserving both historical profile-24 declarations; Copilot remains
profile 22. Focused protocol checks passed 155 cases (one skipped), the
updated Pi attestation check passed 18 (one skipped), and 91
evaluation/catalog checks passed.

- Latest-application manual continuation passed in 37.942 seconds on
`695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native
Opus 5.5, Anthropic API attribution, the same resumed Claude session, an
independently checked 635-byte file and persisted Done status. It uses
the earlier verified Mac daemon; the preceding-source package
qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That
package run predates the small TypeScript startup fix and is not
relabeled as qualification for it.
- Upgrade limitation: changed compiled sidecar identity rejected old
durable launch state and recovery hit session-open bounds before
eventually resuming. That attempt was operator-cancelled and retained;
the successful manual continuation does not qualify seamless upgrades.

- Local latency profile, Opus 5.5/High unchanged: three alternating
real-ACP loopback samples per variant reduce median provider-ready time
from 5.081s to 4.034s. The matched real API task startup improves from
5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s
because agent work varies. This establishes a startup saving of about
one second, not a consistent total-reply speedup. A real candidate
follow-up passed in 20.146s and resumed the same saved session. The
loopback fixture makes no external model requests; failed initial probes
remain retained.
- The startup change passes 107 focused runtime/effort/lease tests, 53
profile checks (one skipped), TypeScript checking and the
TypeScript-only runtime build. Native hire fixture checks pass 70 tests;
their first local run retained a socket-hangup failure and stale
OpenCode expectation, both accounted for before the passing rerun.
Broader required checks run in cloud CI.

## Risks

- **Experience needs improvement:** successful connection setup still
shows “Connection needs attention” because runtime checks are deferred.
Cold provider-pack upload took 122–126 seconds per run while the task
mainly showed “Thinking.” The tested Core-only preview excludes private
Cloud UI plugins; this is not full Cloud distribution or subscription
qualification. Desktop dark theme was tested; mobile and comprehensive
accessibility were not. The portable report validates, but gallery
interaction could not be inspected because host preview was queued.

- The optional supply-chain scan returned neutral/inconclusive because
GitHub Actions package coverage and infrastructure parsing are
unavailable. It is not counted as a successful supply-chain
qualification. Exact package, daemon and image integrity checks passed.
- A stale, missing or wrong-architecture pack must fail admission. It
must not change runner or target silently.
- Provider-pack source changes invalidate affected earlier execution
results. Existing unknown-cost and cleanup holds remain intact.
- Live subscription execution remains unverified under the API-key
qualification direction. Built-in authentication flows are retained.
ARM64 cloud-image production is deferred. Merge and production
deployment remain separate.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution and browser testing. The exact serving model ID and
context-window size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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
- [ ] Focused local tests and final cloud verification 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-10-19 14:17:24 -05:00
DottaandPaperclip 95672307f4 feat(runner): carry acknowledged Claude effort through native resume (#15994)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The native runner must carry each supported agent setting.
> - Claude effort must reach its ACP session before a prompt and after
resume.
> - Installed Claude setup must find the owning server package without a
qualification override.
> - This PR adds those shared contracts and preserves historical
readers.
> - The Claude default change can then use the same runner path.

## Linked Issues or Issue Description

Refs #15683. This prerequisite follows the actual Codex squash
`adb69e8f09852c772d9901ae270e5b2d66e39c77`. Consumers: #15993 and
#15997. Related scope: #15422, #13978 and #15224.

## What Changed

- Add native-input v9 for Claude effort. Preserve v1–v8 readers,
including v7 explicit home modes, v8 Muse, Dot and Grok Bot.
- Preserve prepared task input and constraints through the newer
contracts, including completion-only continuation without wrapping
compact model input again.
- Carry effort through daemon/sidecar admission; require provider
acknowledgment before prompting and after resume.
- Find installed server package authority through the verified canonical
layout. Retain package-integrity, digest, architecture and no-follow
checks.
- Return Claude startup cancellation promptly while retaining unfinished
settings writes and the lifetime lease through cleanup. Preserve merged
Codex close/cleanup behavior.
- Retain both independently authored historical Pi profile-24
declarations. Combined master/Claude source attestations use Pi profile
27; pending Copilot remains profile 22. This does not expand either
provider's qualification boundary.

- Avoid a spare verified executable snapshot when Claude effort control
reuses its initialized provider. Preserve cold-control snapshot renewal
and acknowledged effort.

## Verification

- Reconciled with master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb`,
retaining its task-loading, progress, skill-retention, permission and
OpenRouter changes.
- Final focused protocol/provider checks passed 155 tests (one skipped),
the updated Pi attestation check passed 18 (one skipped), and 91
evaluation/catalog checks passed. Generated TypeScript/Rust profile
checks and Rust formatting pass. The integrated consumer's
TypeScript-only runtime build also passes.
- Earlier branch checks passed 369 protocol tests (one skipped), 72
catalog checks and TypeScript checks/build; their source identities
remain historical. No Rust compilation or Docker build is needed locally
for this proof.
- Current-head cloud CI is green. All three stack PRs have fresh
Greptile 5/5 reviews and zero unresolved review threads. Required
typecheck, test and build gates ran in cloud CI; Docker work stayed
remote. Earlier failed checks remain in their original runs.
- [Earlier four-target package
qualification](https://github.com/paperclipai/paperclip/actions/runs/39267321383)
passed on source `04e0202ca81387b17cbe7fd094a8338648356fe9`; it is not
relabeled as proof for the final merge. Existing failures and
unknown-cost holds remain preserved.
- Current-head cloud CI is green. All three stack PRs have fresh
Greptile 5/5 reviews and zero unresolved review threads. Required
typecheck, test and build gates ran in cloud CI; Docker work stayed
remote. Earlier failed checks remain in their original runs.

- Latest-application manual continuation passed in 37.942 seconds on
`695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native
Opus 5.5, Anthropic API attribution, the same resumed Claude session, an
independently checked 635-byte file and persisted Done status. It uses
the earlier verified Mac daemon; the preceding-source package
qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That
package run predates the small TypeScript startup fix and is not
relabeled as qualification for it.
- Upgrade limitation: changed compiled sidecar identity rejected old
durable launch state and recovery hit session-open bounds before
eventually resuming. That attempt was operator-cancelled and retained;
the successful manual continuation does not qualify seamless upgrades.

- Local latency profile, Opus 5.5/High unchanged: three alternating
real-ACP loopback samples per variant reduce median provider-ready time
from 5.081s to 4.034s. The matched real API task startup improves from
5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s
because agent work varies. This establishes a startup saving of about
one second, not a consistent total-reply speedup. A real candidate
follow-up passed in 20.146s and resumed the same saved session. The
loopback fixture makes no external model requests; failed initial probes
remain retained.
- The startup change passes 107 focused runtime/effort/lease tests, 53
profile checks (one skipped), TypeScript checking and the
TypeScript-only runtime build. Native hire fixture checks pass 70 tests;
their first local run retained a socket-hangup failure and stale
OpenCode expectation, both accounted for before the passing rerun.
Broader required checks run in cloud CI.

## Risks

- Explicit Claude effort needs a daemon and sidecar that support input
v9. Historical readers stay available; downstream builders and
permission-pin transport checks must also use v9.
- Source-bound profile changes may require reopening older Pi/Copilot
sessions. Copilot remains pending and executable package closures remain
unchanged.
- This prerequisite changes shared runtime behavior; Claude default
selection remains in #15993/#15997. No database migration or Codex
default change is introduced.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution and browser testing. The exact serving model ID and
context-window size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-19 13:31:09 -05:00
DottaandPaperclip 985d3b12b6 fix(runner): explain rejected task monitor arguments (#16868)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use task monitors to resume work after a future check.
> - The runner rejects monitor arguments that fail the tool schema.
> - It returned a generic error with no field or repair guidance.
> - An agent could treat a repairable call as a scheduling outage and
block its task.
> - This pull request adds safe repair guidance and shows the nested
request shape.
> - Agents can correct the call and confirm a saved schedule before they
yield.

## Linked Issues or Issue Description

Refs: #15446, #16686.

**What happened?**

A rejected native `set_task_monitor` call returned `invalid_tool_call`
with only “Paperclip rejected this semantic tool call.” The agent could
not identify the invalid field. A retry could fail again and leave
unfinished work without a scheduled wake.

**Expected behavior**

Reject invalid arguments before any mutation. Give the provider bounded
schema locations and clear repair guidance. A corrected call must save a
monitor and allow one wake without duplicate effects.

**Steps to reproduce**

1. Call `set_task_monitor` with `idempotencyKey`, `nextCheckAt`, and
`notes` at the top level.
2. The schema rejects the call because scheduling fields belong inside
`monitor`.
3. Before this change, the provider received no guidance about the
required shape.

**Paperclip version or commit**

Reproduced against master `35c75b56d4` with a failing Rust regression.

**Deployment mode**

Source checkout. This affects the native runner tool bridge.

## What Changed

- Add monitor-specific repair guidance to the runner's existing safe
schema error path.
- Keep feedback within 512 bytes and omit submitted values and unknown
field names.
- Show the nested monitor request in the production tool description.
Refresh generated contracts and catalog identities.
- Test flat and nested invalid input, private value handling, and
unchanged authorization errors.
- Test rejection, correction with the same key, saved schedule and
audit, receipt replay, and one timer wake with real PostgreSQL and the
native tool authority.
- Update execution documentation and the task verification recipes.

## Verification

- Red/green: the Rust provider error regression failed on master because
monitor repair guidance was absent. It passed after the fix.
- Passed: 29 PostgreSQL monitor and scheduler integration tests. These
use the real tool authority and scheduler, with a no-op process agent
for wake delivery.
- Passed: the native Codex server vertical-slice test. It runs the
rebuilt Runner binary with a fake provider and checks durable results
and session resume.
- Passed: map structure checks, Rust formatting, and `git diff --check`.
- Passed locally: full repository `pnpm -r typecheck`, `pnpm build`, and
all 392 Rust library unit tests.
- Passed on commit `3b667ad24763c1828edd48f56ef7a10766aeb946`: [CI run
39290889768](https://github.com/paperclipai/paperclip/actions/runs/39290889768),
including all server, Runner, serialized, browser, typecheck, build, and
canary gates. Across the PR, 56 checks passed and four conditional
checks were skipped. No check remains pending or failed.
- Greptile: 5/5 on that exact commit. The check concluded success, with
no review comments or unresolved threads.
- The duplicate local `pnpm test:run` attempt did not complete. It was
stopped after the full CI suite passed; it is not counted as a local
full-suite pass.
- The first PostgreSQL attempt could not bind localhost inside the shell
sandbox. It passed with normal localhost access. The first broader Rust
attempt had 37 socket-permission failures and 355 passes; all 392 passed
with localhost access and no code change.
- Live model recovery was not run. Local execution policy did not
authorize an extra acceptance run through the signed-in provider
account. This PR does not include a deployment or recovery of an
existing task.

## Risks

- Error feedback must not reveal submitted values. Tests cover private
values, unknown keys, nested constraints, length bounds, and unchanged
generic authorization errors.
- This changes guidance only. It does not relax the schema, retry calls
automatically, or change scheduling authority.
- A new runner binary and refreshed provider contract must reach the
target instance before agents receive this guidance.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, and code execution. The
exact runtime suffix and context window size are not exposed in this
session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-19 12:37:28 -05:00
DottaandPaperclip 9179d8dcc3 fix: credit Paperclip for managed OpenRouter requests (#16850)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - AI connections choose credentials and routes independently of the
agent harness.
> - OpenRouter assigns app credit from the final request headers.
> - Harness defaults can assign Paperclip work to the underlying
harness.
> - This pull request applies one public Paperclip identity to managed
OpenRouter requests.
> - The benefit is consistent app credit across supported harnesses and
internal model calls.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

App attribution for existing OpenRouter connections and explicit
provider configurations.

**Current behavior**

Requests can omit attribution or carry the harness identity. Paperclip
does not receive consistent credit in OpenRouter rankings.

**Proposed behavior**

Use `https://paperclip.ing`, the title `Paperclip`, and the coding
categories `cloud-agent,programming-app` for managed requests to
OpenRouter. Keep credentials, routing, and unrelated providers intact.

**Reason and benefit**

The provider URL identifies the app across personal and shared API keys.
A search of public issues and pull requests found no duplicate
attribution work. This improves existing AI connections and does not add
a separate roadmap feature.

## What Changed

- Add a shared attribution policy and a parity-checked copy for the
standalone Runner.
- Apply it to managed Codex, Claude, OpenCode, and Hermes connections,
plus native Pi and explicit legacy provider configs.
- Preserve attribution across Codex config filtering, Claude environment
filtering, OpenCode proxy requests, and model-level overrides.
- Attribute direct fast-response and decision-model requests, including
custom connections to the OpenRouter endpoint.
- Add positive and negative regression tests and provider attribution
requirements to the connector playbook.
- Advance native Pi to profile 24, preserving historical identities and
binding the attribution source in its declaration and release checks.

## Verification

- Final head `6df282d2a58c2698e41127443903d6fc85b4b72f`: all CI/status
checks passed or were intentionally skipped; Greptile is **5/5**, with
zero unresolved review threads. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/39274938069).
- Focused server/shared/config suites: 132 tests passed before the final
edge-case additions. Expanded adapter suites pass 48 tests; the final
OpenCode merge passes 15 tests; global/EU/US endpoint and policy-parity
suites pass 26 tests.
- Focused Runner suites: 85 tests passed, including model overrides and
recovery/config boundaries. Profile installation/environment/config
tests subsequently passed 72 tests (one optional distribution test
skipped); historical decoding passed 11 tests and updated recovery
coverage passed 27 tests. The Rust profile admission test and all five
native Pi launch/recovery tests passed.
- All 114 managed AI connection tests pass together. They include
custom-header preservation for legacy and native Claude runs, both
OpenRouter and other gateways, inherited headers, and unresolved secret
references.
- Actual requests from installed Codex 0.160.0, Claude Code 2.1.245,
OpenCode 1.18.34, Pi 0.74.0 and 1.0.0, and the managed Hermes runtime
carried all four Paperclip headers. A local endpoint used dummy
credentials and returned an intentional 401 after capture. Codex and
Claude retry requests retained attribution. This proves outgoing header
precedence; it is not a successful model-inference test. The first
Claude capture had an argument-separation error and sent no request;
correcting the command produced the captured requests.
- A live request through `fastResponseModel` completed with `attribution
verified`. OpenRouter recorded generation
`gen-1792420273-Ez1GUTCc7YuZ1FJMCGob` under app ID `3118063`, at a cost
of $0.00000375. The public app record maps that ID to
`https://paperclip.ing/`.
- Full `pnpm -r typecheck` and `pnpm build` passed, including a repeat
after the review fixes. The final server build stamp records commit
`6df282d2a58c2698e41127443903d6fc85b4b72f`. `pnpm check:token-gates`
passed.
- CI first caught the stale Pi source attestation; it is now a new
immutable profile. Greptile caught custom-header loss, now fixed and
covered by the complete managed-connection suite. The next CI run caught
the missing Docker allowlist entry for profile 24; the allowlist and
release smoke pins are now synchronized. Local Docker verification
cannot run because its daemon socket is absent; The exact Docker context
check passed in CI on the final head.
- The initial local `pnpm test:run` did **not** pass. It ran across
source/build edits, reported chat/tool-access collection failures, three
workspace-runtime failures, two new managed-header failures, one Dot
Runner readiness failure, and two native-session-resume failures, and
was interrupted after the final-head CI server coverage passed. Its
secrets suite also reported 91 cases skipped. The isolated tool-access
suite passed all 428 tests, and the complete managed-connection suite
passed all 114 tests. These retries establish recovery, not the cause of
the original local failures; no claim of a successful full local run is
made. Final acceptance uses immutable final-head CI plus the focused
local and live checks above.
- Final-head CI encountered one unchanged UI assertion in
`FileViewerSheet.copy.test.tsx` (missing “Copied link” feedback after
clipboard completion). That shard passed on the earlier head with
identical UI code, and all six clipboard tests passed locally. A timing
race around the asynchronous React update is suspected but not
conclusively established. The single CI retry passed, with no
product/test code changed for it. The earlier failure remains part of
this verification record.

## Risks

- Native Pi profile 24 requires a fresh provider session when
encountering a profile 23 identity; recovery tests cover that boundary.
- Harness upgrades can change header precedence. The playbook requires
actual request capture when changing provider paths.
- Externally managed agents, unmanaged harness settings, and gateways
that replace headers need separate qualification. This change does not
intercept arbitrary model calls made by task scripts.
- The existing OpenRouter entry for the Paperclip URL still displays an
old title, “PrettyFly Opus Testing,” and no categories on the final
public-page recheck. The live request received credit under that URL's
app ID. Public title propagation and leaderboard placement remain
controlled by OpenRouter.
- Global, EU, and US OpenRouter hosts are recognized explicitly; other
subdomains are not treated as OpenRouter. No database migration,
credential ownership change, or Paperclip telemetry event is involved.
Attribution contains public product constants only.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository editing, shell
execution, web research, and live API verification. The exact deployment
identifier and context-window size are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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 — the focused suites listed
above; the unsuccessful full local attempt is explicitly recorded, with
full final-head coverage supplied by CI
- [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-10-19 10:28:53 -05:00
DottaandPaperclip 56e09cd19f docs: add native Runner integration playbook (#16846)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native Runner connects those agents to harnesses through provider
drivers.
> - Adding a harness crosses protocol, setup, lifecycle, packaging, and
product boundaries.
> - Existing guidance does not provide one complete procedure for this
work.
> - This pull request adds a native Runner skill, detailed playbook, and
working templates.
> - Contributors can use them to define a release, implement the
integration, and verify the delivered result.

## Linked Issues or Issue Description

**Issue type**

Missing documentation.

**Where is the issue?**

Native Runner contribution guidance in `doc/DEVELOPING.md` and
`packages/paperclip-runner/README.md`.

**What's wrong?**

Contributors must reconstruct the requirements, protocol mapping, normal
setup, lifecycle rules, packaging, and acceptance process when they add
a harness. The legacy direct-adapter recipe covers a different execution
path.

**Suggested fix**

Add a self-contained native Runner procedure. Include capability
research, a finite release contract, implementation boundaries,
reproducible tests, normal installation, and release evidence. State
each lesson directly so contributors need no private chats, tasks, or
evidence archives. The duplicate search found no existing playbook PR.

## What Changed

- Add `create-runner-adapter` for new native Runner harness
integrations.
- Add a detailed playbook based on the Pi, Cursor, and Copilot
integration lessons.
- Cover model and instruction admission, connection setup, rich events,
durable interactions, recovery, cancellation, packaging, and Product E2E
acceptance.
- Add templates for scope, capabilities, attempts, failures, jobs, and
release handoff.
- Link the procedure from the development guide and Runner README.
- Keep legacy adapters as a compatibility boundary.

## Verification

- `git diff origin/master --check` passed.
- `node scripts/validate-doc-links.mjs` passed from
`packages/paperclip-runner` and checked 53 documentation files.
- All 71 Markdown links in the new reusable files resolve to repository
paths or public provider documentation.
- Skill YAML, naming, description, and scaffold checks passed.
- A private-reference audit passed for the reusable skill, playbook, and
templates.
- The legacy direct-adapter skill matches the base version.
- Full local runtime checks were attempted with pnpm 9.15.4. `pnpm -r
typecheck` stopped because Node type definitions are missing. `pnpm
test:run` and `pnpm build` stopped because `cli/node_modules/tsx` is
missing. This checkout has no installed dependencies. These commands did
not establish runtime test or build results.
- Full remote CI passed on commit
`88b4fc4832d95807da1f5e48029a183b3dc62b6c`: build, typecheck, general
and serialized server tests, Runner checks, browser tests, and the
canary dry run. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39262297681).
- All 55 applicable checks passed. The two Storybook checks were skipped
for this change.
- Greptile gave the current commit 5/5. There are no review comments or
unresolved threads.

## Risks

Low risk. The procedure can drift as the Runner contracts and test entry
points change. It records its source baseline and tells contributors to
inspect current declarations. Historical lessons describe failure
patterns; they do not certify current binaries.

## Model Used

OpenAI Codex with `gpt-6-astra` and `gpt-6.1-sol`, both using xhigh
reasoning. Context-window sizes were not exposed. The models used
repository search, terminal tools, and file edits.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used, including available version and
capability details
- [x] I have checked ROADMAP.md and confirmed this documentation does
not duplicate planned core work
- [x] I have searched GitHub for duplicate or related PRs
- [x] I have described the issue in this PR using the documentation
issue template fields
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket or instance details
- [x] I have run the relevant local documentation checks; they pass.
Blocked runtime checks are recorded above
- [x] I have considered tests for this documentation-only change and
validated its links and skill metadata
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented the 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 merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 08:50:44 -05:00
DottaandPaperclip f3cd3f4ea8 fix(runner): require confirmed exit before remote replacement (#16835)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Remote runs need one runner to own their process identity and
listener.
> - A health request can fail while that runner continues to work.
> - The active monitor treated a failed request as a process exit.
> - Recovery could then launch another runner against the occupied
listener.
> - This pull request retries health reads and requires proof of exit
before replacement.
> - A brief outage can recover on the same runner without replaying
agent work.

## Linked Issues or Issue Description

Refs: #16341 adds remote recovery diagnostics. Refs: #16686 retries
verification when restoring a saved remote session. This change applies
the shared probe policy to active process supervision.

**What happened?**

The active remote monitor settled its completion promise after a
timed-out or rejected health request. The transport treated that result
as an exit and started process recovery. An existing runner could still
own the listener. Replacement then failed with
`runner_ingress_bind_conflict` until the reconnect deadline expired.
Missing or changed ownership markers also did not prove that the old
process had exited.

**Expected behavior**

Retry transient read failures on the same runner. Require a matching
ownership marker and proof of process exit before replacement. Preserve
uncertainty when identity or liveness cannot be verified.

**Steps to reproduce**

1. Start a remote runner and leave its listener alive.
2. Make one process-health request time out or reject.
3. Observe completion and the restart decision. Before this change, the
monitor settles while the process is alive, and the restart wrapper
permits another launch.

**Paperclip version or commit**

The defect was reproduced on master at `6e89919631`. The patch is based
on current master at `c6a0cf4bce`.

## What Changed

- Reuse the bounded read-only recovery probe for active supervision.
Retry up to three reads within 30 seconds.
- Check the saved process generation when available. Accept only the
specific process-not-running receipt as exit proof.
- Add an exit-confirmation contract to remote process handles. Require
it for restart and shutdown completion. Preserve the cause of
supervision errors.
- Test transient failures, exhausted retries, conflicting identities,
real listening processes, and an authenticated runner with a fake
provider. Keep confirmed-exit replacement covered.
- Document the recovery policy and coverage limits in the execution
contract and maps.

## Verification

- Red: the timeout and transport-error regressions failed before the
patch because completion settled while the runner was alive. The
restart-guard regression also failed because replacement was allowed.
- Green: 14 server supervision cases passed, including a real listening
process. All 120 shared control-plane tests passed. Focused Runner tests
passed for authenticated live-runner fault injection and confirmed-exit
replacement.
- Review regression: a replacement-health test first failed because its
error cause was lost. It passed after preserving the cause and detail.
The four affected transport cases and Runner typecheck then passed.
- `node scripts/check-maps.mjs` passed for 35 areas and 176 capability
IDs.
- `pnpm -r typecheck` and `pnpm build` passed locally. The sequential
local full-suite run was stopped before completion; no local full-suite
pass is claimed. Final commit `bcc1b1d339` passed the complete CI
matrix: 55 checks passed and two optional Storybook checks were skipped.
Greptile is 5/5 with no unresolved conversations. The PR has no merge
conflicts.
- The first real-listener attempt could not bind inside the execution
sandbox. The same test passed with local socket access. The first
package-test invocation used the root configuration and selected no
tests; the package configuration ran all selected tests.
- CI attempt 1: nine test jobs were cancelled together at 12:54:59 UTC.
Their test steps report cancellation. The build and uninterrupted jobs
passed. The interrupted jobs were retried once. That retry exposed one
confirmed-exit message assertion failure in the Runner shard; the other
jobs passed. The compatibility correction preserves the prior message.
The failing case and four recovery cases then passed locally. The
complete CI matrix passed after that correction.
- No live sandbox restoration, deployment, or historical task recovery
is claimed.

## Risks

- A persistent outage now ends supervision with explicit exit
uncertainty. It cannot authorize a competing process. Existing ownership
and workspace recovery checks remain required.
- Health reads can take up to 30 seconds before reporting an unavailable
runner. Retries are read-only and bounded.
- Local launchers keep their existing completion contract. No database
migration or public API change is required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and code
execution. The exact serving snapshot and context-window size are not
exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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-10-19 08:19:37 -05:00
DottaandPaperclip 3858d2341d fix(recovery): default saved-monitor waits and keep task recovery quiet (#16686)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - A task must keep a durable path to its next action.
> - A provider can save a task monitor, then fail to yield because it
omits internal continuation fields.
> - An interrupted provider-pack check can then be reported as permanent
artifact incompatibility.
> - The task asks its user to certify recovered workspace files, even
though this is an operator responsibility.
> - This pull request derives the saved monitor continuation, bounds
verification retries, and removes that task form.
> - Normal recovery stays quiet. Unresolved holds retain inspection and
the existing safety checks.

## Linked Issues or Issue Description

**What happened?**

A yielded completion without `continuation` is rejected even after the
provider saves an eligible monitor on the task. Repeated attempts cannot
finish. Remote verification also treats timeouts and missing exit status
as artifact incompatibility. The task recovery notice exposes raw
diagnostics and asks the task user to certify infrastructure files.

**Expected behavior**

Use current persisted task state to fill routine continuation fields.
Retry interrupted verification reads within a fixed bound. Keep normal
recovery in the working state. Show a compact notice only when work
cannot safely continue.

**Steps to reproduce**

1. Save an eligible monitor on the active task.
2. Call `paperclip_finish` with `reportedWorkDisposition: "yielded"` and
omit `continuation`.
3. Return a timed-out remote provider-pack command with empty stderr
during recovery. Inspect the resulting task notice.

**Paperclip version or commit**

Source baseline: `aaeff418cf` (master integrated with its current task
visibility and saved-source reconstruction rules).

Related changes: #15824, #16104, #16451, #16493, #16690. This fix
complements saved-result recovery and verified pack reuse. It does not
replace their workspace ownership checks.

## What Changed

- Allow omitted or null continuation at the provider input boundary.
Read current authorized task context and fill a monitor continuation
only for the bound run and an eligible saved monitor. Keep accepted
results strict. Apply this to Codex, OpenCode, both direct and
production-sidecar ACPX paths, and external drivers. Reserve the
semantic call identity during the saved-context read and reject
cancellation or a changed run/turn.
- Bind the shared completion change and continuation helper in a new
Copilot v21 source declaration. Preserve v20 history and its decoder
support. Qualification stays pending.
- Expose the eligible continuation in task context. Completion admission
still checks persisted monitor state. No schedule is created or renewed
by the default.
- Retry read-only provider verification at most twice per command. Hold
exhausted reads with a distinct verification-unavailable cause.
Reattachment cannot renew the read budget through an unchanged
provider-attempt counter. Keep completed verification failures and wrong
versions incompatible.
- Remove the task file-certification form. Hide the notice only for a
matching durable recovery path without an unknown-action replay hold.
Keep missed retries, unsafe outcomes, and unresolved file holds visible.
- Add production-component stories for automatic recovery, blocked and
expired holds, reader access, persisted repair decisions, source
reconstruction, queued continuation, and mobile. Preserve master’s
guarded saved-source reconstruction choice after confirmed source
destruction. Update the execution contract and access maps.

## Verification

- Completion, helper, Codex, OpenCode, ACPX, and profile regressions
pass. After the sidecar review fix, 271 tests across the production
sidecar and three provider suites pass, plus 72 helper/profile tests.
The real sidecar MCP bridge tests cover saved-monitor acceptance,
no-monitor refusal, cancellation, duplicate call identity, and
raw-versus-forwarded semantic receipt hashes. The OpenCode tests also
cover eligible-monitor acceptance and refusal without one.
- The fresh full native executor suite passes all 743 tests. Four
profile, installation-integrity, and ACPX driver suites pass all 168
tests. The earlier CI fingerprint failure required a new immutable
source declaration; its follow-up Docker failure required the matching
context allowlist entry. Both fixes are verified locally. Targeted
server monitor, tool authority, and provider verification suites pass.
The probe tests include a real timed-out subprocess, an unrelated
responsive timer, transport errors, and completed integrity rejections.
- All 90 tests in the merged task notice, reconstruction choice,
recovery display, and lineage suites pass. They cover reader access,
live/missed/mismatched recovery, unknown outcomes, saved messages, retry
refusal, and removal of the file form. Both review findings have
failing-baseline/passing-treatment regressions: identical polling across
retry expiry, and a failed refresh after cached running activity.
- Browser walkthrough passed for automatic recovery, unresolved details,
a 390px mobile story, and the merged saved-source reconstruction and
queued states. The reconstruction control starts disabled and normal
automatic recovery shows only Working. The stories use production
components and fixture API data. They do not prove live cloud recovery.
- Token gates, map checks, and Storybook catalog generation pass. The
exact Docker context integrity command passes locally after adding the
new build declaration to its allowlist.
- Workspace typecheck and build pass on the final source, including the
versioned identity update. The final server and UI guards pass their
focused tests, typechecks, builds, and token gates. The final standalone
Storybook builds. The saved-monitor default retains master’s stricter
child-task visibility filter. Re-review caught an additional
production-sidecar validator before forwarding; the fix now defaults at
that boundary and has passing regression controls. After preserving
master’s new reconstruction capability, 68 targeted reconstruction,
tool-authority, and provider-verification server tests pass. The
current-master integration at `2a80050a0d` has a fresh 5/5 review with
zero unresolved threads. Its complete CI matrix, including Runner tests,
is the merge acceptance record.
- On the final master integration, local typecheck, build, and all 90
recovery UI tests pass. A concurrent runner run hit five 5-second
sidecar startup timeouts; an isolated sidecar run passed 86 tests and
timed out in the unrelated unsupported-bootstrap case. Those local
deadline failures remain recorded; the canonical CI Runner lanes use
their normal deadlines and pass. The unsharded local full-suite attempt
did not complete. It spanned source edits; the fresh native executor run
above passes. An unrelated workspace fixture timed out once and then
failed to reserve 32 contiguous ports on this host. Its unchanged-base
control and CI server suite pass. Full-suite acceptance uses the fresh
latest-head CI matrix; this PR does not claim a passing unsharded local
run.

## Risks

The default applies only to an eligible persisted monitor. An explicit
invalid continuation still fails validation. The added read occurs only
when a yielded report omits its continuation. Admission rechecks current
state after that read.

An interrupted verification command can add one extra 30-second probe.
Completed rejections stay closed. These probes do not change the pack,
launch provider work, or replay external tools. Two inconclusive reads
hold the original run. They do not schedule another reattachment with an
unchanged provider-attempt counter.

This PR’s pending Copilot v21 declaration binds the changed shared
contract, resolver, direct driver, and production sidecar sources. The
previous v20 declaration is immutable and remains decodable, but launch
requires the new exact identity. Qualification remains pending.

Task users lose the file-certification form. Board-authorized
source-only repair remains available through the resolution API with the
original evidence and stop-receipt requirements. This branch does not
deploy or recover historical held runs.

> This is a bug fix and UI polish within existing recovery behavior.
ROADMAP.md was checked.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, xhigh reasoning, with tool use and code
execution. The host does not expose the context-window limit.

## 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 (changed-area suites; the
full local run limitation is recorded above)
- [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-10-18 21:43:15 -05:00
5623304586 test(runner): isolate provider fixture targets and executables (#16701)
Scope the existing Grok and Pi fixture callbacks to their declared Linux x64
target, and restore the original process descriptors after each callback.
Keep OpenCode executable mode changes inside test-owned temporary copies.

Adapt the two-file OpenCode fixture isolation from caniko's PR #14580,
commit f329db3d6f. Extend the same isolation
to the remaining per-turn reasoning fixture. Preserve every existing test
assertion, case, skip and budget without changing provider support or pins.

Co-Authored-By: Can H. Tartanoglu <gpg@rotas.mozmail.com>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 00:58:47 -05:00
DottaandPaperclip 39c345ec5c test(runner): bind Copilot pack fixture to a supported target (#16697)
Scope the Copilot candidate registry fixture to the supported Linux x64 target and restore both process property descriptors. Preserve every existing assertion and production provider pin. The five-case focused treatment and current PR CI passed; fresh review is 5/5.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 00:09:00 -05:00
Dotta cfa9dce295 refactor(runner): remove unreferenced Paperclip Runner test fixtures (#16543)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Paperclip Runner package keeps fake agent servers and versioned
profile identity declarations under `test/fixtures/` for its test
suites.
> - Five of those fixture files have no reference anywhere in the
repository: no test, script, generator, workflow step, or document loads
or spawns them.
> - Dead fixtures add maintenance cost and make the referenced sibling
fixtures harder to trust.
> - This pull request deletes only those five unreferenced fixture files
and adds an audit receipt with the reference evidence.
> - The benefit is a smaller test-fixture surface with zero loss of
executed coverage.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The test-suite hygiene of the Paperclip Runner package. The repository
keeps unused test-support files that no suite loads. This slows audits
and makes the referenced fixtures harder to trust.

**Subsystem affected**

`packages/paperclip-runner` test fixtures.

**Current behavior**

Five files under `packages/paperclip-runner/test/fixtures/` have zero
references anywhere in the repository:

- `fake-native-resume-codex-app-server.mjs` (277 LOC): an old fake codex
app-server for resume testing. Resume coverage now runs through
`fake-final-burst-codex-app-server.mjs` (used by
`server/src/services/native-runtime/native-session-resume.test.ts:287`)
and `fake-durable-codex-app-server.mjs` (used by
`packages/paperclip-runner/src/live/live-session.test.ts:2192`).
- `copilot-profile-v{3,4,5,6}-identity.json` (64 LOC total): orphaned
profile identity declarations. Copilot profile tests,
`native-backend-factory.test.ts`, and
`scripts/generate-acpx-profiles.mjs` reference only v7 through v19 by
literal path. No dynamic `copilot-profile-v${...}` path exists in the
repository (the only template-literal fixture path is
`test-fixtures/pi-acp/profile-v${version}-identity.json`).

**Proposed behavior**

Delete only the five unreferenced fixture files. Keep every referenced
fixture. Keep all registered test cases unchanged.

**Reason and benefit**

Smaller test-fixture surface: 341 test/support lines removed with zero
loss of executed coverage. The audit receipt
`doc/plans/2026-10-16-runner-dead-fixture-test-audit.md` records the
per-file reference evidence.

**Breaking changes**

None. No production code, no registered test case, and no test selection
path changes.

**Additional context**

A repository-wide `git grep` for each removed filename stem returns zero
external references across all tracked file types. The
`hashFiles('packages/paperclip-runner/test/fixtures/**')` occurrences in
the workflows are Rust cache-key inputs, not execution selectors;
deleting files only changes that cache hash.

## What Changed

- Deleted
`packages/paperclip-runner/test/fixtures/fake-native-resume-codex-app-server.mjs`.
- Deleted
`packages/paperclip-runner/test/fixtures/copilot-profile-v{3,4,5,6}-identity.json`.
- Added the audit receipt
`doc/plans/2026-10-16-runner-dead-fixture-test-audit.md` with per-file
reference evidence.
- 341 test/support lines removed. Zero production, documentation, or
registered test-case changes.

## Verification

- Repo-wide `git grep -i` for each removed filename stem
(`fake-native-resume`, `native-resume-codex`, `copilot-profile-v3` …
`copilot-profile-v6`) across all tracked file types returns zero
external references.
- Selection audit: `packages/paperclip-runner/vitest.config.ts` includes
only `src/**`, `devtools/**`, `examples/**`, and two named
`scripts/*.test.mjs`; the server project selects `server/src/**` and
`server/scripts/**`; the `test:typescript:prep` `node --test` list names
no fixture. No workflow executes anything under `test/fixtures/` — the
`pr-trusted.yml`/`release-verify.yml`
`hashFiles('packages/paperclip-runner/test/fixtures/**')` occurrences
are Rust cache-key inputs, not execution selectors.
- Rust tests use their own `fake-codex-app-server` binary in
`runner/crates/runner-core`, not these `.mjs` fixtures.
- Searched open and merged PRs for each filename: zero overlap (`gh
search prs`).
- Repo-wide `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build` were
not run this session: the removed files are unreferenced, absent from
every vitest/node-test include pattern, and excluded from all tsconfigs,
so no compiled or executed path changes. No runtime CI savings are
claimed.
- All Paperclip CI gates green on head `ce24ab3` (verified 2026-10-16
~09:00Z): every `ci /` shard (General tests, e2e shards, serialized
server suites, Verify Paperclip Runner rust/vitest/static, Build,
Typecheck + Release Registry, policy, Docker context integrity, Canary
Dry Run, gate), `review`, `Superagent Security Scan`, `Socket Security`
PR alerts + project report, and `Contributor trust` all pass; the only
skipped jobs are the Storybook deploy/visual-regression jobs, which are
not required for this change. Greptile Review: 5/5 confidence, "Low
impact", no actionable issues, last reviewed commit `ce24ab3`.

## Risks

Low risk. No executed coverage or selection path changes. The only side
effect is a one-time change to the `hashFiles` Rust cache key that lists
`test/fixtures/**`, which simply invalidates that cache on the next CI
run.

## Model Used

Zhipu `z-ai/glm-5.3` (GLM), served through OpenRouter, running as the
Paperclip Test Gardener agent. Context window size unavailable to the
agent. Capabilities used: shell tooling, git, GitHub CLI search, and
file inspection; no image or code execution capabilities were used.

## 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-10-17 21:18:11 -05:00
Nicky Leach 2723168083 test(runner): control the durable resume watchdog (#16623) 2026-10-17 01:26:01 -07:00
DottaandPaperclip 2cc7992369 Share the external Runner lifecycle and add strict Muse contracts (#16444)
Add the external Runner foundation with distinct Dot/Grok V6, canonical home-mode V7 and Muse V8 contracts.

Keep generated schemas and profiles synchronized. Bound default question-answer command IDs in a disjoint namespace while preserving existing IDs and durable replay. Preserve canonical migration history and add normally generated, replay-safe Muse schema milestones with literal preview-history fixtures.

Refs #16444.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 13:46:50 -05:00
Nicky LeachandPaperclip 6f8ad3d77b Add verified session-local stdio MCP transport to Runner (#16526)
## Thinking Path

> - Paperclip manages AI agent runs and their tool authority.
> - Runner supplies provider sessions with assigned MCP connections.
> - The current native connection binding supports an HTTP gateway only.
> - Execution hosts also have private local tools with stdio MCP
interfaces.
> - Those tools need session-local registration and safe concurrency.
> - This pull request adds verified local stdio assignments beside the
existing gateway.
> - Providers receive the existing tool schemas and image content.

## Linked Issues or Issue Description

**Problem or motivation**

Runner can supply a native provider session with an HTTP MCP gateway,
but cannot also assign a verified local stdio MCP server without
persistent provider configuration. Execution hosts need a session-local
transport for local MCP tools, coordination for calls sharing a
resource, and native schema/image delivery. The pinned native Codex
client drops MCP images when `structuredContent` is also present.

**Proposed solution**

Add general stdio MCP transport support using host-assigned executable
digests, arguments, environment and a private Unix socket identifying
the shared resource. Tool implementations supply their own schemas and
responses; Runner forwards their native MCP schemas and content.
Register the transport for the current provider session. Serialize calls
across processes, keep unknown outcomes fenced, and authorize assigned
native Codex tools without a new prompt while routing explicit tool
confirmations through existing PRP permission requests. Retain the HTTP
gateway and applicable permission policy.

**Alternatives considered**

Reimplementing tools or translating their actions into provider-specific
APIs would tie the transport to individual tool implementations. Global
provider config would leak session assignments. Shell commands alone do
not deliver native MCP images or preserve MCP approval requests.

**Roadmap alignment**

This completes the existing Runner transport boundary. Related: #10690
(operator config for the legacy ACPX engine), #11605 (gateway delivery
of installed stdio connections), #16486 (preconfigured provider homes).
This change assigns local tools on the execution host and leaves those
administration paths intact.

## What Changed

- Add reserved, verified stdio bindings for native Codex and through the
shared ACPX runtime. ACPX clients must support stdio MCP assignments.
Read-only sessions omit the binding. No home/project config is
rewritten.
- Run the backend with only its assigned environment through the
verified executable launch path.
- Serialize all calls sharing a private Unix socket across sessions.
Metadata remains responsive. Queued cancellation prevents execution;
active calls remain fenced until acknowledgement. Unknown outcomes
require a resource restart.
- Authorize host-assigned native Codex tools without a new per-call
prompt, matching existing execution-host shell utilities. Preserve
explicit tool deny/prompt rules. Route requested MCP tool confirmations
through one-time PRP approvals, bound to the active thread and turn.
Keep shell escalation disabled and existing tool deny rules effective.
ACPX adapters retain their applicable ACPX permission policy.
- Preserve schemas and image blocks. For native Codex 0.160/0.162,
retain structured metadata as MCP text on image-bearing results to avoid
the client's image-loss bug. ACPX adapters receive the original
response.
- Document transport authority, cancellation and recovery limits.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed with pnpm 9.15.4 and Rust
1.97.1 on macOS arm64.
- Before Apex, full `paperclip-runner-core` Rust tests passed. After the
fixes, all 379 library tests and eight subprocess tests using a generic
stdio MCP fixture pass. Those subprocess tests cover schema/image
passthrough, assigned-only environment, executable drift, call
serialization, cancellation and unknown outcomes. The native Codex suite
passed 91 tests with two intentionally ignored;
`receipt_limit_rejects_the_call_and_keeps_polling_when_interrupt_fails`
timed out waiting for `turn.interrupted`, including an isolated retry.
The unchanged pre-fix commit `80917b301a2309f7966a466cf0c198a2112be2d5`
reproduces the same timeout in isolation; this local native-suite run is
not claimed as fully passing.
- All 252 native controller tests pass against the final narrowed
approval branch. Focused TypeScript transport/permission suites passed
(298 tests); final binding, read-only host, policy and adapter checks
passed (105 tests).
- **Provider-client smoke coverage:** pinned Codex 0.160.0 through
native Runner and Claude SDK 0.3.286 used local stdio MCP servers and
loopback model API fixtures without live model credentials. These
clients define the smoke-test coverage; this is not an exhaustive
adapter compatibility test. Image responses reached the next model
request as typed image blocks. Native Codex checks also verified
unattended execution without approval requests, explicit per-tool prompt
denial without backend execution, disabled-tool rules, and stale-turn
approval rejection.
- Two Greptile concurrency findings were reproduced with failing
subprocess tests and fixed: pending cancellation under output
backpressure, and a ctime-based fence reset after chmod. Initial checks
exposed Codex CLI option-scope and key-quoting errors, which were
corrected. The existing ordinary elicitation regression also exposed an
overly broad request branch; the final branch handles explicit tool
approvals only.
- `pnpm test:run` was attempted. The broad local server suite hit
persistent embedded PostgreSQL startup failures and unrelated local Git
fixture failures; it was stopped with the failure log retained. Those
local results are not claimed as passing. Hosted Linux CI gates passed
on the reviewed runtime commit, as recorded below.
- First Apex review found three additional defects, now fixed with
regressions: keep the resource-lock socket snapshot instead of sampling
the socket twice; project native permission requests with durable
turn/item IDs while retaining provider IDs in details; validate provider
response conversion before marking a request as settling. The retry
regression failed before the fix. Focused Codex request/adapter checks
pass (23 tests), server permission projection passes (16 tests), and all
379 Runner library tests pass. The broader database-backed bridge suite
was attempted but its local PostgreSQL setup timed out; 29 tests did not
execute. This local failure is retained, not claimed as passing.
- Runtime acceptance before the documentation clarification, on
`bd4fccae001157beb5bc76ff17c1920a5db3105a`: standard Greptile 5/5, then
Apex 5/5 with no unresolved threads; all 60 checks complete successfully
or intentionally skip. Ten CI jobs were interrupted by the same runner
shutdown, including one stale job that required cancellation before
retry; the same-commit retry passed. Hosted Rust tests also pass,
including the native suite with the local baseline timeout noted above.
- `git diff --check`, map validation, and pre-push secret/PII scan
passed.

## Risks

- No live model account or deployment isolation qualification was run.
The loopback fixture proves the actual vendor-client request format, not
model interpretation.
- Stdio MCP support uses the current host-assignment contract: each
binding requires a verified executable and a private Unix socket
identifying the serialized resource. Other platforms retain the HTTP
path. No provider version was upgraded.
- A lost acknowledgement blocks subsequent calls until the host restarts
the assigned resource. Direct shell calls are outside this MCP fence and
retain the existing shell policy.
- Preconfigured Claude remains unattended and denies interactive
approval requests. Host assignment authorizes native Codex local tools;
it must be supplied only for sessions already authorized to use the
resource.

## Model Used

OpenAI Codex, GPT-6, with reasoning and repository/tool execution. The
session does not expose a more specific model identifier or
context-window size.

## 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-16 10:39:38 -07:00