Commit Graph
413 Commits
Author SHA1 Message Date
DottaandPaperclip 5bc8bef9f4 Merge verified sleep prerequisites into 03
Co-Authored-By: Paperclip <noreply@paperclip.ing>

* commit '98a68b492f933890da59e2ec2f9ddd31f997d5b5':
  Remove unused aggregate watchdog diagnostics
  test: settle delegated chat completion before plan assertions
  test: settle saved retry cleanup before idle assertion
  fix: wake retry scheduling only when retry state changes
2026-10-30 22:12:53 -05:00
Dotta 98a68b492f Merge verified sleep prerequisites into 01
Co-Authored-By: Paperclip <noreply@paperclip.ing>

* commit 'd287074fba0ab0365d61416dadc392cc3078eee5':
  Remove unused aggregate watchdog diagnostics
  test: settle delegated chat completion before plan assertions
  test: settle saved retry cleanup before idle assertion
  fix: wake retry scheduling only when retry state changes

# Conflicts:
#	server/src/services/heartbeat/retries.ts
#	server/src/services/native-runtime/native-provider-capacity-retry.ts
2026-10-30 22:12:53 -05:00
Dotta d287074fba Merge verified sleep prerequisites into 07
Co-Authored-By: Paperclip <noreply@paperclip.ing>

* commit '78bd3560a886c7fd3eea03baccb6cf49f6e8499a':
  Remove unused aggregate watchdog diagnostics
  test: settle delegated chat completion before plan assertions
  test: settle saved retry cleanup before idle assertion
  fix: wake retry scheduling only when retry state changes

# Conflicts:
#	server/src/services/heartbeat/retries.ts
2026-10-30 22:12:31 -05:00
DottaandPaperclip 822b173281 test: preserve retry producer boundaries in receipt recovery
Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix/sleep-forward-02b-security:
  fix: wake retry scheduling only when retry state changes
2026-10-30 21:51:11 -05:00
Dotta 63c922a193 Merge commit 'c2ff3eb92113fb16713b270e34932636956ff16b' into fix/sleep-forward-02b-security
* commit 'c2ff3eb92113fb16713b270e34932636956ff16b':
  fix: wake retry scheduling only when retry state changes
2026-10-30 21:50:49 -05:00
DottaandPaperclip c2ff3eb921 fix: wake retry scheduling only when retry state changes
Separate retry-schedule notifications from ordinary queued-run eligibility. Preserve exact deadlines and prove native producer commit/rollback behavior without global retry scans on ordinary agent or issue edits.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 21:49:38 -05:00
DottaandPaperclip 40bd4df17b merge: preserve routine projections across retained execution producers
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:26:14 -05:00
DottaandPaperclip 688f35763d merge: preserve attention, status-card and recovery source ownership
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:25:15 -05:00
DottaandPaperclip 9b4beff72b merge: preserve status-card and recovery producers in the review stack
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:24:40 -05:00
DottaandPaperclip 290d12cf4b merge: rehearse issue-recovery predecessor for saved receipts
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:24:05 -05:00
DottaandPaperclip dee5296b8a merge: rehearse current dispatch predecessor for issue recovery
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:23:55 -05:00
DottaandPaperclip fcc107739c merge: rehearse current master and UI prerequisite for dispatch
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 20:23:37 -05:00
DottaandPaperclip ac6c5191ee Drive saved execution receipts from committed work and deadlines
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 19:22:39 -05:00
Dotta 4ef018cfe6 test: model retention reads in native cleanup transaction fixture 2026-10-30 19:17:14 -05:00
Dotta 0fe6e038c2 Restore independent recovery duties and bound committed-source work 2026-10-30 18:58:39 -05:00
Nicky Leach 9e904ee519 perf(server): overlap independent heartbeat preparation reads (#18372) 2026-10-30 16:49:20 -07:00
Dotta ab5108611d Run recovery producer acceptance on isolated PostgreSQL fixtures 2026-10-30 18:15:23 -05:00
Dotta dc4456c76b Drive issue recovery from scoped source writes and saved deadlines 2026-10-30 18:10:00 -05:00
DottaandPaperclip 0fac69e167 fix(server): scope run retention hints to affected companies
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:27:26 -05:00
Dotta d334f59c98 Merge remote-tracking branch 'origin/master' into codex/sleep-status-card-evaluation
* origin/master:
  fix(evals): support official TestOps job metadata (#18385)
  fix(config): require shared storage for managed cloud (#18350)
  feat(skills): make managed content independent of web-server disk (#18334)
  Add a portable agent question and answer resumption journey (#18346)
  fix(ci): isolate test selection and require current CI CODEOWNERS (#18376)
  fix(evals): capture TestOps registration after watch (#18375)
  fix(runner): allow session reset after confirmed task retirement (#18373)
  fix(evals): batch task search result readback across renders (#18370)
  fix(ui): keep task plugin views available for manual access (#18363)
  test: wait for the evidence expiry worker to settle (#18241)

# Conflicts:
#	server/src/services/company-skills.ts
#	server/src/services/native-runtime/paperclip-runner-tool-authority.ts
2026-10-30 17:25:31 -05:00
DottaandPaperclip 46f2c0bb9a fix(server): bound and scope routine projection recovery
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:25:24 -05:00
DottaandPaperclip 4af412eaea refactor: drive status-card evaluation from committed work
Move generation sequencing into a feature-owned deadline worker and retain persisted evaluation, eligibility and relative-search obligations. Add transactional producer hints and initial PostgreSQL acceptance coverage; follow-up completes the producer audit and remaining lifecycle gates.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:25:18 -05:00
Dotta 043fc50acf Merge remote-tracking branch 'origin/master' into codex/sleep-routine-status
* origin/master:
  fix(evals): support official TestOps job metadata (#18385)
  fix(config): require shared storage for managed cloud (#18350)
  feat(skills): make managed content independent of web-server disk (#18334)
  Add a portable agent question and answer resumption journey (#18346)
  fix(ci): isolate test selection and require current CI CODEOWNERS (#18376)
  fix(evals): capture TestOps registration after watch (#18375)
  fix(runner): allow session reset after confirmed task retirement (#18373)
  fix(evals): batch task search result readback across renders (#18370)
  fix(ui): keep task plugin views available for manual access (#18363)
  test: wait for the evidence expiry worker to settle (#18241)
2026-10-30 17:18:13 -05:00
DottaandPaperclip 2955e0e22e fix(server): scope run retention hints to affected companies
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:06:46 -05:00
DottaandPaperclip 15cc12dba6 fix(heartbeat): scope and batch dispatch wakeups by owner
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:06:23 -05:00
DottaandPaperclip b1104c6dd7 fix(server): scope run retention hints to affected companies
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:04:31 -05:00
DottaandPaperclip 0f3017c96d perf(server): archive attention from source deadlines
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 16:44:21 -05:00
Dotta b57f5e5869 Merge remote-tracking branch 'origin/master' into codex/sleep-run-task-recovery
* origin/master:
  fix(config): require shared storage for managed cloud (#18350)
  feat(skills): make managed content independent of web-server disk (#18334)
  Add a portable agent question and answer resumption journey (#18346)
  fix(ci): isolate test selection and require current CI CODEOWNERS (#18376)
  fix(evals): capture TestOps registration after watch (#18375)
  fix(runner): allow session reset after confirmed task retirement (#18373)
  fix(evals): batch task search result readback across renders (#18370)
  fix(ui): keep task plugin views available for manual access (#18363)
  test: wait for the evidence expiry worker to settle (#18241)
2026-10-30 16:36:30 -05:00
DottaandPaperclip 0e15c92073 feat(skills): make managed content independent of web-server disk (#18334)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use installed skills and exact version pins during execution.
> - Managed skills still depended on mutable directories on the web
server.
> - A replacement server could lose acknowledged edits or remove an
unassigned skill whose directory was absent.
> - This pull request makes immutable versions the authority for managed
content and installed repository reads.
> - The server can rebuild delivery files from durable content after
replacement.
> - This establishes skills readiness for ephemeral web servers. General
server draining and workspace recovery remain separate work.

## Linked Issues or Issue Description

**Subsystem affected**

Skills services, shared contracts, database receipts, Skill Studio, and
runtime delivery.

**Problem or motivation**

A fresh web server must discover, read, edit, and deliver protected
installed skills using the same database, object storage, secrets, and
supported application artifacts. It must not need its predecessor's
files or process memory.

**Proposed solution**

Use `managed` ownership with a null source locator. Read installed
content by immutable version. Prepare packages before a short
publication transaction. Persist execution selections before
materialization. Recover exact pinned runtime assets and reject deletion
while active or recovering pins exist.

**Alternatives considered**

Reconstructing a mutable installed directory preserves the old
source-of-truth ambiguity. Permanent dual writes create two competing
authorities. This change uses one managed model after a bounded legacy
conversion.

**Roadmap alignment**

This improves the existing Skills Manager, Studio, version history, and
Cloud execution capabilities. The maintainer supplied the implementation
contract. This does not add a separate skills product or deploy fleet
changes.

Related work: #18082 supplies immutable package storage. #17273
addresses edits outside the API for linked local skills; this PR keeps
that source category separate. #2648 is a closed earlier
ephemeral-filesystem proposal.

## What Changed

- Add managed ownership and focused content publication and execution
materialization modules. Keep the archive format and package storage
tables.
- Publish managed create, save, delete, fork, rename, restore, and
catalog content with version checks. Add durable create receipts.
Preserve file-save receipt responses.
- Return file version identities. Keep Studio drafts after a conflict
and provide an explicit reload action. A delayed reload cannot overwrite
newer typing or navigation.
- Persist exact runtime selections, including empty selections. Rebuild
pinned assets and verify their admitted digests on a replacement server.
- Preserve source access on forks and disconnected copies. Keep the
existing workspace policy category for managed skills.
- Add bounded conversion, eligibility, and independent verification
phases. Load persisted Cloud configuration in the standalone CLI without
seeding or changing it. Reject partial current versions against
installed inventories; recover only complete saved content or the exact
source. Document storage migration blockers and the compatible rollback
floor.
- Add separate-process PostgreSQL/S3 qualification and update domain,
retention, policy, and UI regressions.
- Pass the plugin worker manager into Studio execution, admit restricted
`skill_test` mode through native Runner contracts, and preserve admitted
scope across native and REST tools. Native tests cannot create ordinary
tasks, browse company data, or use external tools.
- Select the exact durable Studio revision even when unassigned or Beta
skills is off. Persist Studio output and audit atomically with native
task completion, preserving the result on replay.

## Verification

- Final revision `13e8af480b88ba6fea5737bac4bd81104d604792` passed full
CI: all 49 workflow jobs completed successfully ([run
41127396098](https://github.com/paperclipai/paperclip/actions/runs/41127396098)).
This includes typecheck, test suites, Runner checks, browser checks and
build. Greptile review 15 is 5/5 on that same revision, with zero
unresolved threads. The PR is ready for review.
- Local workspace typecheck and build passed after integrating master.
Focused checks passed: 33 execution/completion cases, 52 Runner HTTP
cases, 16 managed-content cases, 17 Studio cases, the new real-process
CLI regression, map checks and UI token gates. The CLI regression proves
inspection does not seed missing Cloud configuration. Server typecheck
passed after that fix.
- The independent-process PostgreSQL/S3 matrix passed through normal
HTTP skill routes. It covers A → B → C replacement, lost commit
responses, upload crashes, concurrent saves, binary contents and
executable delivery. Metadata listing and warm selected delivery retain
zero object downloads. Local timing measurements are recorded; they do
not establish hosted latency.
- Hosted A → B → C passed on the owned disposable test tenant with
external Postgres, S3 and a real remote Paperclip Computer. Predecessor
temporary homes were absent. C read and executed B's acknowledged
managed save. New runs used repository v1 while v2 was installed. Hashes
matched an independently checked exact upstream commit.
- Compatible image rollback to `6518b323` passed. Studio retained the
unassigned fork's C save. A fresh remote run executed the newer managed
content and historical repository pin. The actual shell event confirmed
expected hashes, stdout, exit 0 and mode 0555.
- Runtime candidate `9200e3fcb4` deployed successfully ([Cloud run
41124147876](https://github.com/paperclipai/paperclip-cloud/actions/runs/41124147876)).
The final Studio test delivered only the unassigned fork's exact v3,
executed its script and persisted a successful output snapshot.
Independent command-event inspection confirmed all three hashes, stdout,
exit 0 and mode 0555. All 14 installations were version-backed.
Independent verification checked all 25 versions: 23 remote objects, two
bundled database snapshots, zero blockers.
- The deployed image is `9200e3fcb4`. Later master integration, the
client-only delayed-reload draft guard and the CLI bootstrap have
separate automated proof. The CLI bootstrap was also exercised against
the tenant's stored configuration and storage through the same read-only
services. This PR does not claim that the deployed image is the final PR
revision.
- Live Studio checks exposed worker wiring, admission, access scope,
exact selection and completion-publication gaps. They are fixed. Failed
attempts remain in the evidence. The full local suite exceeded 80
minutes under host contention and was stopped. Later combined/isolated
local attempts also timed out; they are not counted as passes. Full CI
covers the integrated suites. Earlier CI found an obsolete restart-scope
fixture, which was corrected and passed all 52 HTTP cases.
- Reproduction and migration:
[`doc/skill-ephemeral-web-servers.md`](doc/skill-ephemeral-web-servers.md).
Source revisions, deployments, versions, run IDs, hashes and failure
history:
[`doc/plans/2026-10-30-ephemeral-web-skills.md`](doc/plans/2026-10-30-ephemeral-web-skills.md).

## Risks

- Legacy conversion requires stopped admission and retired
filesystem-authoritative writers. Pre-conversion binaries are not
supported rollback targets afterward.
- Cloud readiness requires remote object storage. Local provider
receipts and provider mismatches remain blockers until objects are
copied and verified.
- Linked local sources retain filesystem semantics and are outside the
cloud guarantee.
- Cold reads still fetch the existing archive format. Warm runtime
preparation retains the verified-cache path.
- Bundled reconciliation preserves an installed head. Existing release
snapshots remain selectable. An older server must not replace a newer
head with its shipped files.
- No production volumes, fleet defaults, or general deployment
coordination change in this PR.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser use. The exact backend model ID and
context-window size are not exposed in this session. No subagents 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
- [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-30 16:18:27 -05:00
DottaandPaperclip dd49318d55 fix(server): settle routine status from committed work
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 16:01:08 -05:00
Nicky LeachandPaperclip 6174b4d7c8 fix(runner): allow session reset after confirmed task retirement (#18373)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native warm sessions retain a Runner owner between turns.
> - Closing that owner must stop execution and preserve valid recovery
state.
> - A failed suspension can leave a rejected close promise after the
task has stopped.
> - A session reset then retries that same promise and blocks every
fresh session.
> - This PR separates task retirement proof from checkpoint reuse for a
new session.
> - A reset can proceed after exact stop proof, completed handoff, and
file collection.

## Linked Issues or Issue Description

Refs #18011. That change preserves checkpoint authority during warm
preparation. This change handles a stopped owner whose checkpoint cannot
be reused. Related: #14695 covers managed files retained with warm
processes. A search found no duplicate stopped-owner reset fix.

**What happened?**

A warm Runner can stop and complete its task handoff while close reports
`runner did not durably suspend before checkpoint`. The transport caches
that rejected close promise. Core retains the warm owner. Each session
reset retries the same promise before it can launch a provider. A
controller restart clears the in-memory owner and permits recovery.

**Expected behavior**

A reset to a new normalized session should release the old owner when
its exact task has proved that execution stopped and its handoff
completed. Core must collect stopped instruction files before it admits
the new session. An unconfirmed owner must continue to block
replacement.

**Steps to reproduce**

1. Complete a warm native run through a plugin task provider.
2. Change configuration so Core retires the warm owner.
3. Let the task stop and complete, but fail durable suspension proof.
Close keeps its rejected promise.
4. Reset the session and start another run on the same task environment.
5. Observe the old close error before any new provider work starts.

## What Changed

- Keep a lease-bound retirement receipt in the plugin task owner. It
requires `executionStopped: true` and successful task completion after
credential handoff.
- Accept an unrecoverable suspension error only during retirement for a
different normalized session, with that exact owner's receipt and
settled Core tool results.
- Collect stopped instruction files before releasing the warm owner.
Preserve old checkpoint evidence.
- Keep same-session, active-owner, incomplete-handoff, unrelated-owner,
unresolved Core tool results, and other close-error fences.
- Report Core tool settlement on the close error after ingress
retirement and drain. Default missing proof to false. Expose the error
through the server's Runner shim. Add regression tests and document the
recovery boundary.

## Verification

- The reset regression fails with the new handling disabled and passes
with it enabled.
- Both affected suites passed: 1,032 tests. The final 15 focused
owner/reset cases pass after adding the tool-settlement guard.
- The assembled regression uses the real task-owner and backend binding.
Its controlled task provider proves stop and completion. Close returns
the same rejected promise on every call.
- Negative cases cover incomplete handoff, other close errors,
same-session continuation, provider change with the same session ID,
unrelated receipts, unresolved Core tool results, and failed file
collection. Collection can later succeed without replaying stop or
reading the old checkpoint.
- Five real-process transport cases pass. They cover an insufficient
suspension deadline, the cached rejected promise, late tool completion
within and beyond the deadline, interruption, and result-persistence
failure. Unsettled callbacks produce `semanticToolsSettled: false`.
- `pnpm -r typecheck` passed with the repository's pinned Rust toolchain
on PATH. After the final contract change, Runner TypeScript build and
server `tsc --noEmit` passed.
- The local full-suite run was stopped at the requester's direction.
Full regression and build coverage are delegated to GitHub CI.
- Full GitHub CI passed on `ef0040d80af679ce6d4a130468e15f75678c1f4c`.
Standard Greptile reviewed the same commit: 5/5, zero comments. Apex
then reviewed that same commit: 5/5, zero comments. Final checks confirm
no unresolved review threads and no merge conflicts.
- Initial full CI on `00c002fd5a` failed one scheduled-retry route test
at 18/20 cancellations. Controlled cancellation latency reproduced the
short poll-budget failure. Before the next cycle, master advanced with
#18322, which coordinates that test at the first completed batch. The
separate local timeout commit was dropped during rebase. The upstream
test passes locally. The rebased run passed 46 targeted owner/reset and
scheduled-retry route cases. This PR has no scheduled-retry source or
test diff.
- No deployed provider run or tenant rollout is claimed by these source
tests.

## Risks

The exception applies only to a new normalized session and an exact
completed plugin task. The old checkpoint remains evidence and cannot
authorize reuse through this path. The original suspension failure can
remain visible on its run. This fix prevents repeated startup failures
after a reset; it does not hide unconfirmed cleanup or make every
suspension succeed. Missing task receipts and failed file collection
continue to block replacement. No schema migration, plugin protocol
change, Rust Runner binary change, or new polling is required. Tests use
a controlled task boundary; they do not certify every external provider
implementation.

## Model Used

OpenAI Codex, GPT-6 family, with tool use and local code 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 references)
- [x] My branch name describes the change and contains no internal issue
or instance 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] Greptile Apex is 5/5 with no unresolved findings
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 13:57:12 -07:00
DottaandPaperclip 294d8ca1c2 perf(heartbeat): schedule retry promotion from durable deadlines
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 15:53:26 -05:00
DottaandPaperclip f53db0c70f perf(server): overlap OpenCode setup and trace reply recovery (#18367)
Overlap eligible OpenCode GitHub and assigned MCP preparation. Trace deferred reply discovery and recovery, and forward the native GitHub transport recorder.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 15:21:05 -05:00
DottaandPaperclip 9f524ec1a7 fix: persist native Runner usage before transport acknowledgement (#18354)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent execution must preserve usage so Paperclip can price work and
enforce budgets.
> - Remote Runner execution can outlive its web receiver.
> - The receiver previously acknowledged Runner events before its later
usage recorder saved the accounting receipt.
> - This pull request saves required native usage receipts before that
transport acknowledgement.
> - A replacement receiver can accept the same retained report and
create one ledger charge.

## Linked Issues or Issue Description

**What happened?**

Native remote Runner usage could leave its durable outbox before the web
receiver saved its accounting receipt. The later recorder required a
local receipt directory. A replacement web receiver could lose the only
remaining report when the database write failed.

**Expected behavior**

The Runner retains unaccepted structured usage. Postgres owns accepted
receipts. Repeated delivery preserves one receipt for each source report
and one charge for the run. Missing usage keeps accounting pending.

**Steps to reproduce**

1. Start a supported built-in native remote Runner.
2. Make the receipt database insert fail after the provider reports
usage.
3. Replace the web receiver and its local directory.
4. Reconnect the same Runner and inspect the saved receipt and ledger.

**Paperclip version or commit**

The initial investigation used
`ebd05e9f4c88c66af7473db86bbaacfd1544aa0a`.

**Deployment mode**

A web server with a remote native Runner and shared Postgres.

Related work: #18327 owns output logs and provider traces. This change
has no dependency on its S3 export path. #18031 covers interrupted Codex
receipt recovery. #18005 covers legacy spool reads. #17516 covers Codex
stop-boundary retention.

## What Changed

- Add native producer receipt delivery through the existing Runner
callback before transport acknowledgement.
- Reuse `run_usage_receipts`, stable source sequences, and deterministic
report identities. Reject conflicting replay and retry a lost commit
response with the same receipt.
- Restore per-turn usage from structured receipt facts. Preserve
provider turns that share one PRP envelope turn.
- Bind retained warm transport callbacks to the current run authority
epoch, allowing old attachment control acknowledgements while preserving
accounting ownership.
- Persist Codex session baselines and cumulative totals in the existing
provider checkpoint. Mark qualified whole-run deltas, preserve them
across resume/restart/attachment, and leave old unmarked reports
incomplete and unpriced.
- Normalize the bounded final usage tail before the terminal event.
Retain later increases for explicit reconciliation, block further
attachment, and fail an affected successor without changing its
baseline.
- Complete runs from the accepted immutable receipt and its exact saved
rate-card amount; preserve existing live-budget enforcement.
- Skip the local receipt recorder for supported built-in native remote
Runner execution. Keep local, legacy, and external Dot/Muse behavior
unchanged.
- Keep pricing, reservations, ledger settlement, source fencing, and
budget holds with their existing owners.
- Put the actual Runner integration test in the existing Rust-cached
native test lane. Build before opening Postgres and give cold
compilation its own bounded budget.

## Verification

- Fresh Greptile review is 5/5 on
`e7376a50c8162770da1d581ecf25c8cffac64520`, with no unresolved findings.
Parent and independent peer review approved the final changes.
- Real PostgreSQL 18.6 and a real Rust Runner exercise failed receipt
insertion, receiver-directory loss, replay from the same producer, and
exactly one 25-cent ledger charge. The actual accounting spool path
stays absent. Optional logs/traces are disabled. The provider is
controlled; no paid request is made and the fixture never pre-saves the
expected receipt.
- Producer checks passed 32 usage/provider tests,37 terminal controls,
corrected completion, all 3 previously failing exit cases, and both full
transport goal-continuation cases. Rejected active-goal completion
retains its 120-token tail before failure. Baseline 100→successor150→33
duplicate old snapshots→old120 retains explicit incomplete
reconciliation evidence and positive budget exposure.
- Heartbeat executor checks passed 982/982. PostgreSQL tests preserve
exact 1.002 USD pricing, the 100.2-cent ledger amount, budget holds,
source takeover, partial/final receipts, cost-only corrections, equal
rate-card replay, and stale-completion interleaving. Newer incomplete
usage remains pending rather than settling an older snapshot.
- Runtime replay and strict usage-schema checks passed 2/2; generated
contracts and Rust formatting pass. Test-partition contracts passed
32/32.
- [Final combined-head
evidence](https://github.com/paperclipai/paperclip/pull/18354#issuecomment-6531526158)
records full workspace typecheck/build and 41/41 accounting tests
against all five cloud PR heads, including this final accounting commit.
It includes commands and evidence limits.
- Exact-head CI is green: 53successful checks, 6intentional skips, and
the legacy Snyk status passed. Typecheck, build, Runner, server,
browser, and aggregate gates pass. Runner Vitest1/2 initially failed an
unchanged mocked Antigravity login fixture; its focused case passed
locally, then one unchanged job retry passed 131 files/1995 tests,
including all 11 Antigravity tests. The initial failed attempt remains
recorded in CI.

Initial local attempts exposed the host SysV semaphore limit and
corrected harness path, IPC readiness, and queue-counter defects. A
temporary test loader selected an existing POSIX-semaphore PostgreSQL
18.6 build without changing repository dependencies. An optional
expanded debug provider run was interrupted at its unrelated 8192-turn
rollover stress case; no full-file local pass is claimed. Required
failure cases were run directly, and the full Runner CI remains
required.

## Risks

- The guarantee covers built-in native remote Runner execution. Local
native execution, legacy adapters, external Dot/Muse execution, and
server-originated model calls retain their existing contracts.
- This does not provide traffic switching or general web-server
failover. The existing controller identity, checkpoint, and generation
gates still apply.
- The receipt JSON gains optional structured producer facts. No schema
migration or accounting S3 spool is added. Text output and raw trace
payloads are excluded.
- Codex accounting authority requires a Runner artifact built from this
provider baseline implementation and qualified by digest. Update
receivers and strict usage-schema readers before releasing that Runner;
PRP does not negotiate this payload field. Existing unmarked Codex
reports remain pending/unpriced. No deployed Runner artifact is claimed
fixed.
- Usage arriving beyond the bounded terminal tail may require manual
reconciliation or a fresh session. Its evidence remains in the existing
producer checkpoint/outbox; no adjustment ledger or recurring scan is
added.

## Model Used

OpenAI `gpt-6.1-sol` assisted with the implementation, tests, and
documentation through code execution and repository tools. The context
window size is unavailable.

## 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-30 15:20:42 -05:00
DottaandPaperclip dbff3747b8 feat(server): persist run logs and provider traces in S3 (#18327)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use run logs and restricted provider traces to inspect
agent work.
> - Local log and trace files depend on the web server's persistent
volume.
> - That dependency prevents overlapping volume-backed Railway
deployments.
> - This PR reuses the instance S3 store for batched log and trace
payloads with conditional publication.
> - Existing Postgres rows retain their contracts; native export
recovery reuses events already committed before Runner acknowledgement.
> - S3-configured servers automatically copy and verify retained history
before a later deployment cutover.

## Linked Issues or Issue Description

**Subsystem affected**

Server run logs, restricted provider traces, storage providers, and
migration tooling.

**Problem or motivation**

Replacing the web server and its disk must preserve committed log output
and retained traces. The current S3 mirror can repeatedly upload a
growing file. Moving those payloads into Postgres would add database
writes, WAL, replication, and backup work.

**Proposed solution**

Reuse the existing instance storage configuration, S3-compatible
provider and credential chain. Store new run logs under run-logs/ and
opted-in raw traces under provider-traces/, below the existing prefix.
Cloud keeps its existing bucket and bucket-scoped credentials per stack.
Add no new configuration switches. Store immutable payload segments and
bounded binary range indexes directly in S3. Publish each batch with an
ETag-conditional head. Keep existing database ownership and lifecycle
records. Recover canonical native exports from their existing validated
control event source, checkpointing export progress in S3. Add no new
payload writes to Postgres. Preserve local defaults and migrate settled
history with verified byte counts and digests.

**Alternatives considered**

Postgres payload chunks add control-plane load. Repeated whole-file
mirrors amplify transfer work. The first index prototype left superseded
index nodes; the final binary index keeps all normally published nodes
reachable.

**Roadmap alignment**

This is a storage prerequisite for replacing the main web/API server. It
does not enable deployment overlap, detach a volume, or change native
Runner protocol acknowledgements. The maintainer approved this
implementation scope. ROADMAP.md has no duplicate implementation item.

Related PR: #16770 improves the existing in-flight mirror. This PR
preserves that legacy backend and uses the existing instance S3 profile
for new journals.

## What Changed

- Automatically select S3 segments for new logs and opted-in traces when
instance file storage uses S3. Reuse bucket, endpoint, region, prefix,
path style and credentials. Remove separate backend switches. Keep
local-disk instances local.
- Share the existing storage configuration resolver with product files.
Preserve config-file settings, environment precedence and the existing
root prefix. Keep pre-existing run-log mirror settings for legacy
history.
- Add bounded buffering, conditional ownership fencing, immutable range
reads, stable byte offsets, and completion hashing.
- Dispatch all existing log consumers through the recorded backend.
Coalesce output progress writes and publish live log messages after
storage receipts.
- Recover interrupted canonical native exports from their existing
durable source. Exclude separate credential, cleanup, and reprojection
records. Replay missing callback ranges and deduplicate late delivery.
Repair settled archives after controller lease expiry. Bound shared
repair work and stop it when all readers cancel. Serve the published
prefix when best-effort repair fails.
- Add encrypted optional trace channels, replacement reads, durable
deletion tombstones, and deadline-driven local/external expiry cleanup
independently of heartbeat scheduling. Stream historical source and
remote verification. Propagate worker cancellation through trace open,
conditional-write probing, upload, restore and reads. Fence deletion
even before the first object head exists; abort and drain owned
captures.
- Retry transient storage errors, distinguish 409 from failed
preconditions, and backpressure bounded log admission. Track interrupted
trace imports explicitly so ordinary local deletion stays independent of
S3.
- Automatically migrate retained history through the existing delivery
coordinator. Process one log and one trace per batch. Retry unresolved
history with backoff and stop scans after completion. Keep the
inventory/import command as optional diagnosis and repair. Verify source
and remote bytes before switching references. Verify finalized native
size and digest before setting its export cursor. Require ordered source
coverage when completeness metadata is missing. Preserve original trace
expiry. Block active, missing, corrupt, and unproven sources.
- Preserve identity and run-secret redaction in live and recovered
native logs. Register runtime log redaction secrets once through the
existing encrypted registry. Keep agent private keys in their existing
owner.
- Add storage, migration, retention, UTF-8, and route-privacy coverage,
plus operating documentation and qualification tooling.
- Add no schema, payload table, per-record SQL, production dependency,
or lockfile change.

## Verification

- Final fixes at `b3a44c898e` passed all 116 selected startup,
retention, attribution and cancellation controls. The disabled-scheduler
cleanup and concurrent-repair defects reproduced red before the fixes. A
timed-out repair still prevents later storage reads.
- The merged source passed 124 storage and real-Postgres Cloud
configuration tests. These include automatic history migration, existing
environment/file vault keys, source-directory removal, five real-SDK
stalled-request cancellation cases, shared capability-probe cancellation
and multi-chunk trace ordering. Saved Cloud S3 settings work after the
legacy config file is gone.
- Workspace typecheck and full build passed at the merged parent
`19f702d780`. Server typecheck and build passed again at `b3a44c898e`.
- Actual app acceptance: finish a process-agent run through the normal
API, stage its retained local-file input, then restart. Automatic
migration reports one migrated item and zero blockers. Remove the
original web home and restart at `b3a44c898e` with an empty home, the
existing S3 profile and the existing vault key file. The normal log API
preserves all five producer lines and exactly 788 bytes, with SHA-256
`74d9ae469da28bfe89b9b50a0e132aec24fe9e6d686496ed5e4ffa6167151036`. No
log-specific storage settings are present.
- Actual expiry acceptance: with heartbeat scheduling disabled, a trace
remains unexpired after startup and later reaches its fixture deadline.
The worker marks the row deleted and tombstones both S3 channel heads.
The retained run log stays byte-identical. The process fixture emits no
provider protocol frames, so nonempty encrypted payloads are qualified
separately through the real SDK round trips.
- Isolation tests use identical run identities in two stack buckets.
Cleanup in one existing prefix leaves another prefix, another company
and product files intact. Read-only Cloud source inspection confirms a
bucket and bucket-scoped credentials per stack. Four existing Cloud
storage environment-contract tests passed. No Cloud provisioning changed
and no new live vendor permission probe was performed.
- Earlier qualification passed 1,014 affected storage/native tests and
27 privacy-route tests with isolated Docker Postgres. An abrupt process
test commits 1,000 records, receives receipts, dies by SIGKILL and loses
its directory; another process reads every byte and continues. The real
Rust Runner experiment acknowledges 32 records while the export cursor
is zero, then continues the same Runner PID after controller loss. All
64 records export once with exactly 64 existing control rows. Repeated
snapshot/Stop commands completed in 162/81 ms.
- Emulator workload: 1,000 burst records used two batch PUTs. Eight
steady streams produced 240 records with 104 conditional PUTs and 72
GETs over 6.9 seconds. These are synthetic operation counts, not fleet
sizing or provider prices.
- Failure evidence is retained. Compact native events over 64 KiB,
missing file-key support, disabled-scheduler retention and repair
failure handling all reproduced before their fixes. Fixture repairs
addressed cold module setup, localhost/IPC permissions, the S3
bucket-name limit and a mode-0700 crash-test directory. Full local `pnpm
test:run` was stopped after host PostgreSQL semaphore exhaustion;
affected suites used isolated Docker databases instead. Native package
library symlinks were restored with the package's standard hydration
helper.
- The `19f702d780` browser session-recovery case timed out while saving
a task title. All eight browser shards passed on `b3a44c898e`, including
that case, with no UI behavior or assertion change. Fresh-head CI passed
at `b3a44c898e`: 55 successful checks, three skipped checks and one
neutral check. The branch is conflict-free.
- Map and module-boundary checks passed. Current-head Greptile is 5/5
with zero unresolved review threads.

Reproduce the opt-in storage suites with
`PAPERCLIP_LOG_TEST_S3_ENDPOINT` and a dedicated
`PAPERCLIP_RUN_EVIDENCE_MIGRATION_DATABASE_URL` ending in `_test`. See
`doc/run-evidence-storage.md` for operating limits, automatic migration,
optional diagnostics and rollout qualification.

## Risks

- Keep the existing per-stack bucket, prefix and vault key stable across
replacements. Relocating that storage is a separate whole-instance
operation.
- This release automatically changes new log storage for existing
S3-configured instances. Local-disk instances remain local. Canonical
native source replay is qualified with a deterministic real Runner;
actual remote execution and production-provider qualification remain
rollout gates. Generic server-only diagnostics and optional raw trace
tails without a surviving source can be incomplete after a crash. This
does not establish full zero-downtime deployment.
- Before deploying this release, qualify the actual S3 provider. It must
enforce conditional writes and pass read, version, deletion, workload,
and latency qualification. A capability probe rejects providers which
ignore preconditions. Moto is emulator evidence only.
- Dirty output is bounded and unconfirmed until S3 publication. Storage
failure leaves persistence incomplete while task results and usage can
settle.
- Trace expiry is not yet represented by Cloud's external wake contract.
Outstanding trace deadlines conservatively block sleep.
- Automatic history copying requires the original source volume. Keep it
until all retained resources pass verified import and clean-filesystem
reads. Stop old binaries from creating new local-file runs. Missing or
corrupt history remains blocked and visible in server logs. Rollback
requires a compatible reader against the same external state. Ordinary
object deletion does not erase retained historical object versions or
backups.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, with reasoning, tool use, code execution,
and browser verification. The runtime did not expose a 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-30 15:17:35 -05:00
DottaandPaperclip ebd05e9f4c perf: avoid scanning unused provider pack trees during archive upload (#18340)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native agents need verified provider files in remote sandboxes.
> - A fresh sandbox can need the bundled provider-pack archive.
> - The upload path also hashes the expanded controller tree, which it
does not upload.
> - That synchronous scan blocks the server event loop and delays other
requests.
> - This change verifies the archive source and the installed pack, and
keeps source-tree checks for directory uploads.

## Linked Issues or Issue Description

**What happened?**

Provider-pack archive fallback scans and hashes the full expanded
controller tree before reading the build archive. The archive is the
source sent to the sandbox. The extra scan blocks the Node event loop
for several seconds. An overlapping asynchronous operation can then
appear to take as long as that scan.

**Expected behavior**

Verify the bytes used by the selected upload path. Keep full
verification of the installed pack against the selected manifest before
a provider can use it.

**Steps to reproduce**

1. Use a packaged provider pack with a build archive.
2. Start a remote native run whose sandbox needs that pack.
3. Inspect `provider_pack.archive.verify` and event-loop delay on the
controller.

Related: #18308 adds timing detail for workspace preparation. A search
found no duplicate archive-verification fix.

## What Changed

- Use the verified archive without scanning the unused expanded
directory.
- Keep full directory verification when no archive exists or the remote
lacks archive support.
- Keep archive digest checks and full verification of installed bytes.
- Add `provider_pack.directory.verify` for directory fallback.
- Add regression cases for both archive formats, fallback, and final
verification failure.

## Verification

- Both archive regressions failed before the change and passed after it.
- 80 focused archive, selection, and verification cases pass on the
rebased branch.
- 20 native manifest and admission cases pass.
- Server typecheck, server build, and the runtime bundle pass.
- A disposable sandbox from the recorded image exercised the real
uploader and full installed-pack verifier. It accepted the unchanged
build bytes and rejected an altered proxy file. No model was called. The
sandbox was deleted and its absence was verified.
- A local baseline/archive/archive/baseline probe used the same
unchanged public build pack. Preparation took 30.673 s, 84 ms, 106 ms,
and 5.371 s. The slow baseline outlier is retained. This measures one
controller phase; it does not establish a whole-turn or hosted speedup.

## Risks

The archive path no longer checks expanded files that it does not send.
Archive checks still fail closed, and the installed files must pass the
same full manifest verification. Directory fallback keeps its
source-tree check. Installs without archives retain that synchronous
scan. The local sandbox probe tests upload and installed-content checks;
it does not qualify admission of an older pack by a newer controller.

## Model Used

OpenAI Codex, GPT-6 family, with tool use and local code 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)

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 11:47:21 -05:00
Nicky LeachandClaude Opus 5.5 abc270ee4c fix(runner): attest upstream releases and bind ACPX uniformly for every harness (#18325)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native ACPX runs admit a provider only when its saved profile and
`commandDigest` match the current profile exactly.
> - For Copilot, Grok and Pi, `commandDigest` hashed dozens of Paperclip
source files. Claude, Codex, Cursor and Antigravity hash only their
upstream release.
> - Any change to a bound source therefore advanced these profiles.
#18212 alone moved Copilot from v88 to v91 and Grok from v15 to v19.
Each bump reset in-flight sessions and added immutable identity fixtures
(about 160 on master).
> - #18237 added the provider pack `contractDigest`, which now guards
Runner source compatibility at the pack boundary.
> - This pull request changes the Copilot, Grok and Pi digests to
upstream release attestations, as the other providers already use.
> - It also binds the shared ACPX layer the same way for every ACPX
harness: the profile's `acpxVersion` and the pack `contractDigest`,
which now covers the Runner's ACPX patch.
> - The benefit is that Runner source changes no longer reset these
sessions or need new profile versions and fixtures.

## Linked Issues or Issue Description

Refs #18237, #18212, #17972.

**What happened?**

A Runner change that touched a bound source file changed the Copilot,
Grok or Pi `commandDigest`. The author had to advance the profile
version, regenerate an identity fixture and keep every old fixture. On
deploy, saved sessions for that provider failed the exact admission
check and started fresh.

**Expected behavior**

A provider's `commandDigest` changes only when its upstream release
changes: an upstream version, a platform closure, the ACPX patch or the
Grok launcher. Runner source compatibility is the job of the pack
`contractDigest`.

**Steps to reproduce**

1. On master, change a comment in `src/drivers/acpx/runtime-host.ts`.
2. Run `node packages/paperclip-runner/scripts/grok-profile-identity.mjs
--check`.
3. The check fails. The Grok profile must advance, and the next deploy
resets Grok sessions.

## What Changed

- Add `packages/paperclip-runner/scripts/acpx-release-attestations.mjs`.
It computes the release attestation for each provider:
- Copilot and Pi: a canonical-JSON hash of the profile version, upstream
package versions and the platform closure pins (Pi also binds its Node
version).
- Grok: the SHA-256 of `launcher.cjs`. Admission already hashes these
bytes.
- The attestation binds no Paperclip source, shared ACPX layer, absolute
path, pack manifest digest or install layout.
- Bind the shared ACPX layer once for every ACPX harness (Claude, Codex,
Copilot, Cursor, Grok, Pi, Antigravity):
- Add the Runner's ACPX patch (`patches/acpx@<runner acpx
version>.patch`) to the pack `contractDigest`. A patch change now
retires older image packs for every harness. Other packages' ACPX
patches are not read. A build context without the Runner's patch fails.
- Remove the ACPX patch hash from Cursor's release declaration
(`cursor-contract.json`) and advance Cursor once to profile 17. Copilot,
Pi and Cursor no longer bind ACPX in their own digests, like Claude,
Codex, Grok and Antigravity.
- Saved inputs for every harness already must match the current
`acpxVersion`.
  - Claude and Codex digests do not change.
- `generate-acpx-profiles.mjs` writes these digests to
`acpx-profiles.json`. `check:acpx-profiles` refuses a stale digest.
- Move the Copilot closure pins to `copilot-closure-pins.ts`, so that
the generator can import them. `copilot-installation.ts` re-exports
them.
- Advance each profile once and then freeze it: Copilot 92, Grok 20, Pi
37. A version change at the switch keeps the rollout on the same path as
every earlier profile bump.
- Replace the historical version lists in `profile-compatibility.ts`
with a range. Every revision from 1 through the current one decodes.
Claude and Codex still decode revisions 1 through 5. Launch and recovery
admission still require the exact current profile and digest.
- Delete:
- `scripts/copilot-profile-identity.mjs`,
`scripts/grok-profile-identity.mjs` and its test
  - the Grok launcher source stamp
- 159 Copilot, Grok and Pi identity fixtures, including three
unreferenced `copilot-mainline-v*` fixtures. The Cursor fixtures stay.
- Rewrite the affected tests as behaviour checks:
- Each provider admits only the exact current profile. Every earlier
version decodes and is refused at admission.
- The last source-bound digests, and a changed digest at the current
version, are refused by recovery and by the backend factory.
- The Rust Pi descriptor test uses the generated profile instead of
fixtures.
- New `acpx-release-attestations.test.mjs`: a relocated copy of the
inputs gives the same digests, each upstream input changes only its own
providers, and the generator refreshes and checks the manifest.
- Remove the fixture exceptions from `.dockerignore`. Add the
attestation script and the generator to the Daytona image content
inputs.
- Update the Pi install probe and the Rust integration constant for the
new Pi digest.
- Update the docs to describe the current attestation model:
`doc/grok-native-runner.md`, `doc/RUNNER-INTEGRATION-PLAYBOOK.md`,
`doc/observability.md`,
`packages/paperclip-runner/docs/durable-recovery.md`, and the Copilot,
Pi and rich ACP architecture reports. Each report now opens with the
current profile identity; earlier source-bound profiles remain as dated
chronology. No doc references a deleted file.

## Verification

- In `packages/paperclip-runner`:
- `node --test scripts/acpx-release-attestations.test.mjs
scripts/contracts/contract-fingerprints.test.mjs`: 19 tests pass,
including a Runner ACPX patch edit that changes the contract digest,
other patch edits (including `acpx@0.12.0` for `adapter-utils`) that do
not, and a build context without the patch that fails.
  - `node scripts/generate-acpx-profiles.mjs --check` passes.
- `vitest run src/drivers/acpx src/backends src/contracts`: 1647 tests
pass, 9 skipped.
  - `tsc -p tsconfig.json --noEmit` passes.
- From the repository root, `vitest run --config
tests/runner-e2e/vitest.config.ts
tests/runner-e2e/daytona-image.test.ts`: 11 tests pass.
- In `server`, the 8 test files that use ACPX profiles, pack digests or
`contractDigest`: 1617 tests pass.
- Not run locally: the Rust tests and `cargo fmt`, because this machine
has no Rust toolchain. CI runs them.
- Before this change, a synthetic upgrade check built two Runner
revisions that differ only in shared source. A Claude checkpoint saved
under the first revision rebinds under the second, and a changed Claude
`commandDigest` starts fresh. This confirms that the provider JSON has
no other build-dependent field.

## Risks

- **One reset at rollout.** The Copilot, Grok, Pi and Cursor digests and
versions change once. Saved sessions for these providers start fresh on
their next run, as after any earlier profile bump. After this change,
Runner source changes no longer cause this reset.
- **Lost "source changed, so requalify" signal.** The old digest forced
a new profile version when bound source changed. Nothing enforced
requalification: Copilot was last qualified at v47. Pack-boundary
contract changes are now caught by the pack `contractDigest`.
- **Image packs are retired once for every provider.** Adding the ACPX
patch changes the pack `contractDigest`, so the controller uploads its
bundled pack (about 16 s per remote start) until images are refreshed.
Claude and Codex sessions are not reset: their digests and versions do
not change.
- **Grok launcher and closure pins.** The Grok digest covers only the
launcher bytes. Grok's runtime version is still checked separately at
admission, as before.
- **Grok digest equals early Grok profiles.** The launcher bytes have
not changed since profile 1, so the new Grok digest equals the published
profile 1 digest. The profile version still separates them: launch,
recovery and the backend factory require profile 20. An image pack from
that period has no `contractDigest`, so the pack gate refuses it.
`remote-provider-pack-verification.test.ts` now covers this case.
- **Docker context checks** run `generate-acpx-profiles.mjs --check`,
which now imports `.ts` pin files through Node type stripping.
`materialize-pi-distribution.mjs` already relies on this on Node 24.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use
(shell, file edits, local test runs).

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:10:50 -07:00
DottaandPaperclip 75666224d4 fix(native): use the deadline for remote health retries (#18324)
## Thinking Path

> - Paperclip manages agent work and its execution state.
> - Remote Runner processes use health reads to check their saved
process identity.
> - A failed health request cannot prove that the process stopped.
> - Three fast gateway errors can exhaust the old retry limit in half a
second.
> - The caller already gives these reads a shared 30-second recovery
budget.
> - This pull request uses that budget with backoff for read-only
failures.
> - A short gateway outage can then clear without stopping the existing
turn.

## Linked Issues or Issue Description

**What happened?**

A transient HTTP 502 during sandbox process supervision caused an active
native Codex turn to fail. The probe stopped after three attempts, even
when most of its 30-second budget remained. The run reported
`notification_transport_failed` and required workspace recovery.

**Expected behavior**

Retry read-only transport failures within the existing deadline. Keep
process identity conflicts authoritative. Do not repeat a signal after a
lost acknowledgement.

**Steps to reproduce**

1. Start a read-only process verification with a 30-second deadline.
2. Return HTTP 502 from its first three transport reads, then allow the
next read to succeed.
3. The old helper rejects after three reads. The fixed helper returns
the successful observation.

Related repairs: #16451 introduced bounded remote probes. #16835 and
#17799 require proof of process exit before replacement. This change
retains those guards.

## What Changed

- Use the existing absolute deadline instead of a three-attempt limit
for read-only probe failures.
- Back off from 250 milliseconds to two seconds. Clip each request to
ten seconds or the remaining budget.
- Preserve the original error and diagnostic when the deadline is
exhausted. Reject non-finite deadlines before an RPC.
- Add a red/green regression and a repeated-gateway-failure case around
a real listening process.
- Update execution semantics and both recovery maps.

## Verification

- Before the fix: the new probe suite failed two behavioral assertions.
The gateway case returned its HTTP 502 error instead of the later
successful observation.
- After the fix: 75 focused probe, diagnostic, process-supervision and
adoption tests pass. The diagnostic failure tests use a controlled clock
for their full 30-second budget. Their error and redaction assertions
stay unchanged.
- Map alignment and module-boundary checks pass.
- Full workspace typecheck and build pass at final commit
`ddd42f66378ebc36ec1d7e0ca1f45943473561b3`.
- The broader affected suite against disposable PostgreSQL passed 994 of
997 tests; its three startup/database timeouts passed unchanged in
isolation. The initial full default local run encountered embedded
PostgreSQL startup failures and did not complete. The four diagnostic
tests that assumed the old short retry timing now use a controlled clock
without weakening their assertions.
- Incident evidence came from Linux AMD64, Node 24.22.2, Core commit
`0c70cedce9a803bdc201324528abb35e423e7cd0`, native Codex `gpt-6.1-sol`,
and a shared ChatGPT subscription. Two separate runs recorded the same
supervision HTTP 502 within one second.
- A disposable live Daytona sandbox check passed on Linux x86_64 and
Node 24.22.1. Three injected gateway failures recovered in 3.31 seconds
on production source from `e54a355fa179022caaa6854302ff56bd85de0229`
(unchanged by the final test-only commit). The real Node listening
process had one launch, retained its exact identity and saved file
across a second read, and produced a confirmed Stop receipt. Sandbox
deletion succeeded. This is process-supervision integration evidence,
not a Codex task or model execution.
- Fixed-revision hosted acceptance and recovery of the original
conversation require rollout. This PR does not claim either. The
duration of the original provider outage remains unknown.

- Final commit `ddd42f66378ebc36ec1d7e0ca1f45943473561b3`: required `ci
/ verify` and `ci / e2e` checks pass; Greptile is 5/5 with no inline
findings. The separate Paperclip Review service has not completed an
assessment and remains queued. It is not a required branch check.

## Risks

- Persistent fast transport failures cause more read-only requests
within the same deadline. Capped backoff limits their rate.
- Missing or changed identity still returns immediately. Failed health
reads still cannot authorize replacement, process signals, or provider
replay.
- Signal requests still have one attempt. The timeout budget and
execution permissions do not change.
- No schema or package changes.

## Model Used

- OpenAI GPT-6, through Codex, with reasoning, repository inspection,
and shell tool use. The exact deployment model ID 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-30 10:50:49 -05:00
e345b9217d fix(runner): paginate native task searches without hidden truncation (#18282)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents search tasks to find work that already exists.
> - The search schema permits 200 results, but the server returns at
most 100.
> - The response does not tell the agent that more results exist.
> - This pull request adds pages and reports the page size and
continuation cursor.
> - Agents can read the full accessible inventory before they decide
that a task does not exist.

## Linked Issues or Issue Description

**What happened?**

A native `search_tasks` request with `limit: 200` returns only 100
tasks. Historical scans recovered 167 and 173 tasks with status
partitions. This proves missing inventory and extra work. It does not
prove duplicate task creation.

**Expected behavior**

Honor the declared limit. Report more results and give the caller a
continuation cursor.

**Steps to reproduce**

Create 205 matching tasks in a test company. Call `search_tasks` with
`limit: 200`. The baseline returns 100. The fixed path returns 200, then
five when the caller uses `nextCursor`.

**Paperclip version or commit**

Baseline: `81ebe479e8db8a3d59c86cdfb894bd917734492f`.

Related changes: #16979 changes UI status filters before pagination.
#13699 adds public task URLs. Neither repairs this native limit. An
exact `search_tasks` plus pagination PR search returned no result.

Pattern: [Task searches omit cases beyond the first
hundred](https://www.braintrust.dev/app/Paperclip/p/Paperclip%20Staging/patterns/c20462d6-05fd-4862-bfbd-7bec1f2bc159).

### Hypothesis and thesis for a fix

The native authority uses `boundedLimit` with its default maximum of
100. The tool schema permits 200. The response contains only `tasks`.
The raw request and result counts agree with this cause.

Fix the native authority and its canonical tool contract. Keep the
existing `tasks` field. Add `limit`, `returnedCount`, `hasMore` and
`nextCursor`. Use ascending task IDs so task activity does not move
results between pages. Apply current company, privacy and Muse read
checks before each page. A cursor grants no access. Callers must keep
the same filters and read every page. Concurrent task changes require a
fresh scan.

## What Changed

- Honor the native search limit of 1 to 200, with a default of 50.
- Add ID cursor pagination and page metadata.
- Describe complete inventory reads in the tool contract and access map.
- Refresh the generated semantic contracts and seeded catalog identity.
- Add regression coverage for complete inventories and access-filtered
pages.

## Verification

- Red: the database integration test requested 200 of 205 persisted
tasks. Baseline returned 100.
- Green: the same regression returns pages of 200 and five without
duplicate IDs.
- The native authority and Muse suites cover company exclusion, status
filters, empty pages, invalid cursors and readable-only metadata.
- Command: `pnpm --filter @paperclipai/server exec vitest run
src/services/native-runtime/paperclip-runner-tool-authority.test.ts
src/services/native-runtime/muse-native-visibility.test.ts`.
- The test uses the real run-bound native authority and disposable
PostgreSQL. It does not use an external model or change a deployed
scanner.
- Both native authority and Muse suites pass: 71 tests. Server direct
`tsc --noEmit`, Runner `typecheck:typescript`, `node
scripts/check-maps.mjs` and generated semantic contract checks pass.
- Full typecheck and build cannot finish here because `cargo` is absent.
The full local test command was stopped after about five minutes when
the complete CI matrix was running. It has no complete verdict.
Current-head CI passed, including typecheck, build, all
general/serialized/Runner test suites and E2E. Greptile is 5/5 with no
actionable findings at `392cb7424a1fa0ec73401d5e8a10a22b504fde32`.
Optional Storybook and manual Docker workflows were skipped and are not
executed coverage. The success-example correction also passed all 82
contract tests locally.

## Risks

Task order changes to ascending ID. Pagination is not a snapshot. New or
changed tasks can require a fresh scan. Each page retains the existing
full company-list read and Muse authorization cost. This change adds no
database query loop or new background work. Existing callers can still
read `tasks`, but must follow `nextCursor` for a complete inventory. No
scanner implementation was supplied. No migration or deployment is
included.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The exact
provider deployment ID and context limit 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)
- [ ] 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

The task requires the supplied branch to stay unchanged. All applicable
CI and review checks pass at the current head. Unmerged and not
deployed.

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 09:23:10 -05:00
Devin FoleyandClaude Opus 5.5 2a221e8e80 fix(sentry): keep scheduled native model capacity retries out of run-failure reports (#18295)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The run-failure reporter sends terminal run failures to Sentry when
an operator sets `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected`
> - In `unexpected` mode, the reporter skips failures that a bounded
automatic retry already owns. The Codex ACP model capacity failure
(`codex_transient_upstream`) is one of these
> - The native runner has the same capacity failure: Codex
`serverOverloaded` ("Selected model is at capacity"). Native
finalization schedules a bounded automatic retry for it (#15347)
> - The reporter has no matching exclusion for the native path. Each
scheduled capacity retry also sends a Sentry error, even when the retry
recovers the task
> - This pull request skips the report only when the native failure has
typed capacity evidence, a committed retry decision, and the retry run
that the decision created
> - The benefit is that Sentry shows capacity failures only when
automatic recovery stops (retries are exhausted, held, or not scheduled)

## Linked Issues or Issue Description

Refs #15347 (native capacity retry). Refs #16407 (Codex ACP capacity
exclusion).

**What happened?**
A native Codex run failed with "Selected model is at capacity. Please
try a different model." (`native_provider_overloaded`). Native
finalization scheduled the automatic capacity retry. The retry run
succeeded and the task completed. The run-failure reporter still sent a
Sentry error event for the first run.

**Expected behavior**
When the automatic capacity retry owns recovery, the run failure stays
in the local run log and does not go to Sentry. This is the same as the
Codex ACP capacity path. When retries are exhausted or held, or when no
retry is scheduled, the failure goes to Sentry.

**Steps to reproduce**
1. Set `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected` with a backend Sentry
DSN.
2. Run a native Codex agent turn that ends with a Codex
`serverOverloaded` terminal error.
3. See that native finalization creates a `scheduled_retry` run with
`scheduledRetryReason=native_provider_overloaded`.
4. See that Sentry also receives a run-failure event for the failed run.

## What Changed

- `server/src/services/run-failure-report.ts`: add
`isScheduledNativeCapacityRetry`. In `unexpected` mode it skips the
report only when all of these are true:
- the run is native, `failed`, has
`errorCode=native_provider_overloaded`, and has a native task
(`nativeIssueId`);
- `resultJson.nativeProviderFailure` is the closed
`codex`/`server_overloaded` diagnostic;
- `resultJson.finalizationPhase` is `committed` and
`finalizationReasonCode` is `native_provider_overloaded`;
  - the report is not from setup, and the run has no signal;
- a successor run for the same task exists with `retryOfRunId=run.id`
and `scheduledRetryReason=native_provider_overloaded`. The same status
transaction creates this run.
- The successor lookup filters on `company_id`, `context_snapshot ->>
'issueId'` and `created_at >= run.createdAt`, so the existing
`heartbeat_runs_company_ctx_issue_created_idx` bounds it to that task's
runs since the failure. No migration is needed.
- A failed read of the retry evidence logs a warning and reports the
failure.
- `doc/observability.md`: document the new exclusion in the run failure
context section.
- Unit tests: the exclusion, and twelve cases that must still report
(exhausted, held, no retry run, another retry lane, successor for
another task, run with no native task, finalization not committed, wrong
or missing diagnostic, legacy run, signal, timeout). Also setup phase,
`all` mode, and an unreadable retry record.
- Integration test (real native finalizer): no Sentry event for retries
1 and 2, one event when retries are exhausted, and one event when
reassignment prevents a retry.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/services/__tests__/run-failure-report.test.ts
src/services/native-runtime/native-provider-overload.integration.test.ts
src/services/native-runtime/native-provider-failure.test.ts
src/services/__tests__/status-arbiter.test.ts`: 359 tests pass.
- Red/green: before the fix, the new unit test captured 2 events, and
the integration test captured an event on the first scheduled retry.
After the fix, both pass.
- `EXPLAIN` on the migrated schema: `Index Scan using
heartbeat_runs_company_ctx_issue_created_idx` with company, context
issue and created time in `Index Cond`.
- CI provides the full workspace typecheck.

## Risks

- Low risk. The change applies only in `unexpected` mode and only to
native runs with typed capacity evidence and an existing retry run.
`all` mode still reports every failure.
- The check adds one index-bounded read of `heartbeat_runs` for runs
that match the in-memory capacity checks. Other runs do not do this
read.
- If a scheduled retry later fails, that retry run reports its own
outcome. When retries are exhausted, the final failure reports.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic. Agentic coding with
tool use (shell, file edits, test execution) and extended thinking.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 05:42:43 -07:00
DottaandPaperclip 965184d296 fix(runner): reuse accepted confirmations on native continuation (#18283)
## Thinking Path

> - Paperclip coordinates agent work and human decisions.
> - Native agents receive accepted confirmations when their task
resumes.
> - A resumed run can repeat the original confirmation with the same key
and scope.
> - The interaction service rejects that replay because the source run
changed.
> - This PR returns the original acceptance only to its bound native
continuation.
> - Changed requests and newer proposals keep their existing approval
gates.

## Linked Issues or Issue Description

**What happened?**

A native agent received a human acceptance, then repeated the same
confirmation key and request. Paperclip returned a conflict because
`sourceRunId` differed. The agent then used a new key and created a
second pending confirmation. The task waited for another answer.

**Expected behavior**

An exact replay from the native run that received the accepted response
returns the original accepted record. It creates no request or wake.
Changed scope, another creator, an unrelated continuation, and a newer
proposal must still fail.

**Steps to reproduce**

1. Create a confirmation from a native run.
2. Accept it as a human.
3. Resume the same task with that accepted response in its saved native
input.
4. Repeat the original confirmation key and request.

Before this fix, step 4 returns `409 Interaction idempotency key already
exists for a different request`.

**Paperclip version or commit**

Reproduced against source `81ebe479`. The deployed failure was also
confirmed against Core `6a674716`.

**Deployment mode**

The failure occurred on Cloud. The regression uses the real native tool
authority and PostgreSQL 17 with synthetic data. The full fresh Cloud
journey is not yet verified with this fix.

No duplicate open PR or issue was found in the related
confirmation-replay and interaction-idempotency searches.

## What Changed

- Let the current run's parsed, identity-bound accepted response
nominate an internal replay of a plain confirmation or checkbox. Exclude
governed tool, secret, connection, and quality-review cards.
- Reuse the original accepted record only when the key, creator, and
full normalized request match. Preserve its source run. Reject a newer
confirmation.
- Keep ordinary source-run comparison and mutation receipts. Recheck
accepted cross-run reuse on cached calls and lost-ack recovery. An
absent original cannot create a replacement.
- Add real database regressions and document the replay contract.

## Verification

- Real PostgreSQL regression: the original replay failed with the
observed conflict, then passed.
- Cached replay regressions: two controls first returned stale
acceptance. Both now reject it.
- Final replay and recovery suite: 27 passed. This covers both plain and
checkbox confirmations, governed-payload exclusion, identity, company,
request changes, newer proposals, revised plans, absent receipts, absent
originals, and tool-key conflicts.
- Existing native-tool and onboarding admission suites passed with the
first 24 replay controls: 109 tests at `3cfd58e7`. The scope follow-up
reran all 27 replay controls.
- Existing interaction service and policy suites: 122 passed.
- Full `pnpm build` and `pnpm -r typecheck` passed at `3cfd58e7`. After
the scope follow-up, the focused 27 tests and server TypeScript check
passed. Required full Linux CI passed on the final head `eabdbd6b`.
- The full local Vitest suite was not repeated because the macOS
embedded PostgreSQL bootstrap failure is already documented. Relevant
suites used the supported external test database paths. Required Linux
CI remains pending.
- Final-head CI attempt 1 failed only the unchanged Antigravity login
success fixture. Its implementation and test match a previous passing
head. The exact failure cause is not retained. The original [failed
job](https://github.com/paperclipai/paperclip/actions/runs/41014308876/job/123927423551)
is preserved. The one failed-jobs-only retry request passed on the
unchanged final head. This confirms recovery, not the cause of the
original failure, and is separate from the Cloud journey.
- Full fresh Cloud onboarding and its dependent journey remain
unverified at this revision.

## Risks

An approval replay must not authorize new work. The service keeps exact
request and creator checks under the task lock. Newer confirmations and
ordinary downstream task and target checks remain effective. Normal API
callers cannot supply the internal replay nomination. No database
migration or public request-schema change is included.

## Model Used

OpenAI `gpt-6.1-sol`, ultra reasoning, with repository and shell tools.
The parent runtime metadata supplies this model identity. The context
window is not exposed. Independent review used the same model family.

## 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-30 01:53:45 -05:00
Nicky LeachandClaude Opus 5.5 fa760dbce4 fix(runner): reuse image packs only with matching contract digest (#18237)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Remote native runs use a provider pack. The controller reuses a
protected pack from the sandbox image when the pack is compatible.
> - #17749 gates this reuse on a hand-maintained interface revision in
`provider-pack-contract.json`.
> - Later changes altered the runner/pack boundary (#17922, #18188), but
nobody bumped the revision. A stale Claude or Codex image pack can still
be reused across a sidecar contract change. This is the failure class of
#17972.
> - A manual revision has a "forgot to bump" failure mode. Source-byte
hashes change on every refactor, so they are too brittle.
> - This pull request declares the sidecar `session.open` contract in
its JSON schema and computes a contract digest from the JSON contracts
and Rust shapes.
> - Image-pack reuse now requires an equal digest.
> - The benefit is that an incidental change keeps image packs reusable,
and a real contract change retires them automatically.

## Linked Issues or Issue Description

Refs #17749, #17972, #17922, #18188.

**What happened?**

The controller reused an image provider pack when `compatibility.acpx`
and the selected agent's profile digest matched. For Claude and Codex,
that profile digest binds only the upstream executable. The ACPX
interface revision stayed at 1 after later sidecar contract changes. A
pack built before those changes passed the reuse check.

**Expected behavior**

The controller reuses an image pack only when the pack uses the same
runner/pack contracts as the controller's bundled pack. Comments,
formatting and refactors do not change that result.

**Steps to reproduce**

1. Build an image pack from a commit before a sidecar input change, such
as a new `session.open` field.
2. Run a controller from a later commit that sends the new field, with
the same interface revision and Claude version.
3. Before this fix, `verifyRemoteProviderPack` accepts the old image
pack.

## What Changed

- Declare the sidecar `session.open` parameter set as a closed
`sessionOpenParams` definition in `acpx-sidecar.schema.json`.
- `generate-acpx-sidecar-contract.mjs` now generates
`GENERATED_ACPX_SIDECAR_OPEN_PARAMS` from it.
- `parseOpenParams` uses the generated list instead of an inline `Set`.
The accepted set is unchanged.
- This is the surface of #17972. The schema is now its source of truth.
- Declare the nested `session.open` contracts that the sidecar parses
strictly:
- `protocol/provider-schemas/runtime-context.schema.json` closes every
runtime context object. `parseNativeRuntimeContext` uses the field lists
that `scripts/generate-runtime-context-contract.mjs` generates from it.
- The sidecar schema declares the closed `providerPolicy` object, and
`parseProviderPolicy` uses its generated field list.
  - The accepted fields do not change.
- Add
`packages/paperclip-runner/scripts/contracts/contract-fingerprints.mjs`.
It fingerprints these contracts:
  - the PRP and sidecar JSON schemas, with annotation text removed
  - the generated catalogs in `generated/`
- the Rust serde shapes, `json!` payload keys, match literals and env
keys in `runner-core/src`, without test-only modules
  - the reserved env key lists in `configured_environment.rs`
- Read only the trees that every pack build context contains. Fail when
a registered source is missing, so two build contexts cannot silently
produce different digests.
- Use only Node built-ins. The registry adds no dependency.
- Write `contractDigest` as a top-level payload field in
`build-provider-pack.mjs`. The manifest digest algorithm and the
existing field layout do not change.
- Require an equal `contractDigest` for image-pack reuse in
`remote-provider-pack-verification.ts`. A pack without a digest is not
reused. The controller uploads its bundled pack, as it does today for
any incompatible pack.
- Re-attest the source-hashed profiles, because this PR changes their
bound sidecar sources:
- Grok becomes profile 15 and now also binds the generated allowlist, so
a Grok field change in the schema still invalidates the Grok identity.
- Copilot becomes profile 88, and also binds the generated runtime
context fields.
  - Earlier profiles stay decodable.
- Add the registry script and `generated/` to the Daytona image content
inputs.
- Document the digest and the schema-first rule in
`docker/daytona-runner/README.md` and `doc/DEVELOPING.md`.

## Verification

- `node --test scripts/contracts/contract-fingerprints.test.mjs` (in
`packages/paperclip-runner`): 4 tests pass.
  - These changes keep the digest:
    - schema description text
    - schema reformatting
    - renaming `parseOpenParams`
    - Rust comments, `#[serde(skip)]` fields and `#[cfg(test)]` modules
- edits to the `#[path]` test module `tests/provider_api_validation.rs`
  - These changes alter the digest:
    - a new `session.open` schema field
    - a changed constraint on the `remainingWork[].description` property
    - a new reserved env key
    - a new sidecar env key
    - a new checkpoint field
  - A build context without a registered source fails.
- `node --test test/acpx-sidecar-contract.test.mjs`: 13 tests pass. A
new case rejects an unknown `session.open` parameter and accepts each
declared parameter.
- `node --test scripts/grok-profile-identity.test.mjs`: 4 tests pass. A
change to the Grok field in the generated allowlist invalidates the Grok
identity.
- `generate-acpx-profiles.mjs --check`,
`generate-acpx-sidecar-contract.mjs --check` and
`generate-protocol-manifest.mjs --check` pass.
- Runner vitest suites pass: 470 passed, 1 skipped. They cover the
sidecar, sidecar input and protocol, Copilot and Pi installation,
profile compatibility, native execution, recovery identity, the backend
factory and the environment.
- Server tests: pack verification, executor and artifact preparation
pass (1,004 tests).
- `tsc --noEmit` passes for `packages/paperclip-runner` and `server`.
- `tests/runner-e2e/daytona-image.test.ts`: 10 of 11 tests pass. The
failing test also fails on `master`. It expects a literal
`profile-v19-identity.json` line in `.dockerignore`, which uses a
`profile-v*` glob.
- Not run locally:
- A complete `build-provider-pack.mjs` run. The builder rejects the
local Homebrew Node because it is not portable after relocation.
- Rust tests and `acpx-controller-recovery.test.ts`, because `cargo` is
not installed.
  - The full `pnpm -r typecheck`, `pnpm test:run` and `pnpm build`.

## Risks

- Only JSON contracts and Rust shapes are part of the digest. The
remaining TypeScript-only definitions are the `paperclip_finish` and
`paperclip_block` tool schemas in `completion-result.ts` and the
TypeScript env key lists. They are not covered until they move into a
schema. The nested `expectedIdentity` and `tools` values ignore unknown
fields, so a change there cannot cause a startup rejection.
- A change there can let a stale image pack be reused. The sidecar then
rejects the input with its strict parser error.
  - Today, Claude and Codex image packs have no contract check at all.
- The digest covers all registered contracts for the whole pack. A
contract change for one provider kind also retires image packs for the
other. Each replacement costs about 16 s per remote start until the
image is refreshed.
- Existing image packs have no digest. After deploy, the controller
uploads its bundled pack until the image is rebuilt.
- The Grok and Copilot re-attestations start fresh sessions for those
agents once after deploy, as each profile bump does today.
- The Daytona image content ID formula changes, so the next image build
does not reuse a cached image.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) through Claude Code in the
desktop app, with repository tools, shell execution and research
subagents. The session does not expose the 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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:55:11 -07:00
DottaandPaperclip ed8fae8dbb fix(workspaces): preserve completed shallow sandbox exports (#18221)
## Thinking Path

> - Paperclip coordinates agent work and preserves its results.
> - Remote execution copies completed workspace changes back to the
host.
> - An agent can fetch a published branch with shallow Git history.
> - A full Git bundle omits the shallow boundary metadata and can fail
host connectivity checks.
> - This pull request carries the boundaries through the full-bundle
fallback and imports through normal Git fetch.
> - Recovery must also recognize completed native work on a reusable
lease without treating it as ordinary executor reuse.
> - Completed work can be saved without another provider turn, while
existing host history remains connected.

## Linked Issues or Issue Description

**What happened?**
Sandbox finalization can fail with a missing parent commit after an
agent checks out a separately fetched shallow branch. Re-exporting a
full bundle repeats the failure because Git bundles do not encode
shallow boundaries.

**Expected behavior**
Import the completed branch and saved files. Preserve existing host
ancestry and concurrent host edits. Keep normal Git connectivity and
workspace merge checks.

**Steps to reproduce**
1. Prepare a sandbox from one host commit.
2. Fetch a different published branch with depth one and check it out.
3. Save a result file and restore the sandbox workspace.

**Paperclip version or commit**
Reproduced against master before this repair. The regression fails with
the missing-parent error before the production change.

Related public context: #15268 covers rewritten history integration.
This repair handles shallow bundle transport before integration.
Searches found no equivalent open repair.

## What Changed

- Export shallow boundaries beside the full bundle when the delta import
lacks history.
- Unpack into a temporary shared bare repository. Keep parent
connections already available on the host and import with Git's shallow
fetch protocol.
- Reject malformed boundary values and retain existing connectivity,
branch, and concurrent-work merge guards. Keep boundary probes within 15
seconds without consuming the separate 60-second Git import budget.
- Let source-bound preservation recover reusable leases only for the
finalizer-selected, accepted successful native result and matching
completion contract. Retain provider-stop, physical ownership and
host-writer checks; ordinary reusable sources remain blocked.
- Classify invalid Git metadata separately from omittable unsafe
archives. Keep native finalization failed and preserve service-owned
file recovery; carry the sender's dedicated rejection across the command
boundary without transient retries.
- Share the failure allowlist across bounded run/activity projections
and cancelled-preservation selection. Migration `0416` rebuilds the
matching partial index; task chat retains the non-retryable recovery
notice.
- Add real Git, filesystem sandbox and database recovery regressions.
Update execution semantics and affected verification maps.

## Verification

- Red: real filesystem sandbox restore failed with the same
missing-parent/revision-walk error before the export repair.
- Green: 240 focused Git, workspace restore, sandbox transport and
native-finalization tests pass. Coverage includes both transfer paths,
malformed/oversized metadata, a genuinely shallow host with its original
boundary intact, and concurrent host work with both merge parents
verified.
- Red/green: a 14-second simulated probe left the final real Git fetch
only 45,893 ms before the budget split. It now retains over 55 seconds
after the probes; a 16-second probe exhausts its own budget before host
import.
- Red/green: an oversized read progress report was retried three times
before its distinct metadata classification. It now aborts the first
read before payload consumption, leaves the host tip unchanged and does
not retry.
- Red/green: the real metadata error was swallowed by best-effort export
and native finalization incorrectly returned success. Both regressions
now pass; all 240 focused Git/restore/native-finalization tests pass. A
PostgreSQL/filesystem fault-injection test also verifies retained files,
failed run, service-owned recovery barrier, no preservation receipt and
no new wake.
- Red/green: duplicate metadata produced 47 Git process starts before
deduplication; the bounded-work regression now passes. Oversized byte
and boundary inputs fail before Git probes.
- Recovery red: both reusable lease policies exhausted recovery despite
a selected accepted successful result. The assembled
PostgreSQL/filesystem path now passes for retained and both reusable
policies, including idempotent re-admission after exhausted automatic
recovery, saved files, no agent wake, and once-only existing-result
finalization.
- Source verification controls reject ordinary reusable leases,
rejected/failed/unselected results, another physical allocation owner,
and an active host writer without changing recorded state.
- The 78-test PostgreSQL/filesystem recovery/source suite passed before
the metadata classification correction. Its new persisted
metadata-failure regression also passes. Full workspace typecheck and
build pass at final head `69f10daab2`.
- `node scripts/check-maps.mjs` and `git diff --check` pass.
- Full local `pnpm test:run` attempts did not finish. They are not
counted as passes. Early focused runs exceeded 5-second and 30-second
fixture deadlines; the final serial suite passed all 176 tests with a
30-second per-test budget in 56.8 seconds.
- Red/green: both bounded PostgreSQL projections dropped the new code in
oversized results. All 19 source/projection cases now pass, plus an
actual index-predicate test that excludes a metadata repair hold and
still selects ordinary cancelled work.
- Red/green: an oversized sender `.git/shallow` lost its error type
before host validation. The real transport test now verifies one typed
rejection, no shallow-payload read, and an unchanged host tip. All 465
command/sandbox/task-chat tests pass, and token/migration gates pass.
- Full typecheck/build pass after these final contract corrections at
`69f10daab2`; all 20 PostgreSQL source/projection/index contracts pass.
All current-head CI checks passed; Greptile is 5/5 with no unresolved
review threads. Merged #18230 supplies the CI-cache and Linux
shell-fixture baseline repairs; their duplicate changes have been
removed from this PR. The final Runner lane passed after one justified
rerun of an unchanged authentication fixture timeout (all 11 fixture
tests also pass locally). Previous CI failures and incomplete local runs
remain recorded; live deployment and retained-run recovery remain
separate verification.

## Risks

- The fallback creates a temporary shared bare clone. Metadata is
limited to 64 KiB and 256 unique boundaries, duplicate/parent probes are
cached, and Git import has a 60-second command budget plus a separate
15-second boundary-probe budget. It runs only after a missing-history
import failure.
- Incorrect boundaries could hide real host ancestry. The importer
retains available parent connections, and regressions cover that case.
- The full-bundle fallback can transfer a bundle twice. This preserves
the existing fast delta path; removing that extra transfer is outside
this correctness repair.
- Preservation eligibility expands only for completed native exports on
reusable leases. It creates no provider turn and leaves ordinary
reusable leases ineligible. Database/filesystem regressions cover result
selection and competing physical/host ownership.
- The migration rebuilds one partial index; no tables, columns or user
records change. There are no agent execution admission, model, trust,
recovery permission, workflow or lockfile changes.

## Model Used

OpenAI Codex, GPT-6, with reasoning, code execution, and browser tools.
The exact serving variant 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-29 20:02:53 -05:00
Nicky LeachandPaperclip 1d571de5f9 Add shared native turn attribution boundaries (#18213)
## Thinking Path

> - Paperclip manages work performed by AI agents.
> - Native execution crosses the plugin worker, Runner, sidecar, and
durable event boundaries.
> - Existing outer spans leave repeated preparation and admission work
unattributed.
> - Optimizations need a common baseline with accurate ownership and
event meanings.
> - This change extends the existing opt-in tracing contract with
bounded timing receipts.
> - It preserves execution policy and keeps provider internals opaque
where the API provides no timing proof.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Attribution of native task preparation, retained/cold Runner handoff,
and completion-to-text work.

**Current behavior**
Worker spans use a flat provider contract. Workspace calls lack a
consistent dispatch envelope. Submitted-to-started timing is named as a
provider queue even though it includes other work. The transport does
not expose a shared breakdown of its waits.

**Proposed improvement**
Add invocation-scoped nesting, bounded numeric remote receipts,
current-run transport timing, durable receipt intervals, and distinct
completion/text milestones. Reuse the existing exporter. No latency
optimization is included.

Related public work: #17842 consolidates existing startup tracing tests;
it does not add this runtime coverage.

## What Changed

- Extend the optional SDK tracer with nested async scopes and completed
timing receipts. Keep the host responsible for parent identity,
capability checks, attributes, clocks, depth, and count limits.
- Add dispatch and bounded host-read timings for environment and
workspace providers.
- Resolve transport parents on each call so retained sessions do not
retain an earlier run's trace.
- Split cold/resume/attach/prepare/registration/command/started-event
waits. Add opt-in numeric ACPX Runner/sidecar status and prompt-start
receipts.
- Distinguish first completion request, validated tool receipt, final
result commit, first nonempty text, and event persistence. Rename the
submitted-to-started interval to match its meaning.
- Link completed earlier remote lifecycles to their host-owned observer
rather than placing them under a later polling request. Preserve
sampling, timestamp limits and budgets.
- Document the versioned coverage map, causal clock limits, and baseline
acceptance requirements.

## Verification

- Current head: GitHub CI is fully green. Standard Greptile and Apex are
both 5/5, with no unresolved review threads. Full-suite validation was
performed in CI; follow-up local validation was limited to affected
packages and tests.

- Review follow-up: early rejection, missing provider capability and
startup-parent regressions were reproduced and fixed. The affected
worker/SDK/timing set passes 128 tests; 28 timing/context tests, SDK
typecheck and direct server TypeScript checking pass. The server
typecheck wrapper reached an unrelated Runner rebuild and stopped
because Cargo was absent from PATH; full Runner/image validation remains
in CI.

- CI failure accounting: the earlier Turbo cache/force conflict and
Linux OpenCode shell assertion were reproduced and diagnosed. A direct
proc probe ruled out permissions; a portable shell comparison identified
Bash skipping BASH_ENV with stripped SHLVL and socket stdin. Upstream
#18230 now supplies the CI and ignored-stdin fixture fixes; this PR
adopts them without duplicate CI changes. The strict Linux OOM assertion
passed before this source-equivalent merge.
- Retry follow-up: the three insertion/replay/failure timing cases and
server typecheck pass. The existing database regression now asserts a
single marker across identical result replay; the current-head CI
integration gate passes.
- Upstream CI alignment: all three real-Turbo 2.11.10 integration cases
pass. The repository policy gate rejected committing a generated
lockfile; the final PR contains no lockfile edit and uses the maintained
inline stale-lockfile recovery.
- Linked-lifecycle follow-up: 44 focused host/export tests pass (three
optional SDK-dependent cases skip); SDK and server typechecks pass. The
API contract test verifies an explicit root context, host-owned observer
link and unsampled suppression.
- SDK typecheck and focused worker/invocation tests: 30 passed,
including clock changes, bounded legacy IPC, and manual-span
creation-scope parentage.
- Focused reviewed host/native/transaction-boundary checks: 44 passed.
The 86-test worker-manager suite passes after updating its exact
assertions for the host-owned timing budget found by CI. Earlier
preparation/first-text checks also passed.
- Affected server and Runner TypeScript checks pass after building local
workspace declarations.
- Merge follow-up: the profile/candidate startup subset passes 94 tests,
the four Grok source-identity checks pass, and Runner TypeScript
checking passes. A subsequent execution-factory merge passes 21 focused
timing/trace tests and server TypeScript checking.
- Pinned Rust build and the ACPX Rust subset pass. The hostile receipt
projection test passes. Source profile compatibility checks: 127 passed,
one existing skip. Grok identity checks: four passed.
- Broad transport/ACPX suite: 410 passed after building all fake
provider binaries. Earlier attempts failed on missing
Runner/fake-provider outputs; building the required fixtures resolved
those failures.
- The first CI run correctly rejected stale source attestations. After
integrating current master, Grok advances 13→14 and Copilot 84→85;
master’s historical fixtures and Pi 35 stay byte-identical. Provider
dependencies, models and permission defaults are unchanged. Identity
generation/checks now pass.
- The added real-Postgres result lock regression could not initialize
its local embedded cluster. The insertion/replay/failure unit
regressions pass. The current-head CI integration gate passes.
- Comprehensive repository checks and image builds are delegated to CI,
as requested for this instrumentation pass. No deployment, model run,
collector-ingestion proof, or latency improvement is claimed.

## Risks

The new SDK methods are optional. Legacy span calls and endpoint-off
behavior remain supported. The host accepts only closed timing names and
bounded attributes. Remote durations are anchored at local receipt;
transport/scheduling uncertainty remains explicit. Trace trees have
count/depth limits. The first rollout must inspect actual collector
exports before treating the baseline as accepted. Fresh live
qualification for the new source identities remains a rollout
requirement. Revert these commits to remove the new measurements; no
schema migration is required.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and local code/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 described the issue in-PR following the enhancement
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 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] Standard Greptile and Apex are both 5/5, with no unresolved
findings
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 17:45:56 -07:00
DottaandPaperclip 2aa3ea47e3 Reduce restored workspace overhead and trace cache publication (#18240)
## Thinking Path

> - Paperclip runs agents in isolated workspaces.
> - A native sandbox turn must restore its workspace before the provider
starts.
> - Restored Git metadata can cause expensive work in the provider's
first snapshot.
> - Cache replay also hashes the same archives twice, and workspace
helpers open sessions that do not need output.
> - This pull request removes that repeated work and refreshes the
restored index before OpenCode starts.
> - It also adds cache-publication timings so the next measurement can
separate quota checks, lock waiting, and archive IO.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Native sandbox workspace preparation and copyback.

**Current behavior**

Cache replay validates shared archives, copies them, and validates them
again. Exit-status-only helpers use persistent sessions. A restored
checkout can make OpenCode's first snapshot recheck much of the
repository. Cache publication has an unexplained interval after archive
verification.

**Proposed behavior**

Validate the private archive copy that staging will consume. Use the
existing one-shot command path for helpers that only need an exit
status. Refresh the Git index after workspace transfer for a new native
OpenCode sandbox. Keep the refresh inside the awaited inbound barrier
and use the existing command timeout. Add nested publication spans.

**Reason and benefit**

Two matched local component pairs reduced preparation plus provider time
from 8.563/8.553 seconds to 7.313/7.511 seconds, including the refresh
cost. Two alternating remote copyback pairs reduced the median from
9.110 to 7.943 seconds. These are component results. They do not
establish an end-to-end hosted improvement.

Related: #18181 and the earlier closed #18195. This implementation uses
the existing fully awaited transfer boundary. It does not use an
optional preparation deadline.

## What Changed

- Materialize cache hits into caller-owned staging and validate those
exact bytes once. Remove incomplete copies on failure.
- Select the existing one-shot path for exit-status-only run and removal
helpers. Output-reading helpers keep their existing behavior.
- Refresh restored Git stat metadata before OpenCode starts. Enable this
only for newly acquired native OpenCode host-current workspaces. Skip
recovery and retained sandboxes. Keep dirty files unstaged, accept Git's
dirty-worktree status, and propagate real command errors.
- Trace cache capacity checks, eviction, the body after lock
acquisition, archive copy, sync, and hashing. Keep the operator endpoint
gate and bounded phase names.

## Verification

- On the rebased branch: 202 focused tests pass: 152 workspace
seed/cache/runtime tests, 27 managed command tests, and 23 native
workspace/tracing tests. Adapter TypeScript build and server typecheck
pass.
- Tests cover corrupted copies, cache changes after private
materialization, dirty working trees, quoted paths, recovery, the
awaited refresh barrier, real command failure, and company-lock
contention.
- A real-filesystem probe through the server phase mapper verified
parentage and endpoint-off behavior. A controlled lock wait stayed
outside the locked-publication span. No external export was used.
- A full local Core/Daytona replay on the pre-rebase implementation
saved its synthetic reply. It retained the pinned large public
workspace, all 209 skill files, positive Git context, and 66 tool
schemas. Both model calls stayed on sandbox loopback. Index refresh took
0.644 seconds and the first provider snapshot took 0.499 seconds. The
run took 162.004 seconds, including large laptop uploads; it is not a
hosted acceptance result or a matched end-to-end comparison. The failed
installer attempt remains recorded separately. Normal cleanup removed
all owned sandboxes.
- The current head passed 53 CI checks, with two optional skips.
Greptile is 5/5 on the exact head, with no open review threads. No
deployment or hosted latency claim is included.

## Risks

- Index refresh adds one awaited command. It uses the existing timeout.
A real Git failure stops preparation.
- Cache hits need temporary disk space for a private copy. Existing
corruption fallback and per-run recovery archives remain.
- One-shot command transport must preserve exit status and timeout
behavior across providers. The agent's native session and output-reading
helpers are unchanged.
- Local component gains are small relative to the remaining hosted
latency. Batch the fixes with the diagnostic spans; measure the actual
deployed path before claiming success.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The session does not expose the exact model SKU 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-29 19:32:28 -05:00
DottaandPaperclip 6a67471644 Require publication for explicit JSON file outputs (#18228)
Extend the native file evidence rule to explicit JSON creation and publication requests, with conservative input and destination handling and a real PostgreSQL completion regression.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-29 19:17:46 -05:00
DottaandPaperclip 1e984cc9ca fix(runner): guide missing deliverables to the task workspace (#18226)
Explain missing task-workspace deliverables and preserve safe remote file errors across output streams. Keep the existing file confinement and granted-location contracts.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-29 18:34:08 -05:00
DottaandPaperclip 61bd4ac691 feat(agents): set up Antigravity with saved Google subscriptions (#18189)
## Thinking Path

> - Paperclip manages agents and their work.
> - Users choose providers and managed accounts while adding agents.
> - Antigravity was missing from the ordinary additional-agent picker
and its saved Google path did not complete native readiness.
> - A user needs a successful Test, an enabled task action, and a stable
account binding.
> - This pull request connects the ordinary setup flow to the native
candidate.
> - It also preserves retired credential refreshes across database
failures and server restarts.

## Linked Issues or Issue Description

Built on merged #18188 and #18187. Refs: #12503, #14938 for related
legacy CLI proposals.

**Agent or provider**

Google Antigravity ACP 1.4.3.

**Why this adapter is useful**

Users need to set up an Antigravity agent and run real work through
their managed Google subscription.

**How the agent is invoked**

Native Paperclip Runner uses the pinned Antigravity ACP runtime. Exact
operator admission remains required; the local candidate result does not
enable general release.

## What Changed

- Show Google Antigravity in the ordinary adapter grid and preserve the
draft choice when setup resumes.
- Reuse the same user’s saved personal default Google subscription and
discover the exact low model through the native account.
- Run a prompt-free native Test and wait for authoritative readiness
before enabling task assignment.
- Carry the managed account through native runs and recover retired
refreshes through the existing encrypted, fsynced journal with exact
generation checks.
- Retain the latest rotated credential through verification, storage,
and partial home-removal failures. Retry the exact account’s retained
cleanup before another provider use.
- Reconcile cleanup before taking the credential mutation lock, fence
owners arriving during lock acquisition, and support nested lock holders
without a join cycle.
- Bound sign-in retirement outside database transactions and preserve
claims for the existing cleanup owner; one pending sign-in does not
block unrelated accounts.
- Cover Gemini and Pi API-key recovery, keep API-key bulk manual-model
editing usable, and keep adapter discovery available after candidate
expiry.
- Skip taskless native timer work before run or credential admission.
Preserve current master monitor and deadline scheduling.

## Verification

- The registered local saved-Google-subscription journey passed all 16
matchers in 196,520 ms using eval source `12aba` against actual serving
source `4a37ee7c`. Both turns stayed in one conversation, produced exact
downloaded files of 61 and 119 bytes after reload, and used distinct
native primary processes. All observed owners retired, leases released,
and credential fences settled. Independent readback confirmed Done work,
no active owned runs, a connected saved account, and the retained agent
paused for inspection.
- The measured runtime is production-equivalent to pre-restack
`65ef31dc` except its test-only transport fixture correction.
Current-master head `ff7c9249` preserves all 99 product paths: 98 exact
blobs and only eight inherited plugin-panel lines in `agents.ts`. Its
native binary was rebuilt for inherited Codex-only diagnostic changes;
the changed Rust behavior is outside Antigravity's ACPX execution path.
Shared native/UI changes have focused regression coverage. The recorded
live result is not represented as a measured replay of `ff7c9249`.
- Full workspace build and typecheck passed on `ff7c9249`. All 376
focused tests in 14 files passed, covering Google credential/retirement
controls and the inherited native-tool, redaction, route, and UI
recovery changes. Token gates, maps, and diff checks passed. The
required-close fixture was separately demonstrated red, then passed all
317 selected provider-wiring cases.
- [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/40959387972)
is green: 55 successful checks, two skipped workflow checks, and an
optional neutral review check. Required `ci / verify` and `ci / e2e`
passed. Greptile and Paperclip Review both report 5/5 on exact
`ff7c9249`, with zero unresolved review threads.
- This qualifies the selected operator-authorized local
saved-subscription candidate. The original exploratory journey remains
historical evidence; the repeatable fixed-driver eval is in the next PR.

## Risks

- Google refresh recovery must preserve the exact grant, account, and
credential generation. An uncertain native owner or failed encrypted
handoff retains the private home and blocks cleanup.
- A successful local saved-subscription candidate does not qualify fresh
OAuth, API keys, Cloud, Linux, other models, or general release.
- Timer filtering changes only taskless native Runner admissions.
Existing task-bound monitors and legacy adapters retain their owners.

## Model Used

OpenAI Codex (GPT-6). The host did not expose the exact model revision
or context limit. The model used tools for code edits, tests, and
review.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (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-29 16:51:50 -05:00
Nicky LeachandPaperclip 35ab90ad0f Map runtime activity to authorized task plugin panels (#18131)
## Thinking Path

> - Paperclip manages agents and tasks.
> - Plugins contribute views to the task sidebar.
> - A ready view can belong to an earlier task.
> - Runner records activity under its authenticated run.
> - This PR maps that activity to installed task-panel declarations.
> - The sidebar checks readiness after current-run use and restores use
after reconnect.

## Linked Issues or Issue Description

Builds on merged contract #18129 and Runner publisher #18050. This PR
targets
master and is ready for review. Earlier combined verification is
retained in
[the verification
archive](https://github.com/paperclipai/paperclip/pull/18050#issuecomment-6489369676).

**Subsystem affected**

Run-event reads, plugin task contributions and the task sidebar.

**Problem or motivation**

Readiness polling can show a view left ready by another task. Reload and
reconnect must recover current-run use without losing concurrent live
activity.

**Proposed solution**

Map recorded activity to installed task-panel declarations. Merge
authorized
history and live activity, then perform bounded readiness checks for the
running agent. Preserve the existing read-only view.

## What Changed

- Add optional `{ namespace, activityKey }` activation mappings to
task-panel
declarations. Legacy declarations remain valid but contribute no task
panel.
- Add `view=plugin-panels` to the existing run-events route. Preserve
run-read and
telemetry-read authorization, secret redaction and private-run denial.
Map
activity to installed contributions and return at most 128 panel
identities.
- Scope activation caches to current panel versions and activity
declarations.
Preserve unchanged panels during unrelated plugin updates and history
reads.
- Merge history and live hints without losing concurrent activations.
Filter by
  company, task, run and agent. Restore history on mount and reconnect.
- Replace periodic availability checks with up to three readiness
attempts after
activity. Fresh activity restarts settled transient failures. Pending
checks,
  successful readiness and HTTP 4xx failures are left alone.
- Reuse live run updates with the panel cache key. Recover only panel
history
after a pending subscription read. Mark expected not-ready query results
so
  the global error reporter skips them; real failures remain reportable.
- Preserve current-run dismissal and the read-only plugin view. Update
manifest
  comments and producer/consumer documentation.

## Verification

- Current head: `5e04d757c`, based on master `09c05c550`. Range
comparison
confirmed all six feature commits were unchanged by the rebase. The
final
follow-up keys readiness by the plugin installation ID and availability
path.
- `cd ui && node ../node_modules/vitest/vitest.mjs run
src/hooks/useTaskPluginPanels.test.tsx`
— all 45 cases passed. `cd ui && node ../node_modules/typescript/bin/tsc
-b` passed.
- The shared query-client and live-update recovery selection passed 96
cases on
  `49c544cd2`. Token gates passed before the final hook-only changes.
- Earlier focused verification passed 57 manifest cases, 69
database/history cases,
event-registry cases and route authorization cases, including
private-run denial.
- Regression coverage includes subscription/history races, task changes
during
recovery, unfocused run completion, bounded readiness retries, denied
reads,
expected not-ready responses, changed activity mappings, unchanged panel
preservation, old cache scopes, and same-version route or installation
changes.
- [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/40942001707)
passed: 54 successful checks, two skips, no failures or pending checks.
- [Standard and final
review](https://github.com/paperclipai/paperclip/pull/18131#issuecomment-6489842168)
both scored 5/5 on `5e04d757c`. The final review used the Apex tier,
added no
comments, and left no unresolved findings. The PR is conflict-free and
ready for review.
- Local checks stay targeted. GitHub CI provides the broad build, test,
typecheck,
browser and Runner coverage. No deployment or live-provider acceptance
is claimed.

<details>
<summary>Retained failures and recovery evidence</summary>

- `ac9329548` twice failed a browser reload assertion while conversation
history
was concealed. Master fixed its readiness wait in #17923. The approve
journey
then passed locally on `fea63a418` with installed Chrome (1 passed, 39
seconds).
All eight browser shards passed in later CI. The browser test is outside
this diff.
- A canary checkout failed with Git HTTP 408; its unchanged-head retry
passed.
- `de07d09fa` failed the mobile Cases card click after a ten-second
stability wait.
The same read-only journey passed locally on that exact head (1 passed,
26 seconds).
Its unchanged-head CI retry passed 22 cases, with one skip. The original
artifact
  is retained; the cause of that click timeout is not established.
- [CI on
`49c544cd2`](https://github.com/paperclipai/paperclip/actions/runs/40903679075)
passed 54 checks with two skips. CI also passed on `de07d09fa` after the
recorded retry.
- The `1e59ab441` merge checkout passed all browser and server suites.
Runner
shard 2 passed 2,252 cases and timed out waiting for a
controller-recovery command.
The test had landed on master in #18161 after the former branch base.
Rebasing
aligned the local checkout with that code; Runner shard 2 then passed on
`fcf7380d3`.
The original timeout cause remains unproven; no unrelated timeout was
changed.
- [CI on
`fcf7380d3`](https://github.com/paperclipai/paperclip/actions/runs/40940235193)
recorded runner shutdown signals in typecheck and a workspace shard. A
chat
recovery test observed a null wake deadline, and one Runner transport
fixture
failed during close. Those separate assertion failures remain
unexplained.
All of those jobs passed on the final readiness-key head. Those later
passes
establish recovery; they do not prove the cause of the earlier assertion
failures.
- Local browser setup first stopped at pnpm version-download
verification, then a
sandbox IPC restriction, then a missing bundled browser. Installed pnpm
9.15.4
  and Chrome completed the journeys. No dependency files were changed.
- Earlier optional-property TypeScript errors were corrected. Embedded
PostgreSQL
needed its install hook run from its package directory. Older CI also
recorded
fixture-cleanup lock timeouts, attention-fixture timeouts, and canceled
server
shards after runner shutdown. The parent fixed its FIFO snapshot-copy
failure
before merge. The linked verification archive retains earlier combined
evidence.

</details>

## Risks

Activity is a hint and grants no access. Missing plugins, denied reads
and
unavailable views contribute no panel. Older runs without activity
records show
no task plugin tab. A used view stays available for the running task;
reconnect
reconciles readiness. Matching producer and consumer builds are
required. No
migration, dependency, image publication or deployment is included.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools and code
execution.
The exact serving snapshot 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
- [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-29 13:56:48 -07:00
DottaandPaperclip 9e09d8f51f fix(runner): clarify native approval argument recovery (#18205)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - First-task onboarding requires a saved human proposal decision
before child work can start.
> - Native proposal tools reject interaction metadata placed outside
their advertised schema.
> - The existing rejection text focuses on question forms and does not
explain the misplaced approval metadata.
> - This pull request explains the field placement and keeps approval
recovery in its original confirmation or checkbox kind.
> - It also retains safe schema guidance in the run log so operators can
identify the rejected field.

## Linked Issues or Issue Description

Refs: #18025 for native first-task proposal recipes and #16889 for safe
native schema guidance. Related open PR #18105 changes separate server
API-client guidance.

**What happened?**

A native first-task confirmation copied `version` and
`supersedeOnUserComment` to the tool root. Both belong inside `payload`.
The runner correctly rejected the call before execution, but its
feedback described question forms. Later calls kept the misplaced field
and changed the approval into a question. No proposal card was created.
The run log retained only a generic schema error.

**Expected behavior**

Keep strict validation. Explain the nested field locations. Keep a
confirmation or checkbox approval in that kind while correcting its
arguments. Save the normal pending card and wait for an actual human
decision. Retain bounded schema guidance without storing rejected input.

**Steps to reproduce**

1. Send an otherwise valid native confirmation with root-level `version:
1` and `supersedeOnUserComment: false`.
2. Observe the pre-dispatch `invalid_tool_call` rejection.
3. Move both fields into `payload` and keep `interactionKind:
"confirmation"`.
4. Verify that the corrected call creates one pending confirmation,
exact replay creates no duplicate, and child creation still needs saved
human acceptance.

**Paperclip version or commit**

The observed argument shape and initial regressions came from public
source base `c32e1ba6`. The repair is based on maintained master
`4a6f6a65`. Public tests use synthetic prompts and identifiers.

## What Changed

- Give rejected confirmations and checkboxes approval-specific guidance.
It names `payload.version` and `payload.supersedeOnUserComment` without
suggesting a question-form recipe. Other human-input errors retain
complete question-form guidance and stable question/option ID
instructions.
- State the allowed native root fields in the first-task skill and put
the metadata inside both executable proposal recipes.
- Retain the existing safe guidance in `semantic_tool_denied`
diagnostics. Keep the original rejection identity and
`paperclipExecuted: false`.
- Preserve only the exact bounded scalar diagnostic payload after
verified event admission. The rest of the envelope and all API
request/result bodies keep their existing redaction.
- Add a real native Codex transport regression and strengthen
advertised-schema, card replay, human-admission, persistence, and
privacy controls. Update the execution contract and onboarding maps.

## Verification

- Red: the native transport reproduced the malformed confirmation and
showed that the old hint omitted the metadata correction. A second red
confirmed that approval guidance still included the question-form
recipe. The corrected transport case now rejects before execution,
retains a safe hint, and dispatches one corrected confirmation that
returns a pending card.
- Red: both shipped recipe checks lacked explicit nested metadata. All
49 first-task admission tests now pass, including advertised-schema
validation, idempotent card replay, actual human acceptance, agent-only
rejection, and question-answer controls.
- Updated native checks pass on the current repair: 95 native Codex
transport tests with 2 existing ignored cases, all 32 provider-bridge
tests, and the schema-feedback unit control.
- API/case persistence regressions were red before the event-boundary
correction. All 71 affected port/redaction tests pass in a clean run at
frozen head `3be3a70f`, including the corrected envelope privacy
regression. The focused 16-test persistence/privacy group and server
typecheck also passed earlier.
- Full local `pnpm build` and `pnpm -r typecheck` pass at exact head
`3be3a70f` in a clean detached checkout with Node 24.22.0 and pnpm
9.15.4. Exact-head CI passes: [full PR
CI](https://github.com/paperclipai/paperclip/actions/runs/40950360142)
and [isolated native Runner
readiness](https://github.com/paperclipai/paperclip/actions/runs/40950359835).
- The full local unit attempt recorded a 15-second timeout in the
unrelated Microsoft Teams 100,000-character existing-comment publication
case. That failure remains recorded. The exact isolated rerun passed (1
test; 1,814 unselected). The aggregate timeout cause is unproven. That
long local run straddled subsequent source edits and also observed the
two port regressions during their red phase; it was stopped and is not
final-head evidence. The clean affected-suite run above and current-head
CI provide the final verification. No timeout or assertion was weakened.
- Release-registry CI initially rejected the native test's compile-time
schema include outside the release crate's hashed input closure. The
guard was reproduced locally. The test now reads the current canonical
schema at execution. All 10 crate-cache controls and the real native
approval regression pass afterward; the cache guard and workflow keys
remain unchanged.
- Current-head Greptile review is 5/5 with no unresolved review threads.
All required checks pass (56 success, 4 skipped). The advisory Paperclip
Review remains neutral/incomplete after one normal re-review request; no
completed assessment or score is claimed.
- `cargo fmt --check`, map structural checks, and `git diff --check`
pass.
- Source and scripted-provider checks do not prove that a model will
follow the guidance. The original live onboarding attempt remains
failed; acceptance at a deployed revision is separate work.

## Risks

- This changes repair guidance and shipped instructions. It does not
make malformed arguments valid or supply a human decision.
- Diagnostic retention adds no rejected arguments, values, or unknown
input keys. The API receipt allowlist is unchanged. The validated-event
exception restores only the safe scalar payload; optional debug and
other envelope metadata still pass through redaction.
- The existing 512-byte guidance bound, strict tool schema, company/run
binding, idempotency checks, and proposal admission remain effective.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex, with tool use and code
execution. The context-window size is 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-29 15:48:37 -05:00