Commit Graph
184 Commits
Author SHA1 Message Date
Nicky Leach e2cfdc7e0c feat(plugins): expose GitHub credential broker to task providers (#18178) 2026-10-29 10:52:44 -07:00
DottaandPaperclip f1911a4c53 perf(skills): move repository packages out of Postgres (#18082)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/205/changes/paperclip/205
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents receive selected company skills before each turn.
> - Imported skills can need files from the whole source repository.
> - The current path stores those files in Postgres and reads large JSON
payloads during preparation.
> - This pull request stores verified packages in the configured file or
object store and keeps preparation queries small.
> - It also converts old rows automatically and restores missing files
from the exact saved commit.
> - The result reduces database traffic while preserving skill versions
and repository dependencies.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Company skill import, version storage, and preparation before agent
turns.

**Current behavior**

Repository snapshot bodies live in JSONB. Skill preparation can read
those bodies again even when the files already exist on disk. Historical
packages and native assets also need a bounded cleanup path.

**Proposed behavior**

Store package archives and manifests through the existing storage
service. Keep version identities, receipts, hashes, and recovery
metadata in Postgres. Convert legacy rows after the stored package
passes read-back verification. A missing package can use legacy bytes or
its exact Git commit under current repository authorization. No separate
data-migration command is required.

**Reason and benefit**

The warm path sends no repository bodies through SQL and reads no object
bytes. Cleanup runs through the existing deadline coordinator. Current
versions, active runs, explicit pins, and authored content retain their
protection.

**Breaking changes**

The normal application schema upgrade is required. Single-version and
skill-file responses keep their existing shape. Version lists,
current-version summaries, and test-run version summaries now contain
file names and kinds without file bodies. Diff and restore fetch
selected versions through the existing single-version endpoint. Older
server builds must not write after conversion unless they support the
new package format. The storage override and rollback limits are
documented in `doc/skill-package-storage.md`.

**Additional context**

Related work: #15731 preserves repository dependencies; #17923 changes
version-cache scheduling; #18080 changes delivery to remote Codex homes.
This change owns package persistence, acquisition, and expiry. It does
not replace those delivery or scheduler changes.

## What Changed

- Add company-scoped archive receipts, exact-commit recovery recipes,
migration deadlines, and a durable object-deletion queue.
- Add bounded archive upload, read-back verification, extraction,
concurrent request coalescing, and verified local caches.
- Convert old snapshots and versions automatically. Keep legacy bytes
when verification fails.
- Recover missing files through current source authorization and the
original commit. Validate repository identity, file hashes, modes, and
the aggregate hash.
- Expire unused recoverable Git packages and native assets after 30
days. Preserve active pins and the durable copy of authored or unproven
content.
- Keep warm preparation queries metadata-only. Bound file digest caches
and avoid repeated body hashing when file identities are unchanged.
- Extend the existing storage contract with cancellation. Register
package work with the existing coordinator. Optional conversion retries
retain the original bytes and may wait for ingress without blocking
sleep.
- Add regression tests, operating guidance, a deep trace, benchmark
receipts, and an optional maintenance command.

## Verification

### Final master integration and review repair — October 29, 2026

Current head: `a6065424249e763dfeac37161f1b52a9f25bd9b7`. Commit
`f8bbdd3dbd` resolves the conflicts with master `76a796e964`; the final
two commits repair the Apex deletion findings below.

- Keep both package-maintenance and version-retention notifications in
their write transactions.
- Keep the shared run-pin predicate and master's controller-lease
deadline metadata. Package expiry reads the updated protected-version
result.
- Preserve every master migration entry. Generate migration **0415
(`0415_zippy_zemo.sql`)** after master's 0414. Its skill SQL is
byte-for-byte unchanged from the previously tested idempotent migration.
Retain only the five newest schema snapshots. Migration numbering and
safety checks pass.
- Repair failed file/folder deletion: preserve a complete temporary
subtree until transaction commit, restore on upload or SQL failure, and
restore callback failures before releasing the mutation lock. Both
PostgreSQL regressions reproduced missing files before the fix and now
pass. They cover binary data, executable permissions, empty folders,
unlisted files, unchanged database/version rows, successful retry after
upload-claim expiry, and historical reads.
- Reconcile lost commit replies under the same advisory and row locks.
Check the saved version and source identity before restoring. Keep
committed deletions intact and preserve backups when the database
outcome is unknown or a newer edit exists. Four real-PostgreSQL outcome
tests pass; the prior code failed three of them.
- Full workspace typecheck and production build pass on the final
commit. All **204** focused PostgreSQL package/cache/retention/authoring
and filesystem-boundary tests pass, with none skipped.
- Apex review **18 passes 5/5**, with zero new comments on the exact
final head. All **34** review conversations are resolved.
- [Final-head
CI](https://github.com/paperclipai/paperclip/actions/runs/40914116508)
completes successfully on attempt 2. The head has **55 successful
checks**, two neutral reports, two skipped checks, and a successful Snyk
status. No checks are pending or failing. All eight browser shards pass.
- Runner Vitest 2/2 timed out once in the unchanged ACPX
controller-replacement fixture. The same job passed on the preceding
commit. One unchanged CI retry passes all five ACPX recovery cases,
**2,253** Runner package cases and **126** native server integration
cases; their standard one and five skips remain. The initial timeout's
root cause is not established. Local diagnosis also hit the fixture's
eight-second session.open timeout with an authenticated Runner; no local
Runner pass is claimed.
- Both full local `pnpm test:run` attempts were stopped when Apex
identified deletion defects and source repair became necessary; neither
is claimed as a passing full local run. The final **204** focused tests,
full workspace typecheck, and production build pass. Full-suite
acceptance uses the final-head CI jobs. The superseded merge-head CI
included runners terminated by shutdown signals; each source repair
started a new full run.

- Auto-merge is enabled for squash merge. The final head is
conflict-free and all checks pass. GitHub's active master ruleset still
requires a code-owner approval for the dependency files. The existing
review requests are with `devinfoley`, `nickyleach`, and `forgottendev`;
no policy bypass was used.
- The earlier hosted stress and full native receipts below remain tied
to `a2e597d800`; they are not relabeled as a deployment of this final
integration. The earlier local PostgreSQL startup failure remains
recorded below; PostgreSQL ran successfully for this integration
verification.

### Full native skill execution — October 29, 2026

The full native-agent acceptance gap is closed on candidate
`a2e597d800eb989d565780e7aa947d5368676444`. Two qualifying native turns
used OpenAI API / `gpt-5.4-mini` in real Daytona sandboxes, on the same
disposable hosted TEST tenant as the stress test. A follow-up on the
same task consumed a newly saved skill version.

The task text asked for the assigned skill workflow. It did not contain
the proof nonce or expected receipt. The assigned authored skill
contained a Python verifier and a random package-local nonce. The agent
read the actual installed skill files and executed that verifier against
the imported, automatically converted 1,360-file repository package. It
checked the repository file count and reference/binary bytes, and
directly executed the repository's executable probe. Independent
verification matched the emitted JSON to the nonce and expected byte
hashes. The agent persisted the same receipt as its task response;
native finalization committed, workspace finalization succeeded, and
task state became Done.

| Qualifying turn | End-to-end run time | Recorded skills.prepare |
Repository files | Binary hex | Shell receipt SHA-256 |
|---|---:|---:|---:|---|---|
| Initial task | 47.881 s | 1822 ms | 1360 | `00ff07800a` |
`a1deb30dc095f2306c7aa9cc5ec396da12c68961cf5b809f4d7c20f7fc68493b` |
| Corrected follow-up, new nonce/version | 37.974 s | 377 ms | 1360 |
`00ff07800a` |
`dbcdc33fa1376b4edc136feae1cdf770560a73292467e93619efdda20e4282a7` |

Both successful shell receipts reported `probe: STRESS18082` and
`assetSha256:
e8ea7a2f15f7bb3b332a46adbef848465884c8996595aa234748befd544d1f3a`. Their
proof nonces, selected version IDs and receipt hashes differed, and both
ran on the same task. These are observed timings, not latency SLOs; they
include real provider work. The service stress-test timings remain a
separate measurement boundary.

Earlier failures remain in the evidence:

- The original five-minute Daytona allocation timeout never reached
model execution. After normal owned-stack restore, its durable cleanup
record was `expired` / `success`. The cause of that original allocation
timeout remains unknown; a later success establishes recovery only.
- Initial continuation setup used unsupported generic agent-update
fields and returned HTTP 409 before dispatch. Setup was corrected to use
the supported skill-assignment and versioned instruction commands.
- The intervening completed native turn read repository bytes and ran
the probe, but omitted the verifier JSON under the older test agent's
overly-specific instruction file. Its strict receipt validator failed;
it is not counted as a qualifying turn. Correcting the test agent's
instruction file and sending an explicit task-scoped wake produced the
qualifying follow-up above.
- The pinned application's immutable rate card omits `gpt-5.4-mini`, so
completed usage triggered the normal block-on-unpriced budget policy.
Supported append-only accounting corrections estimated the three
completed runs using the [official OpenAI model rate
card](https://developers.openai.com/api/docs/models/gpt-5.4-mini): $0.75
input, $0.075 cached input, $4.50 output per million tokens, assuming
standard processing. Estimates totaled 12.482655 cents. Original usage
and missing-price records are preserved; the $1 hard stop and
unpriced-usage guard stayed active.
- Model shell attempts included a missing `xxd` command and incorrect
guessed file paths. Those failed calls and subsequent successful actual
verifier calls remain visible in complete event streams. No
zero-tool-error claim is made.

No product source changed during this continuation. The previously
measured contention, cold-start and memory limits remain. The later
merge resolution is covered by the separate integration checks above;
these hosted receipts qualify their recorded candidate.


### Hosted stress test — October 29, 2026

**Hosted acceptance:** full native-agent execution and a changed-skill
follow-up pass on the recorded hosted candidate. The final integration
section above records the subsequent conflict resolution and its
separate checks.

Tested baseline `929e840595c8933ca485ac7a2e99413e1e11ca64` and this
exact candidate sequentially on one disposable TEST tenant, with
external Neon PostgreSQL and actual S3. The fixture contained **1,360
files / 22.4 MB / ten skills sharing one repository**. Measurements
cover deployed skill-preparation and native-context services in an
adjacent diagnostic process, not a complete agent turn. The container
had **24 vCPU / 24 GB**.

| Warm workload | Median before → after | p95 before → after | DB
returned value bytes/preparation before → after |
|---|---:|---:|---:|
| One skill, serial | 1,060 → 125 ms | 1,303 → 155 ms | 22,610,389 →
1,771 |
| One skill, four concurrent | 4,415 → 297 ms | 5,143 → 328 ms |
22,610,389 → 1,771 |
| Ten skills, serial | 5,723 → 535 ms | 6,057 → 600 ms | 224,739,030 →
10,671 |
| Ten skills, four concurrent | 24,410 → 1,986 ms | 24,833 → 2,221 ms |
224,739,030 → 10,671 |

- Candidate warm preparation performed **zero S3 GETs**. Ordinary-pool
queries fell from 16 to 9 for one skill and 61 to 9 for ten, excluding
dedicated lock connections. DB numbers measure returned values before
Drizzle decoding, not wire bytes. Baseline/candidate sample counts were
30/100, 32/100, 5/50 and 8/48 respectively; the small baseline ten-skill
samples are comparative evidence, not SLO estimates.
- **Application-UID soak:** 800 ten-skill preparations over 10.3
minutes, four workers paced by 2.5 seconds; **zero failures**, median
**559 ms**, p95 **775 ms**, p99 **910 ms**, zero warm S3 reads. All 726
accompanying health/company-list requests returned HTTP 200. Their
end-to-end p95 was 569/502 ms, including network latency. The probe
overlaps most of the soak. Soak DB-response capture was limited to its
first 60 seconds.
- **Important remaining costs:** an unpaced 16-way ten-skill burst had
p95 **8.32 seconds** because company-level preparation serializes. Cold
preparation took approximately **1.1–2.5 seconds** for one skill and
**7.4–10.0 seconds** for ten. Ten-skill diagnostic RSS remained about
**1.17 GiB** (baseline 1.18 GiB), and the soak peaked at **1.35 GiB**. A
concurrent whole-container sample was 3.45 GB. This does not establish
suitability for a small-memory host or eliminate per-entrypoint native
asset duplication.
- **Upgrade without a manual data migration passed:** legacy snapshot
JSON shrank from 22,465,691 bytes to `[]`, with a stored package and
zero pending conversions.
- **Recovery passed:** sixteen concurrent cold requests coalesced into
two S3 GETs; full bytes/binary/executable modes matched; same-size
corruption repaired; an injected storage failure preserved warm access
and failed cold access safely. A disabled public-Git source denied
recovery, and after the actual five-minute backoff its exact SHA
reconstructed all 229 files. Cross-company descriptor access was denied.
Private-Git credential revocation was not tested.
- **Retention passed:** reclaimed 27,754,496 allocated cache bytes,
deleted an unreferenced package row and both objects, preserved aged
authored history, and expired/reacquired reconstructible Git content. A
version pinned by the failed native run was correctly retained. Only
owned fixture timestamps were aged.
- **Browser UI passed:** authored skill creation, saved edit surviving
reload, version history, and restoration of earlier content.
- **Initial native attempt (superseded by the qualifying turns above):**
one real run failed at Daytona allocation after five minutes
(`setup_failed`), before any model execution. Provider cleanup also
reported failure. That attempt does not count as a passing native turn.
Its receipt and all evidence remain preserved; its cleanup later
recorded success after normal restoration.
- Initial A/B commands ran as SSH root. Diagnostic-owned lock/cache
permissions caused one setup HTTP 500 and the first UID-1000 soak to
fail; exact fixture paths were repaired. The final soak, retention and
recovery ran as application UID 1000. A fresh UID-1000 one-skill batch
also passed (30 samples, median 116 ms, p95 321 ms, 1,771 DB value
bytes/preparation). Earlier harness-export, SSH, npm provenance, backoff
and UI-wait failures remain recorded alongside their successful retries.
- Private evidence includes raw timings, assertions, HTTP probes,
screenshots and failure/cleanup receipts. Initial failed-campaign
cleanup suspended and retained the owned TEST tenant and released the
shared QA account lease at **15:22:41 UTC**. The tenant was subsequently
resumed under its existing ownership for the native execution
qualification above. Final cleanup completed at **15:53:09 UTC**: the
account lease is released and the tenant is suspended/retained under the
original October 30, 12:24:52 UTC retention deadline. Its separate stack
lease remains held; no active or pending-cleanup environment lease
remained. The original retention window is deliberately preserved even
after successful continuation.

- Earlier hosted-tested head:
`a2e597d800eb989d565780e7aa947d5368676444`, integrated with master
`929e840595`. The earlier merge conflicts were resolved at this head.
[Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/40884087629)
passed; all checks are complete with 55 successes, two neutral reports,
two skips, and no failures. [Apex review
15](https://github.com/paperclipai/paperclip/pull/18082#issuecomment-6480257258)
passed 5/5 with zero findings on this exact head. All review
conversations are resolved.
- Ten real-filesystem boundary cases and server typecheck pass locally
for the security fix. Coverage includes cache roots, descendants,
individual files, symlink aliases, recursive ancestors, a future
concurrent cache fill, and allowed sibling directories. [Current-head
private-project integration
tests](https://github.com/paperclipai/paperclip/actions/runs/40884087629/job/123483306405)
passed all 29 cases, including authorized and unauthorized imports of a
cached private package. Full typecheck, build, server suites, all eight
browser shards, and Runner checks passed in current-head CI. Local
database tests could not run because PostgreSQL could not initialize;
this limitation is recorded below.
- The earlier generated migration preserved the newest five snapshots.
The final integration renumbers its unchanged SQL to 0415. Migration
safety/numbering checks pass. Its SQL is byte-for-byte identical to the
previously verified idempotent skill migration; repeated application on
this latest schema was blocked by the same local database startup
failure.
- The broader verification before the final migration-only rebase passed
1,025 package, lifecycle, remote-launch, native-session, and
asset-retention tests, 52 focused UI tests, full workspace
typecheck/build, token gates, and map checks. The linked complete CI run
passed before the latest focused fixes.
- A disposable MinIO instance passed multipart upload, verified
read-back, and cold restoration of an 18 MB archive.
- Twenty warm samples with a synthetic 1,349-file, 22.8 MB repository
retained five metadata queries and zero object reads. Median preparation
was 256 ms for one selected skill and 691 ms for ten, with 5 ms emulated
network delay each way. These are local measurements, not production
latency guarantees.
- No production instance was changed. Earlier verification failures and
their disposition are retained below.

<details>
<summary>Earlier failures, review findings, fixes, and rerun
evidence</summary>

- The first CI pass found a stale inventory-span expectation and a
missing repository-read span. Both are fixed; all three observability
tests pass. One browser test copied page text into its YAML parser after
reload; its first unchanged-head retry passed, but the race recurred
after rebasing. The test now waits for the renamed URL and completed
reload before copying the editor, retaining its original assertions. The
earlier full local suite did not complete cleanly: it reported setup
timeouts and assertions, while isolated relevant reruns passed. The
complete current-head CI run closes that broad verification gap. No
production instance was changed.

- The first Apex review scored 2/5 and identified six issues. The fixes
protect authored history even when it shares an in-flight Git upload,
recheck upload expiry during orphan deletion, bound failed-upload
cleanup, retain per-version kind/encoding metadata, add sanitized
failure diagnostics, and correct the migration guide. The final focused
run passes all 140 tests; the preceding eight-file run passed all 149
tests, including local storage and S3 diagnostics. Server typecheck and
migration safety/numbering checks pass after the fixes. The second Apex
review scored 1/5 and found unbounded maintenance storage calls and
mismatched package/Git batch limits. Those are fixed with a 30-second
cancellable cleanup deadline, shared 100 MiB/10,000-file scanner and
storage limits, and bounded Git read batches. The proposed manual
lockfile edit was rejected with evidence of the enforced CI-owned
lockfile policy. All 19 storage/recovery unit tests and server
typechecking pass. The new database-backed cleanup/conversion tests were
locally skipped because the host exhausted its PostgreSQL semaphore
capacity (confirmed directly by initdb). That gap is closed by
current-head CI: [package-store
tests](https://github.com/paperclipai/paperclip/actions/runs/40771320775/job/123109300889)
pass all 18 cases and [package-worker
tests](https://github.com/paperclipai/paperclip/actions/runs/40771320775/job/123109301157)
pass all 7, with no skips in either suite. The corrected YAML browser
shard passes. A separate planning-fixture test failed its cleanup DELETE
with an activity-log foreign key violation after its behavior assertions
passed; its one unchanged-head retry passed. The third Apex review
scored 1/5 and identified a one-slot pool deadlock, projected path
limits, cleanup holding the preparation lock during archive reads, and a
publication/expiry race. These are fixed with transaction-local reads,
prefix-aware bounds, isolated verification, and shared package row locks
with a publication grace. The separate Paperclip review also found stale
historical inspection, eager history downloads, and conversion retries
blocking sleep. Those are fixed. Local PostgreSQL capacity recovered:
the new database regressions ran, including the one-slot fork, paused
storage during a warm turn, and a locked publication during expiry. The
expanded run passed 144/145 tests; its remaining assertion still
expected file bodies from the version list and was updated to fetch the
selected version. The corrected company-skill suite passes all 81 tests,
and the final package/projection run passes all 27. All 52 focused UI
tests pass after updating their query-provider fixtures; the first UI
run exposed a fixture remount, and the follow-up exposed an editing
syntax error, both corrected. Full workspace typecheck and build, token
gates, and map checks pass. The sandbox initially blocked the build
tool’s local IPC socket; the authorized build rerun passed. Master then
claimed migration 0401. The branch is rebased on f8226b0515, the
unchanged SQL is regenerated as 0402, and repeated application passed
twice on the combined schema. Post-rebase workspace typecheck passes.
All 1,025 package, lifecycle, remote-launch, native-session, and
asset-retention tests pass on the combined head. All CI checks passed
for head 9d80a3b52d. The fourth Apex review scored 3/5 and found a
save/edit lock-order cycle, a retry retaining an uncommitted source ID
in its recovery recipe, and a summary read racing conversion. Commit
b7d9237c6a fixes all three. The new concurrency and retry tests pass
within all 61 package/source tests, and server typecheck passes. Master
then claimed migration 0402. The branch is now rebased on 65fa1cd617 and
the unchanged SQL is regenerated as 0403. All 68 package, source, and
worker regressions, server typecheck, migration safety/numbering, and
repeated migration application pass on current head 62553671a0.
Subsequent verification and review outcomes are recorded below.


- The fifth Apex review scored 4/5 and found cached version reads
unnecessarily depending on object storage and conversion reads missing
the coordinator cancellation signal. Commit 1eb90d80be fixes both:
cached reads verify bytes without the preparation lock; manifest and
archive reads carry cancellation through conversion. The first focused
run passed 70/71 tests, including all three new cases, but the existing
diagnostic test observed no warning. Its fixture now sets an explicitly
expired migration deadline; the final worker suite passes all nine
cases. Server typecheck passes.


- The sixth Apex review scored 4/5 with one finding: concurrent cached
inventories were unbounded. Commit 4b7589e14c gives cached inventories
and previews a two-reader/32-waiter limit independent of cold storage.
The first expanded pressure test observed a third reader before the
preview path had the same bound; both paths now share the local limit.
All 73 focused cases pass, followed by all 29 package cases after the
final overload adjustment; server typecheck passes. The separate
Paperclip review found no must-fix or should-fix issues. Its optional
suggestion to persist durability verification was considered: cleanup
intentionally verifies current external bytes before discarding the last
local authored copy, and the missing-object regression requires that
check. Shared-package eviction happens on cold fills with at most two
attempts and a ten-second budget.


- The seventh Apex review reached 5/5 with one remaining P2:
timeout-bearing manifest reads bypassed request coalescing. The security
review also found repeated archive acquisition after a cold
administrative read. Commit 79a80a39d2 shares manifest loads with
per-caller cancellation and cancels the underlying work when the last
caller leaves; coalesces identical cold version/file requests; and
publishes verified restored packages into the shared cache. Publication
uses a short nonblocking lock, while eviction verification runs outside
it. The first expanded run passed 73/74 tests and exposed a missing
originating DB for cache publication inside read-only inspection;
transaction readers now pass that owner explicitly, keeping metadata on
the transaction. The corrected run passed 75/75. A final eviction test
initially expected the shared package to remain after only its separate
runtime projection was reused; it now explicitly accesses the shared
package during verification. All 32 final package tests pass, including
independent caller cancellation, one acquisition across
concurrent/repeated reads, and warm preparation during stalled eviction
verification. Server typecheck passes.


- The eighth Apex review scored 4/5 with one finding: decoded cold
inventories outlived the storage semaphore while waiting for cleanup.
Commit 9d7921d1ec adds a separate two-response/32-waiter lifetime bound
held through cleanup, preserving the independent warm-read queue and
forwarding cancellation through eviction verification. The new
regression pauses cleanup after two responses decode, verifies a third
archive stays queued, and completes warm preparation before releasing
cleanup. All 77 package/source/worker cases and server typecheck pass.
On the preceding head, serialized server shard 6/9 was interrupted with
“The operation was canceled” after 57 seconds of tests; the log contains
no failing assertion. Fresh latest-head CI reruns that shard along with
the other gates.

- The ninth Apex review scored 4/5 with one P1: cold responses could own
both permits while waiting on a one-slot ordinary database pool held by
a queued transaction reader. Commit a94f0e409f reads caller-scoped
metadata before admission and isolates all acquisition/cleanup SQL on a
private connection. The new real-PostgreSQL regression reproduces the
deadlock against the previous head and passes with the fix; all 78
focused cases and server typecheck pass. The previous CI run completed
with 54 successful checks, including both formerly interrupted/stuck
serialized shards.

- The tenth Apex review scored 4/5 with one P1: preloading legacy bodies
before admission could retain many full repositories in queued requests.
Commit 276e353a37 removes that preload and also bounds legacy manifest
derivation/fallback, using private connections inside the I/O slot. All
80 focused tests pass; the final synchronized package suite passes all
36 tests and server typecheck passes.

- Apex review 11 returned 5/5 with zero comments on 276e353a37. While it
ran, master 8bc051245f added migration 0403, creating a metadata
conflict. Merge commit e1783764d9 integrates master and generates
0404_clumsy_leo.sql; its skill SQL is byte-for-byte identical to the
previously verified migration. The combined schema passes migration
safety/numbering, repeated SQL application twice, all 80 focused
PostgreSQL tests, full workspace typecheck, and full build. The
preceding a94f0e409f CI run was superseded and cancelled while its final
runner job was active; no old-head success is claimed for that run.

- Final acceptance: Apex review 12 returned 5/5 with zero comments on
e1783764d9. All 28 review threads are resolved. The final head has 55
successful checks, two neutral reports, two skipped checks, and no
pending or failing checks; the PR workflow completed successfully.
Superseded run 40789121902 was cancelled to free its workflow slot for
the final head; normal cancellation did not finish promptly, so force
cancellation completed it.

- October 29 conflict resolution (867c00673b): master 929e840595 added
installed-selection reuse and bundled relocation, routine cleanup
notifications, a hardened YAML copy helper, and migrations through 0413.
The merge retains those behaviors together with package read scoping and
the public-selection fast path; restricted selections still reauthorize
and the full row read rechecks scope. Generated migration 0414 retains
the existing SQL unchanged. Workspace typecheck/build and migration
checks pass. Local database verification is unavailable: initdb reports
semget / “could not create semaphores: No space left on device”; all 168
cases skipped, and repeated migration application failed at startup.
Docker returned HTTP 500 during container creation, so no Docker test
pass is claimed. Current-head CI must close this gap.

- Apex review 14 scored 3/5 with one P1: a local import could copy
cached private package files into a company-wide skill. Commit
a2e597d800 rejects cache trees and ancestors through a canonical
filesystem boundary, including aliases and ancestors checked before a
concurrent fill. Ten local filesystem tests and server typecheck pass.
The existing private-project integration case now rejects package-cache
imports for both authorized and unauthorized users. The preceding merge
commit’s complete CI run passed, and logs confirm all 168 locally
skipped cases executed successfully: package store 36, sources 35,
package worker 9, runtime selection 4, observability 3, authoring 81.

- Apex review 15 returned 5/5 with zero new findings on a2e597d800. The
separate Paperclip review found no must-fix or should-fix issues. Its
optional suggestions were considered: unexpected filesystem cleanup
failures remain visible, the durable marker cannot replace checking that
bytes still exist before deleting a last local authored copy, and
administrative history batching remains outside the pre-turn
optimization. The cache-path literal centralization suggestion is also
optional; the current producer and guard use the same directory, covered
by the new integration regression. All review conversations are
resolved.

- Earlier October 29 CI/Apex acceptance: a2e597d800 was mergeable at
that check, Apex review 15 passed 5/5 with zero findings, and all review
conversations were resolved. The hosted verification above records the
later acceptance limits and renewed conflicts. Workflow 40884087629
completed successfully, with 55 successful checks, two neutral reports,
two skips, and no pending or failed checks. The project-skill-sources
job log confirms all 29 cases ran and passed, closing the latest
integration gap. The preceding merge workflow also confirmed all 168
focused database cases ran and passed. No local PostgreSQL or Docker
pass is claimed.

</details>

## Risks

- First use after eviction can require storage or Git access. Revoked
grants, removed sources, and unreachable commits can prevent
reconstruction. Recovery never substitutes a newer commit.
- Historical packages without a proven recipe keep durable bytes.
Cleanup favors retention when a run pin cannot be interpreted safely.
- New uploads and conversion use bounded work and persisted retries.
Large initial conversions still add temporary storage and database load.
- Optional cleanup can wait until the next server wake. Supported
notifications assume one owning server process.
- Per-entrypoint native tree duplication and cold preparation cost
remain. The final ten-skill cold sample took 47.6 seconds on the shared
host.
- Generic authored edits can still hold an existing edit transaction
while a package uploads.
- Explicit file/folder deletion uses temporary disk space for rollback.
An uncertain commit with a changed skill or unavailable database retains
that backup and logs its location for recovery.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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 12:19:37 -05:00
DottaandPaperclip 6a932bb979 fix(daytona): preserve workspace exports under disk pressure (#18172)
## Thinking Path

> - Paperclip manages AI agents and preserves their work when execution
stops.
> - Remote workspace recovery must save the retained files before
another executor can start.
> - Daytona directory export first writes a complete tar on the source
sandbox.
> - When that disk is full, each preservation retry fails while writing
the same temporary archive.
> - This change streams an archive after a storage-capacity failure,
without another full copy on the sandbox.
> - Existing source ownership, archive validation, and task admission
gates remain in force.

## Linked Issues or Issue Description

Related: #14402 established safe workspace export and retained-source
recovery. This PR handles the remaining temporary-archive storage
requirement.

**What happened?**
A sandbox ran out of disk space. The provider could no longer save its
state, and workspace preservation then failed with tar `No space left on
device` or `Wrote only ... bytes`. Repeating the export could not
resolve that failure because it required free space on the same disk.

**Expected behavior**
Export retained files without needing a second full copy on the source
disk. Reject incomplete transfers and unsafe archives. Preserve the
source and newer host files if export fails.

**Steps to reproduce**
Run the capacity regression with real tar and a file-size limit. The
original export fails during archive creation. The fixed export
transfers the same bytes through a real PTY. The credential-gated live
test uses a real Daytona sandbox and `/dev/full` as the archive sink to
reproduce ENOSPC without filling a provider disk.

**Paperclip version or commit**
Reproduced on `27be859044`; fix rebased onto `6d59f5ef7e`.

**Deployment mode**
Source checkout on macOS arm64; live provider verification on a
disposable Ubuntu 24.04 Daytona sandbox with SDK 0.203.0.

## What Changed

- Fall back only after archive storage-capacity errors. Keep the
ordinary bulk download path.
- Transfer 40 KiB archive chunks over a raw PTY. Wait for each host
write acknowledgement and a final receipt acknowledgement. Send long
scripts only after raw-mode readiness.
- Require successful tar exit and complete framing before the existing
host archive validator can import files. Keep the bounded safe-link
retry and exclude rules.
- Bound total archive bytes by the provider-reported disk allocation,
preserve a 1 GiB host free-space reserve, and bound terminal cleanup to
five seconds while closing the host file independently.
- Add real-tar/PTY regressions, stream failure tests, a credential-gated
provider test, and recovery documentation.

## Verification

- Red before production changes: the capacity regression failed on the
real tar write with exit 153. Green afterward: unchanged bytes, file
mode, confined links, and source files survive. A tar producer that
fails after sending bytes cannot overwrite newer host files.
- 43 focused tests pass. Missing receipts, nonzero exits, transport
loss, invalid base64, oversized frames, stalled transfers, and late
connection cleanup fail closed.
- Live Daytona test passes: stop/start, actual tar ENOSPC, matching file
hashes and modes, unsafe-link filtering, intact source, then another
stop/start and export with a later saved file. The disposable sandbox
was deleted. Initial default-sandbox creation hit account quota; the
successful test used a 1 GiB image. Large output bursts exposed a real
socket closure, corrected by bounded chunks and verified in the
successful run.
- Repository `pnpm -r typecheck` and `pnpm build` pass. `node
scripts/check-maps.mjs` passes. Standalone plugin typecheck passes.
- Standalone plugin build and final typecheck pass. The final broad
plugin run passed 482 tests, skipped seven credential-gated cases, and
hit one existing 30-second archive-listing timeout. Earlier runs hit
both large-listing cases. Both timeouts reproduce with unchanged
`file-sync.ts` from master `6d59f5ef7e`, with 22 other archive-listing
cases passing on both base and fixed source. Parallel, serial, and
GNU-tar local runs retain those timeouts. The serial local `pnpm
test:run` was stopped after 36 minutes once the complete current-head CI
test suite passed; it is not counted as a full local pass. GitHub
Actions on production-code head
`9ffbd9e56e283a01c22f005c022b8f6838cf0143` passed typecheck, all general
and serialized test shards, Runner verification, build, E2E, and canary
dry run.
- Review fixes have passed the live Daytona test again. Sparse-file
budget enforcement, rejection before host writes, low host reserve, and
stalled provider cleanup are covered by the 43 focused tests. Greptile
is 5/5 and security scanning passes on
`9ffbd9e56e283a01c22f005c022b8f6838cf0143`; both review threads are
resolved.
- Test portability: `d2280108f5` verifies GNU tool versions and Python
before running the real-PTY regression. All 43 focused tests pass with
prerequisites installed; restricting PATH to the macOS system tools
cleanly skips the three integration cases. Standalone plugin typecheck
passes. Current-head CI passes typecheck, build, all test shards, Runner
verification, E2E, and canary dry run:
https://github.com/paperclipai/paperclip/actions/runs/40910736373.
Greptile and Paperclip Review both assess the final head 5/5, security
checks pass, and no review threads remain unresolved.
- Paperclip Review assessed the final head 5/5 with no actionable
defects after the test-portability fix. Remaining accepted tradeoffs are
recorded under Risks.
- This is live provider-boundary acceptance. It does not prove a full
task Retry journey, repair lost provider session state, or recover the
original deployed task.

## Risks

- Streaming requires Bash and GNU tar, dd, and base64. Missing tools or
transfer failure reject export and retain the recovery obligation.
- Acknowledged terminal transfer is slower than bulk download,
especially across high-latency links. Very large exports can still reach
the configured deadline. The ordinary bulk path is unchanged.
- The fallback checks host free space before every 40 KiB write; this
deliberately favors a strict reserve check over reducing local syscalls.
It carries archive-download error context but does not yet emit a
dedicated transfer span. Provider cleanup is bounded; a kernel-stalled
local filesystem operation can still delay completion and file close.
- This change does not increase sandbox capacity or reconstruct provider
state that failed to persist. The plugin must reach the target
installation before recovery can use it. No merge, deployment, or
original-task replay is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository inspection, code
editing, shell execution, and automated testing. 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 11:41:01 -05:00
Nicky LeachandPaperclip 247de89eae fix(runner): preserve warm tasks during recovery (#18169)
## Thinking Path

> - Paperclip manages agent work and the lifetime of its execution
resources.
> - A warm native task can keep one Runner alive between successful
turns.
> - Foreground completion selects whether that resource stays running or
stops.
> - Background recovery must use the same selected policy.
> - Recovery currently reads that policy only from workspace copy-back
records.
> - A task without such a record can be stopped immediately after
foreground retention.
> - This pull request saves the resource policy with the native runtime
and permits the retained task to refresh its control connection.

## Linked Issues or Issue Description

**What happened?**

Background native finalization can stop a successful warm Runner when
its run has no Core workspace-sync record. Foreground completion retains
that same task. The stopped Runner cannot receive the later drain and
suspend commands. Cold resume then correctly rejects its unproven
checkpoint.

Hosted diagnostics confirmed the recovery reconciler attempted
environment release immediately after foreground retention. The provider
connection returned HTTP 404 within the same second. A database-backed
regression reproduced the stop without a workspace-sync record.

A separate authorization gap also prevents the current retained task
from refreshing its connection endpoint after the run succeeds.

**Expected behavior**

Foreground completion and recovery must use the selected resource
policy. A successful warm task stays running until its idle shutdown can
suspend it. Failed or cancelled work still stops. The current retained
task can refresh its existing control route, but cannot prepare or
submit new execution.

**Steps to reproduce**

1. Select a warm native runtime on a reusable remote execution
environment.
2. Complete a turn without a Core workspace-sync record.
3. Let native finalization recovery settle the still-active run lease
before foreground retention finishes.
4. Before this change, recovery defaults to `stop_and_retain` and
invokes the provider stop path.
5. Separately, request the retained task's connection endpoint after
successful completion. Before this change, Core rejects that request.

**Paperclip version/commit**

The hosted failure used Core 31b927e301.
Regressions also reproduced on master at 6d59f5ef7.

**Deployment mode**

A remote native execution environment with reusable warm tasks. The
resource policy is generic and applies across harnesses and providers.

Related recovery coverage: Refs #18161. This change preserves the
suspended-checkpoint admission guard. Existing tasks without the newly
saved policy retain the previous conservative fallback; deployments must
drain or recover them explicitly.

## What Changed

- Save the selected native resource disposition in the existing
runtime-selection transaction. Add no startup database round trip or
network request.
- Read this small policy in background settlement and recovery when no
workspace-sync record exists. Preserve valid workspace-sync policies and
export-retry behavior.
- Keep failed and cancelled runs out of warm retention.
- Permit connection refresh for a successful, dispatched warm task on
its current retained reusable lease. Keep retirement, termination,
expiry, saved-run identity, and plugin capability checks.
- Add database-backed retention and selection regressions,
failure/cancellation coverage, and bounded projection checks. Document
the lifecycle and access contracts.

## Verification

- Before the source edits, the no-workspace-sync regression invoked the
driver with `stop_and_retain` instead of retaining the lease. Both
runtime-selection cases failed because the resource policy was absent.
- After the source edits, those regressions and both
run-state/runtime-selection files passed. The three-file run had 77
passes and two new fixture expectation failures. Those fixtures were
corrected. Final-head GitHub CI passed, including the server suites,
Runner checks, typecheck, build, and E2E gates. The local rerun was
deferred at the user's request.
- Commands: `node_modules/.bin/vitest run
server/src/__tests__/native-environment-settlement-work.test.ts
server/src/services/heartbeat/runtime-selection.test.ts
server/src/services/heartbeat/run-state.test.ts`.
- The connection authorization regression failed before its edit. All 34
tests in `server/src/__tests__/environment-task-runtime.test.ts` then
passed.
- `node scripts/check-maps.mjs` and `git diff --check` passed.
- No comprehensive local suite was run. Further local tests and VM
reproductions were stopped at the user's request to conserve battery and
mobile data. GitHub CI verifies the final head.
- Hosted verification of this patch requires deployment after merge.
Passing pre-patch retries did not establish repair of the original
failure.

- Standard Greptile and the subsequent requested Apex review both
returned **5/5** on `360bcd7e789d65950c27484af237faec02553666`, with no
inline findings.

## Risks

- This adds one server-owned field to the existing run profile JSON; no
migration is required. Invalid or absent policy keeps the previous
conservative fallback.
- Valid workspace-sync disposition remains authoritative. Pending export
and failed finalization still use stop-and-retain safety behavior.
- Retained connection access requires a successful run, matching saved
run identity, dispatched warm task, unexpired reusable lease, and no
retirement or termination. Superseded leases and new execution remain
denied.
- The cold-resume checkpoint proof is unchanged. This patch does not
make the already-stopped task's unsuspended checkpoint resumable.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The host does not expose a more specific serving model ID or
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run targeted local checks; final verification passed in
GitHub CI (local rerun deferred at the user's request)
- [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 09:19:49 -07:00
DottaandPaperclip 6f278dd6d7 fix(runtime): settle recovery lease and connection lifecycles (#18167)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - A remote runner can survive a controller restart.
> - Recovery renews its execution lease during slow preparation.
> - The native executor then shares that renewal timer.
> - Preparation kept its reference until all finalization finished. A
tick after lease release treated completion as ownership loss and
detached the retained runner.
> - A Linux continuity test also found that buffered wire events could
arrive before their connection was registered. Cleanup then kept a
completed promise under an undefined key and never finished.
> - This pull request transfers renewal ownership after execution
acquires its reference. It also registers each connection before wire
callbacks can run.
> - Recovered turns can complete, retain the warm runner, and settle
connection cleanup.

## Linked Issues or Issue Description

**What happened?**

A recovered remote run could complete, release its coordinator lease,
then detach during instruction collection. The next turn could find the
old runner still using the ingress port. Recovery then stopped because
it could not prove process ownership.

**Expected behavior**

Preparation keeps the lease alive until execution owns renewal.
Execution stops renewal before releasing the lease. Actual ownership
loss still detaches the runner. Buffered wire callbacks must use the
registered connection, and cleanup must finish.

**Steps to reproduce**

1. Recover an in-flight remote runner after a controller restart.
2. Let the recovered turn complete.
3. Hold instruction collection open through the next lease renewal tick.
4. Send a follow-up that needs the retained runner.

Related: #17439 introduced remote controller recovery. #18011 preserves
checkpoint authority through warm preparation. This change fixes the
lifetime of preparation's renewal reference.

## What Changed

- Pass an internal lease-acquired callback from recovery through
heartbeat dispatch.
- Release preparation's renewal reference after the executor registers
its own. Keep final cleanup for exits before dispatch.
- Add a PostgreSQL regression for completion while finalization is still
pending. Cover callback forwarding, acquire-before-release ordering, and
failure before dispatch.
- Register the authority connection before subscribing to wire events.
Handle an immediate close before accepting buffered data.
- Add regressions for a message or close delivered during subscription.
- Extend Linux continuity coverage with preparation renewal and delayed
instruction collection after recovery.
- Update the continuity guide and session verification recipes.

## Verification

- The new recovery regression failed before the fix because renewal
detached the runner after lease release. The 76 recovery, renewal, and
dispatch tests then passed. The final ordering and early-exit checks
passed again after replacing fixed sleeps with controlled interval
ticks.
- Both buffered-wire regressions failed before the connection fix. All
170 control-plane tests passed afterward. Existing tests cover stale
authority, ownership loss, pending operations, and closed ingress.
- Linux ARM64 acceptance passed at
`a7daefacceb8bd994d0b79d284cdf54f3e3829d1`, with Node 24.19.0,
PostgreSQL, the real Rust runner, TLS ingress, and a deterministic Codex
protocol fixture. The test interrupted the first turn, recovered it,
held finalization open for a renewal interval, and completed two
follow-ups. It retained one provider process, three turns in one
history, and the same runner identity. Final suspension and connection
cleanup completed. The ordinary warm-reuse case also passed three turns
with one provider process.
- Earlier Linux attempts completed the turns but hung during cleanup. A
debugger found a fulfilled promise keyed by an undefined connection. The
regression reproduces that defect. One later setup attempt timed out
while staging an unstripped 373 MB debug binary. The passing run used
the same binary with debug symbols removed.
- Reproduce Linux acceptance with the `same-server` case in
`doc/testing-native-remote-continuity.md`.
- `pnpm -r typecheck`, `pnpm build`, map validation, and `git diff
--check` passed at the final revision. The full local `pnpm test:run`
command was attempted, but the serial run had not finished after 13
minutes. It was stopped after the equivalent CI lanes passed. It is not
counted as a full local pass.
- Greptile and the Paperclip review both scored the final revision 5/5
with no findings. All Runner verification lanes passed. The first CI
attempt hit timing failures in voice recovery, agent YAML configuration,
and the task-title outage browser test. The full YAML and voice-recovery
files passed locally (88 and 19 tests). These paths were unchanged and
passed on the prior revision. All three passed on the single retry.
Final current-head status: 55 successful checks, one neutral check, and
two skipped Storybook checks. No pending or failed checks remain.
- Live Daytona/model acceptance and recovery of the hosted task remain
unverified. This PR does not deploy the change.

## Risks

- Releasing preparation before execution starts renewal could leave a
gap in authority. The callback runs after the executor registers its
reference.
- Preparation errors must not leak renewal. The recovery promise retains
idempotent final cleanup.
- Wire callbacks can run during subscription. Message and close
regressions check that registration is complete before either callback
runs.
- No schema, API, model, permission, lease duration, or retry policy
changes.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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 11:18:53 -05:00
DottaandPaperclip cc6a3296e5 fix: keep agent YAML compact and preserve omitted settings (#18168)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Advanced tab lets operators edit agent settings as YAML.
> - Its first format embedded company catalogs, profile definitions,
history, and instruction text.
> - This made one agent document grow with unrelated company data.
> - Removing those fields from the display also needs safe save
behavior.
> - This pull request renders a compact document and resolves sparse
edits against saved state.
> - Operators can change settings without copying shared data or
deleting hidden values.

## Linked Issues or Issue Description

Refs #2219. Follow-up to #18036.

**Current behavior**

The Advanced document expands shared profiles, embeds instruction files,
and lists read-only state and unused connections. It also emits empty
command lists and unset fields.

**Proposed behavior**

Show the agent's own settings and profile/instruction references.
Omitted settings stay unchanged. Explicit empty values clear supported
settings. A named instruction file changes only when supplied; `null`
deletes that file.

**Reason and benefit**

An agent's YAML should remain readable when its company adds profiles or
its instruction files grow. Every setting remains available through YAML
or its owning settings tab.

## What Changed

- Remove the read-only `observed` export and unused connection
inventory.
- Render profile-key references and instruction locations. Keep file
contents and legacy prompt text out of the default editor.
- Omit unset nullable fields, empty maps/lists, zero budget, standard
permissions, and empty commands.
- Add a sparse input schema and saved-state resolution. Preserve omitted
fields, binding definitions, file contents, permissions, and channel
settings.
- Keep explicit clears and map/list replacement. Patch named instruction
files and use `null` for deletion. Preserve hidden legacy prompt text
unless explicitly changed.
- Check profile references, shared edits, and file restrictions before
writes. Keep revision guards, native authorization, and partial-save
recovery.
- Update documentation, verification maps, and regression coverage.
Remove operating-system clipboard dependence from browser tests.

## Verification

- All 48 jobs pass in the [final CI
run](https://github.com/paperclipai/paperclip/actions/runs/40904124001)
on `6dbb11d7a6`. Greptile is 5/5 on this exact commit. Both findings are
resolved; there are no failed or pending checks.
- Paperclip Review ended neutral because its agent finished without a
complete assessment. It did not provide a code finding. Superagent
Security Scan passed.
- The focused suite passes 58 tests across YAML parsing,
planning/saving, compact output, and the editor.
- A large unit fixture with 30 profiles, 50 entries per profile, and a
1,000-line instruction file renders under 70 lines and is more than 95%
smaller than the prior expanded representation.
- All eight browser cases pass against real APIs and a dedicated
PostgreSQL database. The compact-output case stays under 60 lines with
large profiles and instruction text. It checks sparse saves and
profile-key binding without changing shared definitions. The
resource-save browser case also checks that unpinned skill shorthand
does not trigger another sync during an unrelated save.
- Browser coverage also checks resource saves/clears, secret redaction,
key receipts through rename, stale drafts, lost responses, instruction
relocation, and revision restore. The MCP fixture is a local target; no
model run or external provider login is claimed.
- Workspace build and typecheck pass. Map, Storybook catalog, and token
gates pass. These checks and all eight browser cases passed after rebase
onto current master, including its new Secrets regression. The merge
conflict consisted of adjacent test additions; both were retained. The
final skill no-op correction also passes a focused browser rerun. The
mixed-resource channel regression failed before its fix and now passes,
including revision restore with unpinned skills. UI typecheck passes
after both corrections.
- The first browser run hit a five-second test wait during an active
multi-resource save. A focused rerun exposed shared clipboard
interference. The helper now waits for save completion and uses scoped
copy events plus keyboard input. The next full run passed. Earlier logs
and screenshots remain outside the repository.

Run the focused browser suite with:

```sh
pnpm exec playwright test --config tests/e2e/playwright.config.ts tests/e2e/agent-configuration.spec.ts
```

## Risks

- Omitted fields now preserve saved values. Removing a line does not
clear that setting. Supply its supported empty value instead.
- Instruction file maps are patches. Old exports that removed a file by
dropping its entry must now set that file to `null`. Entry files and
read-only assets remain protected.
- Explicit lists and adapter/runtime/metadata maps retain replacement
behavior. Hidden legacy prompt text is preserved unless supplied
explicitly; an empty string clears it.
- Shared definition edits still require explicit consent. Saves still
use sequential native APIs and can partially succeed. Existing
unversioned resource race windows remain.
- No database migration, new dependency, lockfile edit, or workflow
change.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and context
window are not exposed in this session. The work used reasoning,
repository editing, code execution, and Playwright browser automation.

## 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 11:17:17 -05:00
DottaandPaperclip c32e1ba6da fix(onboarding): keep approved child task handoffs runnable (#18160)
## Thinking Path

> - Paperclip manages work through tasks, agent runs, dependencies, and
human decisions.
> - The first-task workflow asks for approval before it creates an
execution task.
> - File-producing work must run on a child task before onboarding can
finish.
> - A child blocked by its onboarding source cannot start while the
source waits for that child.
> - This change rejects that dependency during task creation and later
edits, and gives the agent a correction.
> - The shipped recipe shows the dependency direction and requires the
actual approved inputs in the child instructions.

## Linked Issues or Issue Description

**What happened?**

After human approval, an onboarding run could create a child with the
onboarding source in `blockedByTaskIds`. Creation saved a blocked child
with no wake. The parent could then wait for that child. A handoff could
also refer to input from the parent conversation without including the
input in the child description.

**Expected behavior**

The approved child can execute before its waiting parent. Invalid
first-task dependency input fails before task creation and leaves the
same command key available for a corrected call. The child instructions
include the required approved input and constraints.

**Steps to reproduce**

1. Accept a proposal on a server-created first task.
2. Call native `create_task` with `status: "todo"` and the onboarding
source in `blockedByTaskIds`.
3. Observe a blocked child with no scheduled wake. Block the parent on
that child to expose the stalled handoff.

**Paperclip version or commit**

The regression reproduces on `f8484a9f8d1f68e9534fee4f29e00e716dc680f4`.
The repair is based on current master.

**Deployment mode**

Core native and REST task creation. The same server boundary serves
self-hosted and hosted instances.

Related: #18080 fixed remote delivery of the selected first-task skill.
This change handles the later child handoff boundary.

## What Changed

- Reject a task blocked by its authenticated first-task source during
creation and later dependency edits. Later agent edits also check the
locked target's server-owned onboarding parent, protecting a child
running under its own execution. Compare UUID identity in PostgreSQL so
alternate supported UUID spellings cannot bypass the check. The error
explains the correction.
- Add a native child/dependency recipe with self-contained approved
input guidance. Clarify the general `create_task` input descriptions and
update their generated contracts.
- Cover native and REST rejection, corrected retry, preserved valid
dependencies and replay, and an executable recipe with exact input bytes
read from the child's own context. Thread the authenticated run through
native dependency edits. Keep blocker corrections independent of a new
proposal decision.
- Update execution semantics and the existing onboarding map entries.

## Verification

- Red on `f8484a9f`: the new native regression received a created
blocked child instead of the expected rejection.
- Review regressions were red on the original PR head: uppercase,
unhyphenated and braced source UUIDs created blocked children; a later
child PATCH returned 200 and saved the reversed blocker.
- Review follow-up reproduced both native and REST child-own-run
bypasses on `75fa75a6`: the native dependency call applied the reverse
edge; the child's own PATCH returned 200. The regression uses the actual
authenticated child execution and an already checked-out task.
- All 95 tests across first-task admission, assets, and the full native
tool-authority suite pass. The shipped recipe is validated against the
native schemas and exercised through real task/dependency services with
disposable PostgreSQL. Rejected PATCH tests preserve existing
authorization and attempt-audit behavior and require no requested
task-field, relation or wake change. Compatibility controls retain
ordinary manual parent blockers, explicit board edits, other blockers
and empty-list corrections.
- Runner TypeScript build, generated contracts, capability inventory,
protocol manifest, and map checks passed.
- Server typecheck and all 95 focused tests pass with the child-run
follow-up. All latest checks pass on `f24509ae`: 55 successful checks,
one neutral review check, four skipped checks, and a successful legacy
security status. Both automated reviews are 5/5 on this exact commit.
- Prior-head CI failures are preserved: the Runner close fixture had
unconfirmed provider drain while suspension succeeded; its exact
fake-provider subprocess row passed locally with unchanged sources. The
browser outage test lost its title textarea before any outage write. A
bounded local control with a fully loaded composer passed every original
outage assertion. The prior failure is an editor-readiness race; its
exact asynchronous ordering remains unproved. No UI, browser-test, or
timeout change is included. Neither failure is counted as a pass or
silently discarded.
- The first `f24509ae` CI attempt had two interrupted jobs: Typecheck
and General server 9/12. Their logs record runner shutdown signals. The
server job also records lost runner communication. The same-head
failed-job rerun passed both jobs and the required aggregate. It reused
the other successful results. No source, test, or timeout change was
made for the rerun. The failed attempt remains preserved. Full
repository checks pass in CI; the local full repository typecheck, test,
and build commands were not repeated.
- No external model or provider calls are used by these checks.
Real-provider acceptance at this revision remains separate.

## Risks

- The new rejection uses the authenticated run and the server-owned
onboarding origin. Ordinary tasks, other blockers, empty-list
corrections, and already committed creation replay retain their existing
behavior. Blocker edits do not reapply the creation approval gate.
- Nonempty blocker edits perform two indexed identity reads; the task
lookup covers at most the run source and locked structural parent. Other
patches and empty-list corrections add no source lookup. The update
guard adds no parent row lock behind a child. Existing REST
authorization checkout and attempt auditing remain in place before the
domain mutation guard.
- The explicit input recipe guides the model. Schema and persistence
tests do not prove that a future model follows every instruction.
- The tool guidance changes the generated semantic catalog identity. The
maintained generated files are synchronized in this change.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with `ultra` reasoning effort,
repository tools, code generation, and test execution. The context
window is not exposed by the runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used and stated the available runtime
detail
- [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 bug issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket ID
- [x] I have run focused tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented 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 10:57:31 -05:00
Devin FoleyandPaperclip fd98075a22 fix(ui): show environment variables on agent Secrets pages (#18121)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators inspect agent configuration to understand which
credentials an agent can use.
> - Agent environment bindings can contain inline values, company secret
references, and user secret references.
> - The Secrets page did not mount the environment editor. Inline
credentials were absent, and its empty message said no secrets were
bound.
> - The existing environment editor already handles these binding types
and redacted values.
> - This PR mounts that editor on the Secrets page in both UI layouts
and clarifies the empty reference message.
> - Operators can inspect and edit the configured bindings. Values
remain masked, and the Runtime editor remains available.

## Linked Issues or Issue Description

**What happened?**

An agent can receive an inline credential through its environment while
its Secrets page shows no matching entry. That page only rendered the
secret-reference overview and API access controls.

**Expected behavior**

The agent Secrets page shows existing environment bindings as well as
secret references. Saved inline values stay redacted. Saving another
binding preserves existing credentials.

**Steps to reproduce**

1. Save an agent with an inline environment credential.
2. Open the agent Secrets page.
3. The credential row is missing, although the runtime configuration
contains it.

**Paperclip version or commit**

Reproduced on master `27270e9bf8b7a294cf03f8b84f4857f1b1ff05c7` before
the fix.

Related: [#12517](https://github.com/paperclipai/paperclip/pull/12517)
proposes changes to secret assignment controls. This PR covers display
of existing inline environment bindings through the current editor.

## What Changed

- Show the environment editor on agent Secrets pages in both UI layouts.
Keep the Runtime editor available.
- Change the empty overview message to describe missing company secret
references. Personal references remain visible in the environment
editor.
- Add native and legacy agent regressions through the actual page
components.
- Add a browser check for masked values, secret references, save/reload,
and exact credential preservation through an opaque configuration
revision.
- Update the feature and agent access maps for the existing UI entry
point.

## Verification

- Red before the fix: the native and legacy page regressions could not
find the saved environment credential row.
- The focused UI suites pass: 207 tests, including all four
layout/adapter page cases.
- The server redaction and configuration revision suites pass: 42 tests.
Native Runner environment assembly suites pass: 40 tests.
- An isolated Chromium flow passes against the real local API and
database. It checks a masked inline value, a company secret reference,
and save/reload of an added variable. It then removes the new variable
and checks that the opaque server revision matches its original value.
This proves that the hidden credentials survive both saves without
reading them. The initial browser attempt exposed a fixture ordering
assumption; the test now compares variable-name sets because PostgreSQL
JSONB does not retain insertion order.
- `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and `node
scripts/check-maps.mjs` pass.
- The full local `pnpm test:run` attempt found three failures in
unchanged server fixtures. The chat-recovery case passes in isolation
and in its 22-test group. The two workspace cases inherit
`init.defaultBranch=main`; all 179 workspace tests pass when the child
process uses `init.defaultBranch=master`, as the fixtures expect. The
long local invocation was then stopped. Later local groups were not
reached. All corresponding CI test shards pass.
- [CI passes on the final
commit](https://github.com/paperclipai/paperclip/actions/runs/40809064907).
The first canary dry run found an npm version collision. Its single
retry passed without a source change.
- Apex passes at 5/5 on the current commit with no unresolved findings.

## Risks

Low risk. The change reuses the existing editor and save path. No API,
secret delivery, permission, or database contract changes. The tests
cover masked values and existing references during save/reload.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The
session does not expose a more specific model ID or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 08:32:30 -07:00
DottaandPaperclip 7e27bc5007 fix(tasks): keep anchored opens compact and stabilize saved cards (#18092)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task pages must make the current instruction and recent conversation
readable quickly.
> - Compact startup avoids reading all earlier messages and run
activity.
> - Every URL fragment previously selected the full-history path, even
for documents.
> - Saved document cards also arrived after the conversation was
visible. PR statistics could add another row later.
> - This pull request keeps anchors compact and reveals the saved
conversation structure together.
> - The benefit is stable reading position without loading unrelated
history.

## Linked Issues or Issue Description

Related: #17593 introduced compact startup. #14667 covers earlier reveal
and scroll work. This fix retains the bounded history contract.

**What happened?**

Opening a task document link loaded all task history. Ordinary cold
opens could reveal messages before saved document cards and plans
arrived. Later PR metadata added a statistics row and changed card
height.

**Expected behavior**

Every URL fragment keeps compact startup. Document links open their
pane. Older-comment links fetch only the target comment. Saved cards
keep their geometry after first reveal.

**Steps to reproduce**

1. Create a task with many comments, a saved plan, documents and saved
PR work products.
2. Delay the enriched task response and open the task. Observe cards
inserted after messages appear.
3. Open a document fragment. Observe full comment, activity and run
reads.
4. Delay PR metadata refresh. Observe each card grow when diff counts
arrive.

## What Changed

- Remove fragment and tab checks from automatic history expansion.
Resolve validated comment UUIDs through the authorized single-comment
endpoint, encode their path components, retain fetched targets across
document navigation, and preserve cancellation/deletion cache updates.
- Include the saved plan, document metadata and local work-product
projection in the core task read. Skip recovery, workspace and
related-task enrichment. Do not refresh providers. Summary queries no
longer select other document bodies.
- Seed saved work-product and plan queries from core, including already
pending or errored reads, without replacing known lists or an
authoritative empty result. Coordinate the bounded recent reads, saved
cards, latest transcript and settled initial pane width before first
reveal. Keep the thread and composer mounted during refresh and explicit
expansion.
- Open continuation summaries in the document pane. Reserve PR
statistics geometry while provider metadata loads.
- Add a reusable synthetic local task, nine browser checks, frame
measurements and video. Extend the PostgreSQL core-route fixture with a
saved PR row and assert its identity, URL, state and stored metadata
survive the response. Update design guidance and capability maps.

## Verification

- Red: visible document/plan cards changed from 0 to 1 to 4; thread
height grew from 690 to 1,432 pixels. Green: all seven saved cards
appear before reveal, with constant thread height and zero per-card
movement in the final reviewed browser run. The final 1,492-pixel layout
includes the reserved PR statistics lines.
- Red: delayed PR diff counts changed all three cards from 62 to 82
pixels. Green: their heights stay at 82 pixels before and after metadata
refresh.
- Nine browser journeys pass: delayed enrichment,
document/comment/unknown/continuation anchors, document clicks and
explicit history expansion with a retained draft, missing-comment retry,
delayed PR statistics, and retained older-comment position after
document navigation.
- 583 focused UI tests passed on `c91fa107ba`. After the plan-cache
follow-up, all 212 affected page/cache/plan-hook tests and UI typecheck
pass, including 14 plan-hook cases. The original 16 focused PostgreSQL
tests passed for the server changes.
- Merge-review red: holding the duplicate stored work-products read
blocked the first reveal past 10 seconds despite core already containing
the saved cards. Both empty and populated core projections now reveal
while that request remains pending. Malformed-comment tests prove no
target request is made; API tests prove path encoding and abort-signal
forwarding.
- The populated core-route test now inserts a real saved PR work product
alongside the plan and documents, then checks the complete saved
projection through HTTP. All ten task cold-open PostgreSQL tests pass.
- Plan-cache review red: an existing pending or errored plan query
prevented the saved core plan from reaching the consumer. Four real-hook
cases failed before the data-presence fix and pass afterward, for both
present and absent plans. A separately fetched newer plan or known
absent plan remains authoritative.
- Further layout red: the initial properties pane reduced visible thread
width from 775 to 742 pixels after reveal. The reveal now waits for two
stable width frames; the browser check includes width, height, card
counts and per-card geometry.
- `pnpm -r typecheck` and `pnpm build` passed for the original change;
UI typecheck and build pass after review fixes. Token, module-boundary
and map checks pass. `pnpm test:run` was stopped after about 15 minutes
in the serialized server lane. No full local test-suite pass is claimed.
On the earlier head, hosted build/typecheck and all Vitest lanes passed;
one E2E shard failed because the agent-configuration clipboard helper
copied page text into its YAML parser. On `c91fa107ba`, Greptile was 5/5
and every E2E shard passed, including the earlier clipboard case. One
unchanged Discord chat-binding test in server shard 8 returned false
after 185 ms; its 16-test integration file passes locally without
changes. The CI cause remains unestablished. On `be436ce492`, both
server shard 8 and E2E shard 7 passed without changing those tests or
their product code. On final head `e357b3bced`, all CI jobs pass,
including full general and serialized tests, all eight E2E shards,
typecheck, build and the aggregate verification gate. Exact-head
Greptile is 5/5 with no findings. The overall status rollup contains 55
successes, two intentionally skipped Storybook checks and a neutral
Paperclip Review. That advisory review ended without a complete
assessment; all previously posted findings are resolved and it added no
current findings.
- Test startup exceeded an initial 5-second deadline once while
development assets and other checks were active. The final browser
checks allow 10 seconds. These runs establish geometry and bounded
requests; they do not establish a reliable latency improvement. An
initial 503 error fixture exercised global reconnect/backoff. The
target-comment failure test uses a terminal 404.
- Browser data is synthetic. Provider metadata is simulated for the
delayed-response check. No staging deployment or live provider execution
is claimed.

## Risks

- Core task reads now include local saved-card queries and the saved
plan body. Other document bodies and all historical run activity remain
outside that path.
- First reveal waits for the bounded current structure. The existing
15-second incomplete-history fallback and inline retry remain available.
- Continuation-summary links open in the document pane in the current
task interface. Classic tasks keep their existing surface.
- No migration or mutation permission change.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 09:13:01 -05:00
DottaandPaperclip b81b870732 Add QA smoke journeys and OpenCode run traces (#18098)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product E2E journeys verify saved application behavior across
deployments.
> - Task creation and questions need reusable smoke selections and exact
run attribution.
> - Operators also need to inspect the OpenCode execution behind a
measured question.
> - Company observability does not currently support native OpenCode.
> - This change adds the journeys and a bounded projection of normalized
OpenCode run events.
> - The projection follows the configured capture policy and retains the
current run identity across warm reuse.

## Linked Issues or Issue Description

Related foundation: #17262. Related alternative: #17989 exports metadata
from OpenCode's native OTLP stream. This change uses normalized run
events to support the existing content switches and per-run linkage. It
does not forward the native stream. The two PRs overlap in launch
registration and must be reconciled before both land.

**What existing behavior does this improve?**

Reusable Product E2E smoke selections and company observability for
native OpenCode.

**Current behavior**

The journey catalog lacks reusable task creation and attached-agent
question checks. Native OpenCode is marked unsupported for company
observability, so a successful destination connection test does not
prove that agent traces will appear.

**Proposed behavior**

Add explicit task-create and ask-question selections. Verify saved state
and exact company, issue, agent, model, environment and successful run
attribution. Export normalized OpenCode turns, tools and usage to the
configured OTLP destination. Honor each capture switch and redact known
secrets.

**Reason and benefit**

CI can run a small measured smoke selection, retain its screenshots and
checks, and link results to traces belonging to the same run.

**Breaking changes**

Existing selectors remain unchanged. OpenCode export is opt-in through
existing company settings. Legacy OpenCode stays unsupported.

## What Changed

- Add reusable task creation and question journeys, configured-agent
capability, owned-fixture checkpoints and strict evidence validation.
- Add an OpenCode-owned projection of normalized run events. No provider
SDK or raw payload schema enters heartbeat coordination.
- Extend the private launch union and reserved environment allowlist for
native OpenCode. With export disabled, no receiver request runs.
- Keep destination headers in the parent wrapper and out of the actual
provider child environment and configuration.
- Bound each turn to 64 tool and 64 usage entries, 8 KiB per text field
and a 1 MiB request. Use a three-second request deadline, four
concurrent exports, and no retries or idle worker.
- Pass the rotated runner authority to each proxy turn. A retained
process no longer attributes later turns to its original launch run.
- Update settings copy, observability documentation and capability maps.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed after the implementation
changes.
- Adapter launch/redaction: 9 tests passed. Projection and actual proxy:
12 tests passed before the review fix; the expanded projection suite
passed all 12 cases after the fix. The proxy test exercises two runs in
one process against a real local HTTP receiver and a fake provider.
- Full OpenCode driver/projection suite: 72 passed, one existing
response_wake test timed out at five seconds. A focused check then
passed both existing omitted-continuation cases and the new trace export
case. The timeout cause remains unconfirmed.
- Runner package TypeScript and Rust `cargo check` passed. Map and UI
token checks passed.
- Prior journey validation: 273 tests across 12 files and the journey
TypeScript check passed.
- Broad local `pnpm test:run` encountered native-runtime integration
failures with repeated embedded PostgreSQL initialization failures and
was stopped. All 16 failing cases passed in an isolated run outside the
filesystem sandbox (961 unrelated cases unselected). The broad local run
is not a clean acceptance result. A later focused database-backed
chat/heartbeat run passed all six selected observability cases,
including native OpenCode launch and successful allocation (1,809
unrelated cases were unselected).
- All CI gates passed for `21085f880d8babc9efeb22d0623db99613d33093`,
including packaged-runner, clean-install, browser and build checks:
https://github.com/paperclipai/paperclip/actions/runs/40884658995 .
Greptile reviewed the same commit at 5/5 with no unresolved findings.
- Verified OTLP JSON acceptance and indexing with an explicitly
synthetic transport marker. No live OpenCode model trace or deployed
smoke acceptance is claimed yet.

## Risks

Export is best effort. Abrupt termination, recovered in-flight turns
without a new submitted event, limits or receiver failure can lose
traces. Export failure does not change task success. The projection
represents observed normalized events, not raw native model spans or
hidden reasoning. Known-secret redaction is not an OS isolation
boundary. UI changes can break journey locators. Deployment adapters
retain credential, ownership and cleanup responsibility. Both the
controller and native runner bundle must be updated before live
qualification.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 08:57:12 -05:00
DottaandPaperclip 7d8d1fbc1d fix(adapter-utils): provide a default author for local commits (#18094)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/209/changes/paperclip/209
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use managed launchers for Git and GitHub commands.
> - These launchers exclude host credentials and host Git identity.
> - A checkout without an author cannot save a local commit when managed
GitHub identity is absent.
> - A local author default belongs in the launcher that owns this
isolation.
> - This pull request supplies a private Paperclip default and preserves
explicit and managed identity selection.
> - Agents can save local work without manual author setup or extra
GitHub access.

## Linked Issues or Issue Description

**What happened?**

An ordinary `git commit` fails with `Author identity unknown` in a fresh
checkout without author settings or a usable managed GitHub identity. An
agent must set its own author to continue.

**Expected behavior**

The managed launcher supplies a default local author. Repository and
command settings override that default. A current managed identity
retains its existing precedence.

**Steps to reproduce**

Run the managed launcher in a fresh Git repository without author
settings or broker credentials. Add a file, then run `git commit -m
work`.

**Paperclip version or commit**

Reproduced at `063cfd43813cabf18417605fb9eefb9aacf95c8d` on Linux with
Node 25.9.0 and pnpm 9.15.4.

**Deployment mode**

Managed sandbox execution. The shared launcher also serves local and SSH
execution that selects managed access.

Related: #16662 changes precedence for a connected GitHub account. #8945
assigns identity to managed worktrees. This repair supplies the missing
anonymous launcher default and keeps the current managed precedence. It
does not require either change.

### Hypothesis and thesis for a fix

**Hypothesis:** The launcher removes inherited author variables and host
Git config. Without a broker identity or explicit repository settings,
it has no author. Four real-Git cases reproduce the reported error on
the base revision.

**Thesis for a fix:** Put `Paperclip <noreply@paperclip.ing>` in a
private Git config for each operation. Git treats it as global config,
so repository and command settings can override it. The existing broker
environment still takes precedence. Do not store a person's identity in
shared checkout config, where it could remain after steering or
revocation. The default grants no GitHub access.

## What Changed

- Write the default author to the existing private operation directory
with mode `0600`. Remove it when the operation exits.
- Point managed Git at this file while keeping host global/system
config, credentials and SSH identity excluded.
- Add real-Git regressions for missing, absent, unavailable and rejected
access. Preserve explicit overrides, identity changes and revocation
controls.
- Verify two shell commits through normal launcher staging and a commit
after anonymous heartbeat cleanup. Check saved files, commit metadata
and temporary config cleanup.
- Update identity documentation and the two run map recipes.

## Verification

- Red: the four new local-commit cases fail on the base launcher with
`Author identity unknown`.
- Green: all 80 focused tests pass in one run across
`github-launcher.test.ts`, `github-launcher-environment.test.ts`,
`heartbeat-github-launchers.test.ts` and `native-github-access.test.ts`
(23.31 seconds).
- A controlled filesystem failure first made the candidate discard valid
managed credentials. After the correction, the same real launcher
process retains them. Default-author file failure does not change
operation-directory readiness.
- Review found a second failure: a partial write can leave invalid Git
config. The real-process test failed before the repair with `fatal: bad
config line` from `git status`. The launcher now selects the default
file only after the write succeeds. Both write-failure cases retain
managed credentials, allow status, require identity when no default is
available, and save a commit with explicit identity. The test reads the
stored commit metadata with real Git.
- Real shells, generated launchers and Git create and inspect saved
commits. Sandbox transport and broker replies use controlled fixtures.
No live cloud rollout or GitHub write acceptance is claimed.
- The isolated test process excludes inherited task launcher paths, Git
config and broker authentication variables. An initial run exposed those
test-environment inputs; the isolated replay passed. The heartbeat
assertion now checks the private default file and its cleanup instead of
expecting `/dev/null`.
- Adapter-utils typecheck and build pass. Map validation and `git diff
--check` pass.
- Conflict repair on 2026-10-29: merged master
`fa5e70faf47ef2ca20bf2daf95b7503c94469b89` into the PR branch. Resolved
19 conflict paths by retaining master for unrelated files. All seven Git
identity files remain byte-for-byte equal to the reviewed fix. The final
diff is seven files, 145 additions and 15 deletions.
- At head `c501e3f28369d404c91082b89188dc150c9362a9`, all 80 focused
tests pass again (37.53 seconds). Adapter-utils typecheck and build
pass. Map validation and migration checks pass. The PR diff passes `git
diff --check`.
- Full workspace typecheck and build were attempted again. Both stop
because this sandbox has no Rust `cargo`. The duplicate full local
Vitest run was stopped after about five minutes without a final result
while full CI was running. The earlier full local attempt was stopped
without a final result. No local full-suite pass is claimed.
- GitHub now reports the PR as mergeable. All current-head checks have
completed. [Full CI run
40878973679](https://github.com/paperclipai/paperclip/actions/runs/40878973679)
passes, including typecheck, build, Rust, test shards and all eight E2E
shards. The exact-head check inventory has 54 successes, one neutral
Paperclip Review and two Storybook skips. Snyk passes. Greptile and
Paperclip each reviewed `c501e3f28369d404c91082b89188dc150c9362a9` at
5/5 with no actionable findings. All review threads are resolved. GitHub
reports the PR as clean and mergeable.
- The prior CI run had one failed E2E test: `a lost creation response
requires reload and cannot blindly replay commands`. Its YAML parser
received page text that starts with `Skip to Main Content`. The new run
passes E2E shard 7/8 and the full E2E gate. The prior failure remains
part of this record. A passing run does not establish the earlier
failure's cause. This change does not alter that test or the agent
configuration UI.

## Risks

- Commits without explicit or managed identity now use the generic
Paperclip author. Operators can still set repository or command
identity.
- `git config --global` writes to temporary operation config and does
not persist. The documentation states this behavior.
- If the private config directory cannot be prepared, commits still need
explicit identity. Existing redacted diagnostics and credential
isolation remain.
- One small synchronous file write is added to a directory the launcher
already creates. No new subprocess, network request, persistent identity
or authority cache is added.

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

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, shell execution and tool
use. The runtime does not expose the exact model ID or context window
size to this agent.

## 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 08:56:12 -05:00
scotttongandPaperclip 71f0c0c99e feat: add opt-in Coordinator workspace for chat, tasks, and decisions (#17983)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/147/changes/paperclip/147
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People coordinate work through conversations, tasks, and requests
for input.
> - These surfaces must share task state and preserve the context of
each decision.
> - The existing workspace makes people switch surfaces to follow that
context.
> - This pull request adds an optional Coordinator workspace with linked
conversations, tasks, documents, and decisions.
> - Each person can enable it in Settings > Experimental and return to
the classic workspace.
> - The benefit is a coherent path from a request to an assigned task
and reviewed work.

## Linked Issues or Issue Description

**Subsystem affected**
UI, server, shared contracts, and database.

**Problem or motivation**
People need a consistent way to start tasks from agent conversations,
answer questions, review work, and return to the source context.
Decisions and task state must agree across these surfaces.

**Proposed solution**
Add a personal, default-off workspace experiment. Keep one conversation
per agent. Add task proposals, compact task and decision cards,
contextual document panels, and a Needs You queue with search, filters,
sorting, grouping, and history.

**Alternatives considered**
Replacing the classic workspace for everyone would remove the opt-out
path. Keeping separate decision state in each surface would create
conflicting answers. This change uses the existing canonical task and
interaction records instead.

**Roadmap alignment**
This supports the existing agent chat, task management, and human review
capabilities. It is an experimental presentation choice. The user
requested this isolated implementation after design review. No Discord
discussion is claimed.

## What Changed

- Add per-person workspace preferences, a default-off setting, and an
additive migration.
- Add Coordinator navigation, pinned destinations, task lists, agent
switching, and contextual panels.
- Link task suggestions and creation to the source conversation. Default
new task ownership to the current agent unless the user specifies
another owner.
- Share pending questions, decision receipts, exact review targets, and
history across tasks, chat, and Needs You.
- Preserve task access, assignment authorization, revision binding, and
required output review gates.
- Add compact document links, relative timestamps, composer controls,
and reduced-motion support for task and decision transitions.
- Add component stories, regression coverage, and capability-map
documentation.

## Verification

- Final head: `4b839aae1e314bd7e8635a766f1d205ff1c03ba6`, based on
master `8bc051245f77a47bee0f8ba45896b8bfa5922e0a`. Verified October 29,
2026 at 00:10 UTC: **MERGEABLE, 56 checks passed, four conditional
skips, no pending or failed checks**. [Current CI
run](https://github.com/paperclipai/paperclip/actions/runs/40790639688)
passed without a rerun on this head.
- Fresh Greptile **5/5**, zero new comments and zero open review
threads; Superagent passed with no suspicious changes.
[Checks](https://github.com/paperclipai/paperclip/pull/17983/checks).
- Local workspace typecheck/build passed after the latest rebase. The
final account-read patch passed UI typecheck/build and all 12 related
preference/settings tests, including a delayed real-client request
across account changes. Earlier scoped checks cover review
deduplication/replay, decision deep links, cross-surface state, access
boundaries, and migration replay.
- Local database/browser rechecks after the latest rebase were limited
by exhausted macOS shared-memory IDs: `initdb` failed before database
creation. The local run passed 31 UI/snapshot tests and skipped 24
database tests; those skips and the blocked local browser start are not
claimed as passes. The independent Linux CI database and browser checks
passed. No running dev database or host setting was changed.
- Upstream migration 0403 is preserved. Preferences and durable review
retry aliases are generated as replay-safe migrations
`0404_tense_silver_sable.sql` and `0405_harsh_avengers.sql`; five newest
snapshots are retained. Every detected conflict was rebased and pushed
before waiting for CI/review, as requested.
- The PR is unmerged. The active master ruleset still requires
code-owner approval for the changed Paperclip skill; no approval or rule
change was performed.

<details>
<summary>Earlier verification failures, integration history, and
evidence</summary>

These entries preserve prior checkpoints and failures; the current
acceptance result is above.

- Focused UI and server checks from the isolated build are recorded in
the implementation plan.
- Browser checks covered the opt-in shell, navigation, task/document
links, and decision card states. No new live provider trial is claimed
for this handoff.
- Current acceptance head: `4b839aae1e314bd7e8635a766f1d205ff1c03ba6`,
rebased onto master `8bc051245` immediately after its GitHub
review-repair migration took 0403. Preferences are generated as
idempotent `0404_tense_silver_sable.sql`, preserving upstream
SQL/journal/snapshot history and five newest snapshots. GitHub reports
MERGEABLE after the immediate lease-protected push. Scott's updated
instruction is to rebase and push every conflict resolution first,
without waiting for CI or Greptile; verification follows the push.
- The final reviewed feature tree was consolidated for repeatable
single-commit rebases. The complete previous commit history remains
reachable through local recovery ref
`codex/coordinator-recovery-before-rebase-20261028` (resolved snapshot
`0e1bbdf4e`). The actual rebase completed, and its tree hash exactly
matches that resolved snapshot. The force-with-lease required the known
remote head `0e6ef7c44`, protecting against concurrent branch changes.
No PR merge or permission/runner setting change occurred. Fresh
CI/review are in progress for the current head.
- `2001132fa` received Greptile 5/5 with one nonblocking account-switch
read finding. Current head detaches path-coalesced preference GETs and
disables HTTP caching, retaining React Query's account-scoped sharing. A
delayed real-client GET regression proves account B can load its saved
choice before account A responds, and A's late response only updates A's
cache. Preference/settings tests 12/12 and UI typecheck passed; its
review thread is resolved. Fresh current-head CI/reviews are pending.
The prior CI chat shard 3 ended with “The operation was canceled” and no
assertion failure ([job
123171595631](https://github.com/paperclipai/paperclip/actions/runs/40789688333/job/123171595631),
`/tmp/pr17983-2001132-chat3.log`); no code/timeout change is attributed
to that cancellation.
- `843e823b4` reached fresh Greptile 5/5 with zero comments/open threads
and Superagent pass. All browser tests including the repaired YAML shard
passed, and 54 checks passed. General server shard 9 ended with “The
operation was canceled” and no failed assertion; its test step was
marked cancelled (job
[123164350893](https://github.com/paperclipai/paperclip/actions/runs/40787501761/job/123164350893),
log `/tmp/pr17983-843e-server9.log`). A single unchanged-head rerun was
started after the workflow completed, but master moved while it ran. A
local nested-clone check timed out in its 30-second database-startup
hook and then failed cleanup before the 20 database cases ran; this is
retained as a local verification limit
(`/tmp/pr17983-843e-nested-clone-check.log`), not claimed as a pass or
proof of the CI cancellation cause.
- Following Scott's instruction, the new conflict was rebased and pushed
immediately without waiting for that rerun. Upstream's
`0403_natural_cerise.sql` is preserved; regenerated preferences and
retry-alias migrations are `0404_tense_silver_sable.sql` and
`0405_harsh_avengers.sql`, replay-safe with five newest snapshots
retained. The YAML helper conflict combines upstream's click and header
behavior with the editor-selection guard and injected regression.
Recovery ref `codex/coordinator-recovery-843e823b4` preserves pre-rebase
work. Current head is MERGEABLE. Full workspace typecheck/build passed;
UI and snapshot checks passed 31 tests, but 24 database tests were
skipped by the local support probe, and the local browser server could
not initialize PostgreSQL. A direct disposable `initdb` diagnostic
established the host limitation: `could not create shared memory
segment: No space left on device` (`shmget`, shared-memory IDs
exhausted, not disk space). No dev database or host setting was changed.
Diagnostics: `/tmp/pr17983-2001132-initdb-probe.log`,
`/tmp/pr17983-2001132-db-probe.log`; checks:
`/tmp/pr17983-2001132-tests.log`, `/tmp/pr17983-2001132-browser.log`,
`/tmp/pr17983-2001132-types.log`, `/tmp/pr17983-2001132-build.log`.
These local skipped/blocked checks are not claimed as passes; fresh CI
on independent runners is in progress.
- `d18f683cd` reached fresh Greptile 5/5 with zero comments/open threads
and Superagent pass, but [E2E shard
7](https://github.com/paperclipai/paperclip/actions/runs/40785966243/job/123159719925)
failed parsing an Advanced YAML clipboard read beginning with “Skip to
Main Content.” The log is retained at `/tmp/pr17983-d18f-e2e7.log`.
Current head hardens the test helper to verify editor focus and
selection, clear stale clipboard content, and require the YAML header at
the start of a fresh copy before parsing. Saved-state assertions and
timeouts are unchanged. All six Advanced YAML browser journeys passed on
a disposable local instance (41.0s); the exact lost-response journey
also passed with a one-time injected surrounding-page copy, verifying
rejection/reacquisition (17.6s). The precise browser focus/clipboard
timing in CI remains unproven; the observed invalid-read path is now
guarded and deterministically exercised. Logs:
`/tmp/pr17983-yaml-clipboard-scope-browser.log`,
`/tmp/pr17983-yaml-clipboard-injected-browser.log`. Fresh current-head
CI and reviews are pending.
- `19e6dcb0b` passed Superagent and Greptile 5/5, with one nonblocking
deep-link finding. Current head preserves attention links using
`?decisionId=`: the requested pending decision is rendered even beyond
the first 40 cards, focused and scrolled into view, then only that
parameter is consumed so later refreshes do not refocus. Other URL
parameters remain. Needs You tests 10/10 and UI typecheck passed; its
review thread is resolved. The preceding post-rebase regression run
passed 45/45 tests. Fresh current-head CI/reviews are pending.
- `6d772b7cc` reached Greptile 5/5 with zero comments/open threads and
Superagent pass. While 32 checks had passed, master moved and caused a
documentation conflict in `maps/feature-map/onboarding.md`. Rebased
immediately, preserving both onboarding paragraphs. The complete
four-commit branch was pushed as `19e6dcb0b` before waiting on
CI/review, per Scott's instruction. A transient Git index lock
interrupted the first continue; the command sequence briefly pushed
intermediate `34e298c07`, then the completed rebase was immediately
pushed. All feature and security/retry fixes are present; local recovery
ref `codex/coordinator-recovery-6d772b7cc` preserves the pre-rebase
history. The only tree differences from that ref are upstream's two
smoke-test files and the combined documentation paragraph. GitHub
reports MERGEABLE. Fresh current-head verification is in progress;
prior-head review results are not current acceptance.
- `21efa3120` passed Superagent but Greptile scored 4/5 for a valid
retry-key persistence bug: an acknowledged duplicate key could reopen a
resolved review. Current head adds an additive, replay-safe
`0404_light_swarm.sql` migration for indexed, task-scoped aliases from
acknowledged retry keys to the canonical interaction. Alias registration
and retry lookup occur under the existing task lock; payload/actor
mismatch still conflicts, and each canonical review permits at most 100
aliases. Original and acknowledged keys replay the terminal result
rather than creating a new gate. Five newest migration snapshots are
retained. Service/routes tests 165/165 passed; final quality review plus
migration replay/snapshot checks 25/25 passed; server typecheck passed.
The P1 thread is resolved in code; fresh current-head reviews and CI are
pending.
- `69c2c7543` passed 55 checks and Greptile 5/5 with no open Greptile
findings, but Superagent check
[123140675812](https://github.com/paperclipai/paperclip/pull/17983/checks?check_run_id=123140675812)
correctly flagged unbounded pending quality-card creation. Current head
fixes that under the existing task-row lock: equivalent requests with
fresh idempotency keys reuse the pending card; conflicting requests for
an unresolved deliverable return the existing interaction ID; pending
cards are capped at ten per task across all reviewers. Distinct outputs
remain independent, and already-answered items in a partially pending
batch can receive a fresh review. Added real-database concurrency,
cross-card duplicate, partial-answer, and hard-cap regressions. Quality
review 22/22 tests and final server typecheck passed; earlier
service/routes 163/163 tests passed before the final partial-answer
refinement. One added assertion initially expected a service HTTP error,
but duplicate keys are rejected earlier by the existing shared schema;
the assertion now verifies that validation. Fresh current-head
CI/reviews are pending; the action-required security result is not
treated as passed.
- `c9c575e5f` completed all 56 checks successfully with four conditional
skips, Greptile 5/5, and Superagent pass. Its two P2 review findings are
fixed in the current head: independently bound quality approvals now
each remain visible in attention; changing/clearing URL-backed
assignee/status filters updates the URL and survives task navigation.
Both review threads are resolved. Regression evidence: attention service
34/34 tests passed, CoordinatorTasks 20/20 passed, UI and server
typechecks and the full workspace build passed on `69c2c7543`. The first
new UI test run caught an assertion racing React Router's transition;
waiting for the navigation before asserting passes without weakening the
navigation/remount checks. These older-head green checks are not claimed
for the new fix commit.
- Preceding `0e6ef7c44` completed all 56 checks successfully with four
conditional skips, fresh Greptile 5/5 and no open findings, and passed
Superagent. A fifth migration-metadata collision arrived before the
final Runner job finished. Those green results are preserved as
prior-head evidence, not current acceptance.
- Previous fully verified migration head:
`0e6ef7c44696a377f35e69521b93587576374bd0`, integrating master
`f8226b051` after the fourth migration-number collision. Master added
terminal GitHub-response migration 0401 while the final native check
ran; upstream 0401 SQL/journal/snapshot is preserved unchanged, and
preferences are generated as idempotent `0402_yielding_blink.sql` on
top. Exactly the five newest snapshots remain. GitHub reports MERGEABLE
after the push. All 1,155 relevant
migration/review/interaction/native-execution/remote-assets tests,
workspace typecheck/build, migration guards and whitespace checks pass.
Fresh exact-head CI/Greptile/Superagent are pending.
- Immediately preceding head `36c67cf03` completed all 56 checks
successfully with four conditional skips, fresh Greptile 5/5 and no open
findings, plus passed Superagent security. No retry was needed for that
head's CI. Master advanced and introduced only a migration-metadata
conflict while its final native check ran, so that green result does not
establish acceptance of the current integration. Four consecutive
collisions (0398, 0399, 0400, 0401) during verification are retained as
concrete integration churn; a brief pause of competing migration merges
was requested, without assuming it happened or changing any repo
setting. The PR has not been merged.
- Prior fully verified head: `36c67cf03`, on the clean `30059c0ed`
integration of master `efd65c112`. The last Greptile P2 is fixed: Needs
attention retains the participant-agent scope through authoritative
server membership queries for each pending task, including historical
participation when another agent currently owns the task. It does not
approximate participation with current assignment or enumerate every
company task. The actual view-switch regression and all 31 focused
task/routing/collection tests, UI typecheck/build, token gates and
whitespace checks pass. Greptile completed a fresh 5/5 review on this
exact head (review 19) with zero new comments and no open review
threads. CI and Superagent remain in progress; no current-head CI
failure has been reported.
- Head `30059c0ed` received Greptile 5/5 with that one nonblocking
participant finding, now fixed. Superagent passed that head.
Current-base integration restored the ephemeral RunsOn fleet after a
superseded workflow retained queued aggregate jobs: normal cancellation
was insufficient; the single force-cancel request was interrupted but
readback confirmed that obsolete run cancelled and current CI began on
the trusted fleet. No cancellation retry or runner/security/workflow
changes were made. Its partial CI was superseded by the necessary
participant fix and is not current acceptance.
- Previous compatibility/base-sync head:
`30059c0ededc0eab4e04e8299a884f36db8b292f`, integrating master
`efd65c112` and the Inbox/workspace compatibility fixes. GitHub reports
MERGEABLE after the push. Coordinator keeps Inbox standalone under More
without rewriting the instance's Combined Inbox preference; opting out
restores that preference. Saved merged-Inbox URLs resolve to their
original owner, task status presets remain usable, and canonical
repeated `workspace` parameters retain scoped, deduplicated pagination
(including Needs attention). All 192 broader
routing/Inbox/sidebar/privacy/review tests and the final 16 task-page
tests pass, as do workspace typecheck/build, token gates and whitespace
checks. The two review threads are resolved. Fresh exact-head CI,
Greptile and Superagent results are pending.
- The preceding `d5b9be5bd` remained mergeable but its CI routing gate
intentionally fell back to GitHub-hosted runners: “stacked base merge
commit does not contain the current base branch.” All 45 downstream jobs
stayed queued. Current master was merged cleanly to refresh the pinned
base; no runner/security settings or workflow logic were changed.
Greptile scored that preceding head 4/5 with the two compatibility
findings fixed here. Its automatic Superagent scan was inconclusive at
checkout; the documented retry was still pending when superseded. Those
results do not establish acceptance of this current head.
- Previous approval/migration head:
`d5b9be5bd3b8d6b0437e42bf48138377f34fa67d`, integrating master
`ba5bba86d` and the stale-output approval correction. GitHub reports
MERGEABLE after the push. The fresh P1 finding is fixed: every submitted
item now validates and locks its bound output inside the resolution
transaction, whether or not it carries a required-quality-review
binding. Real database regressions verify that an advanced document
revision or deleted attachment refuses the entire batch without
recording approvals, and current ordinary output reviews still resolve.
All 272 combined migration/review/interaction tests pass; workspace
typecheck/build passed. Fresh exact-head Greptile and CI are pending.
The automatic Superagent scan ended inconclusive at checkout; one
documented on-demand retry is pending. These are explicit verification
limits, not passed security results. The P1 thread is resolved.
- Master consumed the next migration slot three times during this
verification pass: confirmation recovery took 0398, continuation
recovery took 0399, and GitHub acknowledgement recovery took 0400. Each
upstream SQL/journal/snapshot is preserved unchanged. Preferences are
now generated as idempotent `0401_white_lenny_balinger.sql` from
upstream 0400; exactly five snapshots remain, and replay coverage
locates this migration by table content. This is recorded concurrent
integration churn, not a claim that older green results apply to the
latest base.
- Head `ed3b68da9` fixed the two history/URL findings with 26 focused
regression tests, server/UI typechecks, workspace build and token gates
passing. Greptile then scored that head 4/5 with the stale-output P1
corrected in the current head. Its partial CI is superseded, not counted
as current acceptance.
- Previous filter-fix head: `ed3b68da9`, based on the `8458d39d9` merge
of master `063cfd438`. The two fresh Greptile findings are fixed:
history outcome filters now match recorded per-item verdicts in SQL
before pagination (mixed reviews remain in both applicable outcomes),
and same-page URL assignee changes/back/forward navigation update that
filter without clearing independent filters. All 26 focused
database/navigation/collection tests, server/UI typechecks, workspace
build, token gates and whitespace checks pass. The two review threads
are resolved. Fresh exact-head CI, Greptile and Superagent results are
pending.
- The `8458d39d9` migration integration also passed all 328 targeted
migration/interaction/confirmation tests, workspace typecheck/build and
Superagent security scan. Greptile scored that head 4/5 with the two
functional gaps fixed in the current head; those prior-head checks are
not current acceptance.
- Migration integration head:
`8458d39d9721f4cb312c2390070a0609f8cddd1a`, integrating master
`063cfd43813cabf18417605fb9eefb9aacf95c8d`. GitHub reports MERGEABLE
after the push. Master advanced twice during this conflict-resolution
pass: first its confirmation-recovery migration took 0398, then its
continuation-recovery migration took 0399. Both upstream migrations and
journal entries remain unchanged; Coordinator preferences are now
generated as idempotent `0400_sad_guardian.sql` from upstream's latest
snapshot. Exactly the five newest snapshots remain. The replay
regression now locates the table migration by content instead of
hardcoding a renumbered filename.
- All 328 targeted question/review/confirmation/migration tests passed
again after the second merge. Workspace typecheck/build and fresh
exact-head CI/reviews are in progress. The preceding `0c46f46d6` passed
workspace typecheck/build and Superagent security scan, but was
superseded because master consumed migration 0399 while those checks
ran. That prior-head result is not acceptance of the current head. No
production settings or runner/security permissions were changed, and the
PR has not been merged.
- Previous integration head: `0c46f46d6f2b23417ab872ce3cb6ff2673647287`,
integrating master `287b04d72f1b9fca1412e05435c75b8302ba0710`. GitHub
reports MERGEABLE after the push. The renewed conflicts were
`0398_snapshot.json`, `_journal.json`, and the top imports in
`issue-thread-interactions.ts`. Upstream's `0398` confirmation-recovery
index and journal history are preserved unchanged; Coordinator
preferences were regenerated as idempotent `0399_bouncy_miek.sql`, with
replay coverage updated and exactly the five newest snapshots retained.
Both terminal confirmation notifications and Coordinator task
assignment/required review behavior are preserved.
- All 328 targeted interaction/review/confirmation/migration tests pass,
as do workspace typecheck, map validation and whitespace checks. The
workspace build and fresh exact-head CI/Greptile/Superagent checks are
pending. The first migration-generation attempt hit the sandbox's local
IPC restriction before generating files; the unchanged authorized local
generation completed successfully. Prior-head green checks below do not
establish acceptance of this merge.
- Previous acceptance head: `8b7dcf739ed15afc51351fdfa0e0e5fbc75ab788`,
with master `1aa3a21ac` integrated and GitHub reporting MERGEABLE.
Greptile completed a fresh 5/5 review on this exact head with zero new
actionable findings and no open review threads. The [fresh CI
workflow](https://github.com/paperclipai/paperclip/actions/runs/40752864319)
completed SUCCESS on attempt 2 at 19:40:08 UTC, including all eight E2E
shards. Final completed check set: 55 succeeded, four conditional checks
skipped, zero pending/queued/running checks, and one
neutral/inconclusive Superagent scan. The auxiliary commitperclip review
and isolated native Runner compilation/cache-reuse check both passed.
This is not a claim that Superagent produced a passed security verdict.
GitHub still reports MERGEABLE against current master
`60b8089a44b4eaa37e627adbfdf2f130bda13335`.
- Current-head E2E: all eight shards and the aggregate passed, including
the previously failing YAML browser journey. Serialized server shard 9/9
failed: the protected YAML projection test exceeded its original
15-second timeout; its late update request then reached the next test's
reset mock (the captured payload is the prior test's model/label
update). All 88 tests in that exact unchanged file passed locally in
38.03 seconds, with no timeout or assertion changes. The original
slow-request cause remains unproven. CI failure log:
`/tmp/pr17983-8b7-serialized9.log`; local recovery:
`/tmp/pr17983-adapter-yaml-repro.log`. The single bounded unchanged
shard rerun passed, and the workflow completed SUCCESS. Rerun log:
`/tmp/pr17983-8b7-serialized9-rerun.log`. The initial failure is
retained; a passing retry does not establish its original slow-request
cause.
- Greptile scored preceding head `4873704be` 5/5 with one valid P2:
opened task decision records missed company-scoped live invalidation.
The current head uses the existing company decision prefix for
resolution and effect-completion events, and resets private record
payloads on access changes. Its thread is resolved. All 107 focused
record/live-update tests, UI typecheck/build, token checks and
whitespace checks pass.
- CI on `4873704be` failed E2E shard 7/8 in the Advanced YAML
lost-creation-response journey: its clipboard helper selected page text
starting with “Skip to Main Content” instead of YAML. The exact
unchanged journey passed in a disposable local browser instance (1 test,
17.1 seconds). No assertion, timeout or production behavior was
weakened; the original failure cause remains unproven. Failure log:
`/tmp/pr17983-487-e2e7.log`; local check:
`/tmp/pr17983-agent-yaml-repro.log`. The full unchanged Advanced YAML
browser suite also passed locally (6 tests, 37.8 seconds). Fresh
current-head CI subsequently passed this journey and all other E2E
shards.
- Both the automatic and one supported on-demand Superagent scan on
`4873704be` ended neutral/inconclusive: “Pinned PR scan merge-base
checkout failed or timed out.” These do not count as a passed security
verdict. The current head's automatic scan and one documented on-demand
retry also returned the identical neutral checkout failure, with zero
annotations or further diagnostics. This is an external scanner blocker,
not a passed security verdict. No security settings or permissions were
changed.
- Recorded decision links now render and focus the full source-task
record in both Classic and Coordinator, including recorded choice,
submitted inputs, and the existing effect-result resolver. Fresh
terminal records take precedence over older open-decision cache entries.
Context and account checks keep mismatched or inaccessible records out
of the DOM; no decision-history tab was added to tasks or chat. The
shared company live-run feed now drives live-only filtering, including
ended runs and terminal tasks with stale run entries. All 213 focused
tests, UI typecheck/build, token and whitespace checks pass; the final
focus follow-up passed all 188 task-detail tests and UI typecheck. The
first new navigation test failed because its test host omitted company
context; the host was corrected before the passing run.
- Previous integration head: `375c5e89516705050d94bab99336212841b2e6e1`
merges master `1aa3a21ac` after four additional upstream commits. The
sole conflict was competing imports in `server/src/services/issues.ts`;
both quality-review policy and inbound wake-notice notifications are
preserved. The PR-specific review import now sits beside
execution-policy imports instead of the frequently changing first line.
GitHub mergeability is rechecked after the push.
- On the combined master tree, workspace typecheck/build, all 153
affected UI tests, map validation, and whitespace checks pass. Four
server suites passed 77 tests; the fifth suite's module-import hook
timed out while broad verification was running. Its unchanged isolated
run passed all 41 tests in 7.2 seconds with the original timeout. This
records recovery without claiming the original import-timeout cause is
proven. CI on `375c5e895` passed every substantive job, including all
eight E2E shards and Superagent; Greptile found the two functional gaps
fixed in the current head. A short-lived `669d90876` commit added the
main fixes before the focused navigation follow-up.
- Immediately preceding head `9d9737b49` completed all 56 checks
successfully with four conditional skips, Greptile 5/5 and no open
findings, plus a successful Superagent scan. The signoff E2E shard
passed on its single accepted rerun; its initial cancellation/timing
failure is retained below. Master moved again while those checks ran,
requiring this final integration rather than treating the prior head's
green result as current acceptance.
- Previous head `9d9737b496911a6054d0ea22d1b42b28b115e9ab` includes
master `d30c8f42b842327ee1c18c41a2efd6ba623da5cd`; that head was
subsequently conflicted by moving master. The master merge preserved
durable account-bound writes and Coordinator UX. Workspace
typecheck/build, 416 focused UI tests, and 142 affected comment-route
tests passed. A stable full UI run on preceding head `938ad1665` passed
all 9,833 tests across 836 files; its final full workspace build also
passed.
- Greptile found nested proposal project inheritance and Classic
bound-revision links on `91be74952`. Both were fixed with 142
interaction-route tests, 113 focused UI tests, and UI/server typechecks.
Its next review identified a valid draft-preservation bug in the new
Classic loading UI. Head `9d9737b49` keeps loading/error notices outside
editors and annotations while preserving dirty drafts; 115 focused
review UI tests pass, including pending/failed revision loads and
continued draft editing. All related threads are resolved. Greptile
completed a fresh 5/5 review of
`9d9737b496911a6054d0ea22d1b42b28b115e9ab` with no open findings.
- CI on `938ad1665` exposed an integration regression with the newly
merged durable startup saves: the personal preference gate blocked the
task page before its first session lookup. The guarded title editor now
mounts while that lookup is pending, with presentation-specific tools
still gated. All 216 affected component tests pass. The unchanged
five-test `disconnect-write-recovery.spec.ts` browser suite passes
against a newly launched disposable local-trusted PostgreSQL instance on
port 33219, including the exact failed startup-save journey. No live
provider, hosted authentication or production proof is claimed. The
helper-owned test server exited and the port has no listener. UI
typecheck, built-browser assets, token and whitespace checks pass.
- Initial durable-write merge tests found duplicate imports and unscoped
draft fixtures, fixed before 416 focused tests passed. A sandbox
typecheck could not create its IPC socket; the supported rerun passed.
The first revision-link test used a wrong Return to latest button
assertion, corrected before the 113-test pass. The startup E2E
reproduction initially still failed because an outer shell gate also
blocked the page; the subsequent fix passed all five cases without
changing the test or its timeouts. A focused loading-header assertion
initially used an incorrect fixture title; correcting it preceded the
216-test pass. These failures remain recorded.
- Earlier routing gates fell back to GitHub-hosted runners while master
was moving or conflicted. Superseded queued runs were cancelled, then
the `938ad1665` routing gate explicitly selected the ephemeral RunsOn
fleet. Its CI actively executed and completed most tests; only the
diagnosed startup E2E shard and aggregate failed, alongside the valid
Greptile finding. Auxiliary GitHub-hosted workflows also completed
successfully on earlier heads, so queueing alone is not an
administrative blocker. Fresh [CI on
`9d9737b49`](https://github.com/paperclipai/paperclip/actions/runs/40744012678)
is the acceptance target; the previously failing startup E2E shard now
passes. A different signoff E2E shard failed during executor
resubmission when its fixture run was cancelled as
`issue_continuation_waiting_on_review`. The exact unchanged journey
passed locally (1 test, 46 seconds), and the preceding head with
identical server/signoff code passed that CI shard. This supports a
bounded rerun but does not establish the timing failure's root cause.
After the workflow finished, GitHub accepted one rerun of that failed
shard and its dependent aggregate; both passed, completing all checks on
that head. The failure log is retained at `/tmp/pr17983-9d9737-e2e7.log`
and the local reproduction at `/tmp/pr17983-signoff-repro.log`. No
assertion or timeout was weakened.
- On the first merge, full workspace typecheck/build, all 9,622 UI
tests, 267 tests across seven affected server suites, two migration
checks, map validation, token gates, and the PR diff whitespace check
passed. Greptile then found duplicate local task-search filtering and
lost completed item-review detail. Both are fixed, with 42 passing
focused UI tests and passing UI typecheck/build.
- A subsequent Greptile review found attachment confirmations without
working links and mobile history without a visible host. Confirmation
layouts now derive the authenticated immutable-content endpoint from the
attachment ID, and Needs You uses the existing full-screen mobile sheet.
All 119 focused tests pass, including missing/stale display URLs, both
review layouts, and both mobile history entry buttons. UI
typecheck/build and token checks pass. Full workspace typecheck/build
also pass after the second master merge.
- Greptile gave head 22f69c304 a 5/5 score with one non-blocking
desktop-history reopening finding. Head 6dd52b6d3 fixed it, passed all
nine history tests, UI typecheck/build, token gates, and the full
9,679-test UI suite, then received a fresh 5/5 review with zero open
findings. These are prior-head results; review on the master-sync commit
is pending.
- The chat and workspace CI jobs on head 22f69c304 were interrupted by
runner shutdown signals and cancellation before completing their tests.
Their logs do not report failing assertions. Those interrupted jobs are
not claimed as passes. The new head starts fresh runs.
- The first merge CI had a Slack session-sync idle assertion fail after
an unexpected database read. Its exact isolated reproduction passes, and
the chat CI shard passed on head 618c5a2a3. The original failure's cause
remains undetermined. The broader local reproduction, run concurrently
with full verification, instead encountered 21 timeout failures across
its two test chunks; it is not claimed as a passing full local server
run. A concurrent local UI run had eight failures (seven timeouts and
one delayed autosave assertion). The complete UI run on the final head
passed all 9,679 tests across 830 files with two workers; no test
timeout or assertion was weakened. This establishes recovery without
claiming that every earlier timeout's cause has been proved. An earlier
intermediate UI run also overlapped the second master merge and failed
the newly added Advanced-sidebar expectation, so it is not treated as
stable-tree evidence. The newly merged UI dependencies initially
required refreshing the local install from the upstream package
manifest; the generated local lockfile update is not committed, per
repository policy.
- Superagent returned neutral/inconclusive scans on the preceding heads
because its pinned merge-base checkout failed or timed out. The
available retry endpoint returned 404. These are not successful security
verdicts. The fresh scan on `91be74952` passed (PR scan passed; no
suspicious PR changes detected). The `938ad1665` scan again returned
neutral/inconclusive with the same pinned merge-base checkout error; the
check-suite rerun endpoint returned 404. The fresh `9d9737b49` scan
completed successfully at 18:22 UTC with no suspicious changes detected.
Earlier neutral scans are not counted as successful security verdicts.
- Prior head `57902152ac3218096fca669d33ff18400a2a86ae` passed 9,618 UI
tests across 826 files, received Greptile 5/5 with no open findings, and
completed CI with 56 passes and four conditional skips. These are
historical results, not acceptance of the latest merge commit.
- The first full build found generated capability-contract drift. The
generated outputs were refreshed. Initial sandbox runs could not open
local IPC sockets; verification was rerun with local test access.
- Current master was merged. The workspace preference migration was
regenerated after the existing migration history.
- The UI run first found two outdated expectations: early custom-answer
validation and the document access error copy. Both were corrected, and
the full UI suite then passed.
- The local server run found three failures in unchanged tests. The Muse
test passes with Python 3.13 instead of the host's Python 3.9. The two
workspace tests pass when their test process uses the expected master
default branch. These environment settings do not change application
behavior or global machine settings. The unsharded server run was
stopped after those reproductions; CI supplies the full sharded server
result. No successful full local server run is claimed.
- Skill inventory generation needs an external eval checkout, which is
absent locally. The existing generator functions refreshed only the live
skill inventory and its derived files. The checked-in eval inventory was
preserved. The inventory validation gate passes.
- Greptile found a dropped MCP review requirement, missing per-item
output links, generic item-review summaries, and a history-refresh
failure. The fixes have 32 passing database-backed server tests and
focused rendered-card tests. A follow-up partial-review finding was
corrected by forwarding the canonical mutation status before settling
the card. Attachments open through the authenticated immutable-content
route in both card layouts. The final focused UI set has 117 passing
tests, including these regressions.
- Both browser shards that first failed expected a disabled-chat
message. The copy was restored, and those shards passed in CI on the
next commit. The two journeys also passed locally. One local attempt
first timed out before feature disable while waiting for the provider's
initial message; its isolated reproduction passed. That earlier timing
failure remains recorded and is not presented as an explained
infrastructure failure.
- Serialized server shard 9 first failed during pnpm setup with
ECONNRESET, before dependencies or tests ran. Its single rerun passed
setup and all tests. The build and production runtime boot passed on the
first attempt, but that run's public-install step timed out during Pi
setup. The single build-job rerun passed compilation, runtime boot, and
clean public-install verification. Those setup scripts are unchanged by
this PR. The successful retry establishes recovery; the earlier Pi
timeout's underlying cause remains undetermined. The aggregate CI gate
is green: [workflow
run](https://github.com/paperclipai/paperclip/actions/runs/40637789695).

</details>

## Risks

- This touches shared task, interaction, and completion paths.
Regression tests must cover classic and experimental behavior,
authorization, duplicate answers, and stale review targets.
- The additive preference table must migrate before the setting is used.
The setting defaults off.
- The experiment changes navigation and message presentation. Canonical
task and document records remain the source of truth.
- The initial task brief and saved plan can repeat information. This
change fixes chronology; a broader redundancy policy remains a design
decision.

## Model Used

OpenAI GPT-6 Codex with reasoning and tool-assisted code editing, tests,
and browser verification. Earlier iterations used Codex models in this
task; their exact model IDs are not available in the current context.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used
- [x] I have checked ROADMAP.md
- [x] I have searched GitHub for duplicate or related PRs
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change
- [x] I have run relevant tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have documented risks
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open recommendations or follow-ups
- [x] I will address review comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 17:20:01 -07:00
DottaandPaperclip c74171d620 fix(recovery): retire superseded native workspace retries (#18077)
## Thinking Path

> - Paperclip coordinates agents while retaining their work and
execution authority.
> - A failed native run can schedule an exact-session retry and retain a
sandbox.
> - An explicit task Retry can already have completed successfully on a
successor.
> - Recovery correctly refuses the old run after its task execution lock
changes.
> - It nevertheless leaves that old retry scheduled and its workspace
without a preservation owner.
> - This change retires that proven superseded retry and registers
exact-source preservation together.
> - Existing stop receipts and saved-file verification still control
workspace switching.

## Linked Issues or Issue Description

**What happened?**

A native sandbox run failed before starting a provider turn. An explicit
Retry completed on a linked successor. The original coordinator remained
in `retryable_failure` with an active sandbox lease. Restart recovery
returned `issue_execution_lock_changed`, while the ordinary sweep kept
delaying it. A pending workspace selection then made every new task run
fail during setup.

**Expected behavior**

Stop replaying a failed retry after its linked explicit successor has
completed. Preserve the original files through the existing system
worker. Keep the current task, ownership, pending choice, and unresolved
action outcomes intact.

**Steps to reproduce**

1. Persist a failed, unowned native run with a prepared remote workspace
and `retryable_failure` coordinator.
2. Complete a same-company/task/agent explicit Retry linked to that run.
3. Release the task's old execution lock and schedule a workspace
selection.
4. Run startup or ordinary retry recovery. Observe the old retry remain
scheduled and the selection fail with an unfinished-recovery conflict.

**Paperclip version or commit**

Regression reproduced against `644937c931`. The current repair is based
on refreshed master `60b8089a44`.

**Deployment mode**

Native Runner with remote sandbox workspaces. The reported runtime used
ACPX Claude with per-turn lifecycle. The original provider
session-resume rejection is not independently reproduced or claimed
fixed here; this PR addresses the subsequent stranded recovery.

Related: #17839 records preservation when restart classification becomes
terminal. This change handles the earlier lock-mismatch return and
ordinary retry admission after a completed explicit successor. It uses
the same preservation service and does not require that PR.

## What Changed

- Share a narrow superseded-retry settlement between startup recovery
and the ordinary retry sweep.
- Require a failed source with no coordinator owner or process, its
exact prepared source lease, and a completed linked successor under the
same company, task and agent.
- Atomically retire replay and register preservation. Do not alter task
state or create another provider run.
- Add PostgreSQL lifecycle/safety regressions, a real-file preservation
and workspace-selection regression, and execution/map documentation.

## Verification

- Red: both startup and ordinary admission regressions left the old
coordinator in `retryable_failure` with no preservation obligation.
- Green: the same two cases retire the retry and retain the exact lease
without another run or task mutation.
- The assembled PostgreSQL/filesystem regression passes: workspace
selection remains blocked before preservation, the existing service
saves `saved.txt` and preserves newer local work, then the normal
selection guard applies the pending shared workspace.
- All 90 native retention/resumption cases pass. Three neighboring
startup-recovery cases pass, including the blocked-owner inventory. Full
recursive typecheck and full build pass at runtime head `23ddb213b4`;
final `19d7738ae3` only moves the function comment into execution
documentation. Map, module-boundary and diff checks pass. The duplicate
full local Vitest run was stopped after 20 minutes in its first long
general shard once the complete current-head hosted test gates passed;
no complete local-suite pass is claimed.
- Current-head CI has 53 passing checks and two intended Storybook
skips, including full typecheck, all test shards, build, Runner
verification, browser shards and both aggregate gates. The separate
`commitperclip PR Review` job is still queued on `ubuntu-latest` with no
assigned runner; its outcome remains pending. Greptile reviewed exact
head `19d7738ae3` at 5/5, with zero unresolved threads.
- Live acceptance passes on exact final source `19d7738ae3`: a
disposable Daytona Linux sandbox, the current immutable staging fleet
snapshot, SDK 0.203.0, a Darwin arm64 source host and Node 26.4.0. The
real native workspace preparation/export and provider stop/start paths
preserve an unpredictable report and newer host files. The ordinary
workspace-selection guard stays blocked until preservation commits, then
applies the pending shared workspace.
- The old workload's start count and side-effect marker each remain one.
Recovery creates no new run or native result. The sandbox finishes
stopped and is then deleted by the probe; a final provider read confirms
it is absent.
- A second live acceptance also passes on the original runtime's older
immutable snapshot with the source explicitly archived before recovery.
It verifies cold source reopening, the same report/newer-file checks,
one workload start and side effect, pending workspace application, and
confirmed deletion. Its initial probe attempt used immediate
archive/deletion reads and failed during asynchronous cleanup
observation; bounded provider-state polling fixed the probe without a
product change. The abandoned probe allocation is independently
confirmed absent.
- Scope: database fixtures represent the already-failed run and
completed explicit successor. The old workload is a persistent shell
process with observable file/side-effect markers, not a paid Claude
turn. This qualifies the repaired recovery handoff and real provider
preservation; it does not reproduce the initial ACPX session-resume
rejection.
- The original hosted task has only been inspected read-only. No rollout
or original-task recovery is claimed.

## Risks

- Incorrect successor classification could retire legitimate work.
Matching requires the server-persisted explicit Retry link, same
company/task/agent, later successful committed execution, no current
source execution lock, no recorded process, no coordinator owner, and no
workspace finalization owner.
- Retirement is not a stop receipt. The exact source remains retained,
unknown effects remain unknown, and workspace switching still waits for
the existing worker's stop and file-persistence proof.
- A failed preservation transaction rolls back retirement. No new scan,
retry budget, schema or public API is introduced.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use and code execution.
The host does not expose a more specific model ID or 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
- [x] I have run tests locally and they pass — focused suites and live
acceptance; full-suite status above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green — separate template-review job
still queued as noted above
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
exact head `19d7738ae3`
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 15:15:19 -05:00
DottaandPaperclip 60b8089a44 fix(runner): trust managed Cloud sandbox images (#18066)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Cloud selects and updates the sandbox image used by its agents.
> - Runner admission also required saved qualification for the exact
snapshot and configuration.
> - An image update left the old record stale and stopped work before
runtime startup.
> - This pull request trusts the image selected by Cloud and uses the
real runtime startup check.
> - Agents can continue after an image update without an operator
running a separate qualification test.

## Linked Issues or Issue Description

**What happened?**

A managed Cloud image update could cause
`sandbox_snapshot_qualification_required` before provider work began.
Runner discovery also fell back to Legacy when saved platform
qualification was absent. The agent Test action could require a separate
qualification request even when discovery already offered Paperclip
Runner.

**Expected behavior**

A managed Cloud image can start without a saved qualification record.
Runtime startup and the handshake report actual compatibility failures.
Custom images keep their existing qualification rules.

**Steps to reproduce**

1. Use Paperclip Runner on a Paperclip-managed Cloud sandbox.
2. Save qualification for its current snapshot.
3. Update the platform-selected snapshot and leave the old record in
place.
4. Start a task. Before this fix, admission rejects the stale record
before starting the provider.

Related work: Refs #17445, Refs #17724, Refs #17448. These changes cover
saved-computer qualification and setup tests. This fix removes the
qualification prerequisite only for managed Cloud images.

## What Changed

- Use one managed-image policy in runner selection and lease admission.
Require the active Cloud configuration to provision the provider. Active
captured custom images are excluded.
- Use the current Cloud image and ignore missing, stale, revoked or
valid saved qualification records for that image.
- Reuse the existing provisioned-runner selection path. Keep adapter
availability checks and the Legacy choice for managed sandboxes.
- Read custom-image metadata directly during discovery without resolving
provider credentials.
- Use the existing template-matching rule for captured images. Ignore
outdated captures, preserve qualification for matching custom captures,
and fall back to Legacy discovery for malformed saved capture config.
- Skip the separate qualification request when discovery already offers
Paperclip Runner as the default. Test checks the actual runtime.
- Add regressions for image updates, provider failures, custom images,
self-hosted environments and company access. Update the development and
verification guides.

## Verification

- Before the fix, managed-image discovery regressions returned Legacy,
and the rendered Test action called the separate qualification endpoint.
- The original runtime source fails four of the five managed-image
regression cases. The fixed runtime passes all five, including provider
startup error propagation. The baseline check uses the original module
source through a temporary Vitest transform and the same database-backed
tests.
- All 603 focused tests pass: 231 runner selection, 185 environment
runtime, 10 snapshot qualification, 168 rendered agent form and nine
form source controls. Discovery controls cover unavailable credentials,
stale managed markers without an active provisioner, outdated captures,
matching custom captures and malformed saved config. The
outdated-capture regression fails before the fix and passes afterward.
- `node scripts/check-maps.mjs` and `pnpm check:token-gates` pass.
- Full `pnpm -r typecheck` and `pnpm build` pass. All five focused files
passed together on `8275bbe72bb4d91fb3a02fb0658f0846b2abc966`
(`codex/simplify-managed-runner-readiness`, Node 24.19.0, macOS ARM64).
- The full local `pnpm test:run` suite is still in progress. Hosted CI
is waiting at `ci / gate / Select trusted runner`; the separate `review`
workflow is queued. Greptile is 5/5 on the current head, and both review
threads are resolved. This PR is not yet verified by full CI.
- Live fixed-source Daytona acceptance is not verified. This workspace
has no Daytona API key or image configuration. The earlier deployed
recovery is not evidence for this source change.

## Risks

- Managed Cloud now trusts its selected image. A bad image can fail at
real runtime startup instead of a saved qualification gate.
- Company access, credentials, runtime integrity and handshake checks
still apply. Self-hosted sandboxes, custom environments and active
captured custom images keep their qualification and immutable snapshot
binding.
- No schema change or data migration is required. Existing qualification
records can remain in place.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 14:39:26 -05:00
DottaandPaperclip c4b6168e08 fix(server): disclose assigned tool search page bounds (#18056)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/187/changes/paperclip/187
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the control plane for AI agents at work.
> - Native agents find connected app tools through the assigned-tool
search tool.
> - Large catalogs require small pages and an offset for the next page.
> - The input schema enforces a maximum of 20 results, but its
descriptions omit that number.
> - Providers can render the integer field as a plain number and hide
its numeric bounds.
> - This pull request puts the existing range and default in both
descriptions.
> - Agents can choose a valid page size before they make a search call.

## Linked Issues or Issue Description

**What happened?**

An agent can request `limit: 50` for `paperclip_search_assigned_tools`.
The tool rejects the call with `invalid_tool_call` at
`/properties/limit/maximum`. Its model-visible description does not
state the accepted range.

**Expected behavior**

The tool description and the `limit` description must state the range of
1 to 20 and the default of 5. Agents can use `nextOffset` to read more
results.

**Steps to reproduce**

1. Inspect the assigned-tool search description in a provider tool list.
2. Render the integer schema as a TypeScript number field.
3. Request `limit: 50` without a visible page-size bound.
4. Observe the validation error. Retry with a valid size and offset.

### Hypothesis and thesis for a fix

The numeric schema is correct, but the descriptions omit the page limit.
Put the existing range and default in text that all providers can see.
Keep the strict validation in the assigned-tool discovery owner. This
should reduce avoidable retries. It does not guarantee that every model
call will be valid.

## What Changed

- State the accepted range and default in the search description and the
`limit` property. Add the existing default as schema metadata.
- Test the tool listing and calls through the real HTTP MCP bridge for
both compact delivery paths.
- Document the page size and offset procedure in the Runner README and
verification maps.

## Verification

- Red: the two new bridge tests fail against the unchanged
implementation because the listing omits the numeric guidance.
- Green: all 37 tests in
`server/src/services/native-runtime/assigned-mcp-tools.test.ts` pass
after the change. The tests cover default pages, a 20-result page,
offset continuation without duplicates, and rejection of 21 and 50.
Existing tests cover grants, revocation, modes, approvals, aliases, and
schema chunks.
- Current head `7d658d0c4e4d9db3feb53a5c508214440ff058c4`: 37/37 focused
tests pass locally. Greptile is 5/5 with no unresolved threads.
Current-head CI is green, including typecheck, build, unit tests, Runner
checks, and all browser shards ([CI run, attempt
2](https://github.com/paperclipai/paperclip/actions/runs/40733284523/attempts/2)).
Browser shard 7 initially failed in a newly merged agent YAML editor
test when its clipboard read included the whole page. The single retry
passed without a code change; the exact cause is unconfirmed. The
original failure remains in [the CI
log](https://github.com/paperclipai/paperclip/actions/runs/40733284523/job/122975224906).
- Run the focused suite from `server/`: `pnpm exec vitest run
src/services/native-runtime/assigned-mcp-tools.test.ts`.
- `node scripts/check-maps.mjs` and `git diff --check` pass.
- The bridge uses real local HTTP. The app gateway uses synthetic
descriptors. No deployed build or live model improvement is claimed.
- Full local verification is incomplete. Recursive typecheck and server
typecheck require `cargo`, which this workspace lacks. A direct server
TypeScript check was killed by the workspace. The full test suite had no
final verdict before the resource stop. CI must supply the remaining
verification.

## Risks

Low risk. This change describes existing limits and adds default
metadata. It does not change search execution, page caps, gateway
access, revocation, approvals, or audit. Models can still send invalid
calls. This change has not measured their future retry rate.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used, its capabilities, and unavailable
model metadata
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs
- [x] I have described the issue in-PR following the bug report fields
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] The public branch name describes the change and has no internal
task ID
- [x] I have run the focused tests locally and they pass
- [x] I have added tests for the reported failure
- [x] I have updated relevant documentation
- [x] I have considered and documented risks
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open recommendations or follow-ups
- [x] I will address reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 13:55:48 -05:00
DottaandPaperclip 21137db805 fix: make Check now work for retained monitors on blocked tasks (#18061)
## Thinking Path

> - Paperclip lets people manage agents and inspect their work.
> - Task monitors schedule checks of work that is still pending.
> - A task can retain a monitor after it becomes blocked.
> - The UI still offered Check now, but the server rejected the task
status.
> - The UI also claimed that an automatic check would run on the next
tick.
> - This change admits an explicit human check through the normal
execution gates and shows that automatic checks are paused.
> - People can request the check without changing task status, and
skipped checks no longer report success.

## Linked Issues or Issue Description

**What happened?**

A blocked task with a retained monitor showed Check now and an overdue
countdown. Clicking the button failed because manual checks required an
in-progress or in-review task. The endpoint also returned success when
admission skipped a check.

**Expected behavior**

A human can request one check through normal admission. Automatic checks
stay paused while the task is blocked. A check that cannot start reports
a conflict.

**Steps to reproduce**

1. Schedule a monitor on an agent-owned task.
2. Let the task become blocked while it retains the schedule.
3. Open the task and click Check now.

Related: #14909 addresses scheduled-retry promotion. This PR addresses
retained task monitors.

**Paperclip version or commit**

Base: 7f10cc0585.

## What Changed

- Allow a human to check a retained monitor on a blocked task. Keep
agent and automatic checks limited to active task statuses.
- Keep the existing admission path and status guard. Do not change task
status to start a check.
- Return 409 when admission skips the check. Preserve the schedule when
a dependency or recovery hold prevents dispatch. Keep a successful
result when a new schedule replaces the consumed schedule after
admission.
- Show Automatic checks paused in the banner, composer strip and
properties. Hide Check now on backlog and todo tasks. Provider-quota
recovery stays paused on blocked tasks because it uses a direct retry
path; its monitor is retained until the task resumes.
- Add database, process, route and UI regression coverage, a Storybook
state, API metadata, and behavior documentation.

## Verification

- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- Server scheduling, process admission and route suites: 94 tests
passed.
- UI monitor, properties and time-formatting suites: 142 tests passed.
- Additional admission checks passed: an explicit check starts a process
on a blocked task; an unresolved dependency prevents dispatch and
preserves the monitor.
- Token gates, map checks, Storybook catalog checks and 30 map/catalog
tests passed.
- The full local `pnpm test:run` attempt reported 1 timeout among 1,621
chat integration tests: “keeps an ambiguous github text part blocked
across restart and retries only that part and its tail” exceeded 15
seconds. The exact case passed in isolation on the final head (1 passed,
1,620 skipped). The remaining full-run groups were stopped to isolate
that failure. This does not establish a full local pass or explain the
initial timeout. Final-head CI is green, including the full chat lanes
and the successful single server-shard retry.
- Browser inspection passed for the blocked-task banner, composer strip
and properties row. Clicking Check now set both visible buttons to
disabled Checking state. The preview uses isolated fixtures.
- CI server shard 7/12 failed one decision-expiry deadline assertion.
The entire unchanged decision-expiry suite passed locally on the final
head (20/20). The single retry of that shard passed after the first
workflow attempt completed. The initial failure remains recorded here.
Neither that test nor its production path changed before retry; the
cause is not established by a passing retry.
- Greptile reviewed final head ed936f7433
at 5/5. Both prior review threads are resolved.
- The first CI chat job stopped after its runner received a shutdown
signal. The final head completed a fresh CI run.
- The process fixture uses a local no-op adapter. It proves admission
and execution, not a live provider's response. The Storybook state
simulates dispatch.

## Risks

- An explicit human check can start work on a blocked task with no
unresolved execution gate. This is intentional. Dependencies, recovery,
native finalization, ownership, pause and budgets retain their existing
checks.
- Skipped manual checks now return 409 instead of 200. The UI already
displays API errors in context.
- No schema change or migration.

## Model Used

OpenAI Codex, based on GPT-6. The session does not expose a more
specific served model ID or context-window size. Used repository tools,
code execution, and browser inspection.

## 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-28 13:01:11 -05:00
d30c8f42b8 feat(ui): keep writes durable through temporary disconnects (#17960)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/123/changes/paperclip/123
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People save tasks, write documents, make decisions and send board
messages.
> - A disconnect can hide a response after the server accepts a write.
> - Recovery must keep the original account, task and request key.
> - The merged connection foundation in #15754 handles reads and shared
outage state.
> - This change adds bounded write recovery and explicit actions when
recovery stops.

## Linked Issues or Issue Description

**What happened?**

Temporary failures could lose edits, report accepted writes as failures,
or require people to copy and send input again. A retry could target a
newly selected task or account. Restoring attachments could create a
second task.

**Expected behavior**

Keep the draft, its owner and its target. Retry only operations with a
server contract that prevents duplicate writes. Verify uncertain
results. Show conflicts and permanent failures, with an explicit resend
or cancel action.

**Steps to reproduce**

1. Save a task title during an outage, then open another task before
recovery.
2. Restore a task creation that needs files, selecting those files in
another order.
3. Lose a document or decision response, then interrupt the verification
read.
4. Switch accounts while a create, upload or connected-channel
publication is pending.
5. Type and erase a new-task draft before the first account lookup
completes, then reopen it.

This PR carries the write layer from #15769 and its review fixes. It
targets master after #15754 merged. Related test cleanup #16952 already
covers the unchanged copy-link toast test; this PR does not duplicate
that work.

## What Changed

- Add bounded autosave and submit jobs for supported writes, with
pending, conflict and manual retry states. Retain admitted autosaves
after navigation and preserve newer task revisions.
- Keep each job with its original account, task and operation. First
account resolution adopts admitted startup work; a later account change
cancels old work. Remount inline and document editors when their owner
or document subject changes.
- Preserve task-creation keys and immutable request snapshots through
file reattachment. Restore generated document keys before comparing
reselected files. Reject changed requests instead of creating a second
task.
- Check the original account scope before creates and each upload. Save
successful upload receipts before stopping on an account change.
Identify attachments by content digest and metadata.
- Verify uncertain document and decision results. Replay only plain,
keyed comments automatically; combined reassignment, reopen and
run-setting changes require receipt reconciliation or cancel. Settle
each request once when a receipt races its retry.
- Scope drafts and connected-channel publication reads to their owner.
Keep unowned older records unread and unreplayed, with an explicit
confirmed discard action after Activity inspection. Preserve typing
through the first session lookup, keep erased text erased, and report
browser persistence only when storage succeeds.
- Wait for the first account lookup before sending startup status
changes or decisions. Retry failed required lookups with a fixed limit
and surface exhaustion to the original action. Preserve uncertain
comment keys on account cancellation. Check the account generation
before a comment retry calls its sender and again immediately before
POST after asynchronous preparation. Retire only that request’s
optimistic echo on completion.
- Return an ordinary comment’s accepted same-company, same-task,
same-user receipt before workspace reopening, task status changes or
wakeups. Reused keys with changed text still conflict. Complete
reference and activity records through the same finalizer for initial
sends and accepted retries. It locks the task before its comment,
matching task and company deletion, comment removal and tombstoning,
rejects removed or tombstoned comments, repairs references and inserts a
missing activity record in one transaction, and publishes after commit.
- Remove reader-only record and comment-body size caps so accepted
browser writes remain readable, including JSON-escaped comment requests
in local and session storage. Update four existing Storybook fixtures to
use owned draft keys.
- Document the write contracts and add regression and real browser
recovery coverage.

- Add the exact reviewed-save recovery regression for both composer
implementations and reloads. Align receipt completion, both comment
deletion methods and company deletion with task deletion by locking
tasks first. Cover real task and company deletion races.

## Verification

- The exact reviewed-unknown-save regression fails in all four cases on
original commit `1ed0af4186`. It passes with this PR for both composers,
before and after reload. Cancel keeps the text and uploaded receipt. The
retained draft sends, and the next message also sends. Run `pnpm exec
vitest run --project @paperclipai/ui
ui/src/components/composer-recovery.test.tsx`.
- The new real PostgreSQL task-deletion race fails with SQLSTATE `40P01`
on parent commit `f3253a00c4`. The company-deletion race also fails with
`40P01` on `e8cf0e02dd`. All six receipt tests pass after the final
lock-order fixes. They cover company deletion, task deletion, comment
removal, tombstoning, concurrent cross-task references and interrupted
reference repair. Run `pnpm exec vitest run --project
@paperclipai/server
server/src/__tests__/issue-comment-receipt-postgres.test.ts`.
- The full UI run passed 9,656 of 9,659 tests across 816 files. Three
cases failed under that run: two large-tree timeouts and one
plugin-panel assertion. All 67 tests in those two files passed in an
isolated rerun. These failures remain recorded; this does not claim a
clean full UI run.
- `pnpm -r typecheck`, `pnpm build`, token gates and map checks pass on
the final change. The local full repository test command was started,
then stopped when the delivery moved to this existing PR. Fresh PR CI
must provide the full-suite gate.
- A local Storybook walkthrough used the real rich editor. Cancel kept
the restored text, Send cleared it after the simulated save, and a new
draft enabled Send again. Storybook simulates submission; it is not
staging acceptance.
- Earlier verification on `f3253a00c4` recorded five browser journeys
for title saves, cached-task offline recovery, startup recovery,
accepted comment replay and session lookup failure. Those results remain
prior-head evidence. No new staging deployment is claimed.

- On `e8cf0e02dd`, all CI checks passed after one browser-shard rerun.
Its first failure copied page text instead of YAML in an unrelated
agent-configuration test. On final commit `35131d4380`, Greptile is 5/5
with no unresolved review threads. The first CI attempt has two failures
outside this diff: runner close-attachment suspension and
scheduled-retry teardown. The scheduled-retry file passes all 14 tests
in isolation; the isolated runner test still fails locally. The single
standard CI rerun passed both jobs, and the aggregate verification gate
passed. All CI checks are green on `35131d4380`; Apex is 5/5 on that
same commit with no unresolved findings.

## Risks

- Automatic replay requires server duplicate prevention or result
verification. Uncertain combined mutations require receipt observation
or cancel and a fresh intentional send.
- Old unowned form drafts remain stored but are not assigned to an
account. Unowned channel records can be retired after Activity
inspection; this never cancels an accepted remote update.
- Browser storage and hashing can be unavailable. Storage failure is
reported honestly. Without a digest, replay can duplicate an upload
rather than silently drop a selected file.
- Detached autosaves remain bounded and check account ownership on each
attempt. Conflicts or exhaustion retain the draft for explicit recovery.
- No schema, credential or agent permission change is included. This PR
does not claim staging deployment or original-task acceptance.

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) produced the original
implementation with tool use. OpenAI Codex, GPT-6 family, assisted with
restoration, integration, verification and review fixes. This Codex
session does not expose its exact serving model ID or context window
size.

## Checklist

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

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Amy (Opus) <claude@users.noreply.github.com>
Co-authored-by: Dotta <bippadotta@protonmail.com>
2026-10-28 10:52:06 -07:00
Nicky LeachandPaperclip a2fbce9305 Fix plugin session and directory reuse on follow-up turns (#18045)
## Thinking Path

> - Paperclip preserves task state when agents receive follow-up work.
> - Plugin computers keep their process state outside the controller.
> - A local receipt proves that a previous plugin run suspended.
> - A cold resume left that receipt in place after the session became
live.
> - The next warm follow-up rejected the stale receipt as an identity
mismatch.
> - A separate follow-up path also treated a fresh task directory as a
Git worktree.
> - This PR consumes the obsolete receipt after admission and preserves
the bound directory on follow-up.

## Linked Issues or Issue Description

Related: #17820. This change retains the controller restoration added by
#18018.

**What happened?**

A plugin session resumed from a suspended checkpoint and completed a
turn. Its next warm follow-up failed with
`runner_state_identity_mismatch:
prior_owner_terminal_state_indeterminate`. The journal had the completed
run's identity. The local suspension receipt still had the preceding
run's identity. Two separate task histories showed this sequence.

After a fresh retry completed in a repository-free plugin directory, an
ordinary follow-up could instead fail with `The selected plugin
environment does not support Core Git worktree preparation.` The saved
task settings contained only `mode: isolated_workspace`, which
introduced the default Git strategy on the next admission.

**Expected behavior**

Keep the same admitted provider session during warm follow-ups. Reuse
the saved plugin task directory without Core Git preparation. Retain
ownership checks and explicit strategy settings.

**Steps to reproduce**

1. Complete a warm plugin task and let its session suspend.
2. Resume the checkpoint and complete another turn.
3. Send a follow-up while that session remains warm.
4. Separately, complete a fresh retry in a repository-free plugin
directory and send an ordinary follow-up.

**Paperclip version or commit**

Both regressions reproduce against base `820c45846` with the added
tests.

**Deployment mode**

Hosted plugin execution. Local reproduction uses the real filesystem and
a disposable PostgreSQL 18 database, with synthetic provider execution.

## What Changed

- Remove the local plugin suspension receipt after provider recovery and
durable run admission publish a live session. Admission still checks the
receipt first. Normal suspension writes a new receipt.
- Recognize a saved fresh plugin directory through its company, task,
workspace, owner, attempt and path. Use the existing directory-selection
path. Explicit strategy settings still apply.
- Add cold-to-warm, database-backed workspace-selection and ownership
regressions. Update execution semantics and session verification
recipes.

## Verification

- Red: the cold-to-warm regression failed on unchanged executor code
with `prior_owner_terminal_state_indeterminate` on the follow-up.
- Red: the PostgreSQL regression selected a Git strategy on unchanged
environment-selection code. The explicit-strategy denial case already
passed.
- Green: all 95 tests in `workspace-preparation.test.ts` and
`provider-fresh-workspace.test.ts` pass against a disposable local
PostgreSQL 18 database, selected with the existing
`PAPERCLIP_WORKSPACE_PREPARATION_TEST_DATABASE_URL` test seam.
- Green: 92 focused executor cases pass, including plugin checkpoint
recovery, warm rotation and denial cases. The full
`plugin-runner-task.test.ts` suite also passed (38 tests).
- Green: direct server check, `node node_modules/typescript/bin/tsc -p
server/tsconfig.json --noEmit`.
- Green: `node scripts/check-maps.mjs`, `git diff --check`, and a local
diff scan for secrets, personal data and live identifiers.
- Full local native suites: 988 of 1,004 cases passed. Sixteen
integration cases could not start their bundled PostgreSQL cluster. The
failure persisted outside the sandbox. These cases are not claimed as
passing. An earlier sandboxed attempt also denied process and loopback
operations; those denials disappeared when run outside the sandbox.
- The first broad local commands could not locate Cargo on `PATH`. Rust
is installed under `~/.rustup`; its Cargo executable was verified. Per
the requested scope, subsequent local verification stays targeted to
changed TypeScript paths; no Rust source changed. CI Typecheck + Release
Registry and Rust verification passed on the initial commit. The
complete repository test suite was not run locally.
- Review regression: an explicit agent-level Git strategy reproduced the
incorrect directory fallback before correction. After including the raw
agent strategy in the existing check, all three targeted cases
(implicit, task-level explicit, agent-level explicit) pass. The server
TypeScript check passes after this correction.
- CI on `a81668c4b`: the first workspace-a 2/2 attempt failed in
unchanged UI `AgentActionButtons.test.tsx` (`calls clearError and
refreshes agent-related queries`, zero mock calls). [Original failed
job](https://github.com/paperclipai/paperclip/actions/runs/40717870938/job/122921463517).
That shard passed on `294c5dfc3`. The failure is retained here. The UI
shard passed on final commit `687000287`; no unrelated UI edits or local
UI suite runs were added.
- CI also exposed three existing local-directory recovery failures on
`a81668c4b`: the review correction applied the raw agent strategy guard
to local directories. [Original failed server
job](https://github.com/paperclipai/paperclip/actions/runs/40717870938/job/122921463229).
Narrowed that guard to adapter-managed directories, preserving local
recovery behavior. All 20 targeted cases (three plugin selection cases
and 17 local recovery scenarios) pass afterward, and server TypeScript
verification passes.
- Final commit `687000287d3339b7e15e35d95515b3c75c273d7a`: [hosted CI is
green](https://github.com/paperclipai/paperclip/actions/runs/40720169342),
including the corrected server shard, all other server/workspace shards,
Runner checks, typechecking and build. All 55 non-skipped PR checks
pass. Greptile scores this exact commit 5/5, with no unresolved review
threads. GitHub reports no merge conflicts.
- Pre-merge hosted acceptance was requested. The maintained deployment
CLI stopped during artifact discovery: no published private Cloud
composition exists for `687000287`. The current private build requires
canonical Core master readiness and standard-image provenance. The
Core-only branch preview omits the private computer plugin needed for
the journey. No campaign or tenant update was started; private-preview
deployment support is a separate prerequisite. No live deployment or
provider acceptance run is claimed.

## Risks

The receipt is removed only after the existing runtime publishes an
admitted session. Earlier admission failures keep their proof. A later
normal suspension creates a new receipt. The change preserves existing
identity, lifecycle and controller checks.

Directory selection remains limited to the exact bound, active,
repository-free plugin recovery directory. Foreign owners, changed
paths, wrong attempts and explicit Git strategies do not gain this
fallback. No schema, API, credential, permission or fleet-default change
is required.

Existing failed runs and recovery holds remain history. This PR does not
edit quarantined state or replay an interrupted task. Rollback restores
the previous code and can reintroduce the two admission failures.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use and code execution.
A more specific model ID and context-window size are not exposed in this
session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 10:26:12 -07:00
DottaandPaperclip b14e1ecaf8 feat: add a complete agent YAML configuration editor (#18036)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/175/changes/paperclip/175
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators configure each agent through several settings tabs.
> - Operators also need one complete, editable configuration document.
> - The document must retain each resource service's access and
validation rules.
> - This pull request defines the `paperclip/v1` Agent YAML format and
adds an Advanced editor.
> - The editor previews changes, rejects stale core writes, and explains
partial saves.
> - Operators can edit agent settings in one place and verify the saved
state after reload.

## Linked Issues or Issue Description

Refs #2219. Related settings work: #10974.

**Problem or motivation**

Agent configuration spans profile, runtime, instructions, skills, tools,
channels, permissions, secrets, keys, and revision history. Operators
cannot inspect and edit those settings as one versioned YAML document.

**Proposed solution**

Add an Advanced agent tab with a YAML editor. Define a shared document
schema. Read and write resources through their existing APIs. Separate
editable settings, explicit commands, and read-only observed state.

**Alternatives considered**

A raw agent-row editor would omit related resources. A generic database
update would bypass resource ownership. The editor therefore uses the
existing resource contracts and records partial results when a later
request fails.

**Roadmap alignment**

This extends the shipped agent configuration capability. It relates to
easy AGENTS.md configuration, multi-harness teams, governed tool access,
and secrets management. Stored credentials remain redacted. This format
is an editable settings view; it does not add company portability or
provider consent.

## What Changed

- Add the `paperclip/v1` Agent document schema and format documentation.
- Add the Advanced route, sidebar entry, YAML editor, validation, change
summary, save progress, and reload recovery.
- Cover core settings, instruction files, skill pins, tool
installs/profiles/policies, channels, permissions, secret operations,
API keys, and revision restore.
- Add private-keyed configuration revisions checked under the agent
write lock. Read the current key through its owner so file-based
rotation does not require restarting the server. Preserve unchanged
secret markers at their original paths.
- Retain drafts and returned credentials after partial saves. Require
reload before retrying commands. Prevent duplicate submissions. Keep new
key tokens visible through rename and disable saves with an empty change
plan.
- Send only changed channel settings. Require explicit intent for shared
profile edits. Load destination instruction files when changing their
location.
- Update Storybook fixtures, verification maps, and regression tests.
Add browser acceptance through real APIs and PostgreSQL.

## Verification

- `pnpm -r typecheck` passes.
- `pnpm build` passes.
- The focused UI suite passes all 50 tests. The API/revision helper
suites pass all 93 tests.
- All 65 lifecycle tests pass with a dedicated PostgreSQL database. They
exercise real row locks, redaction, revision history, audit, and company
access.
- All six browser acceptance cases pass. They check saved settings and
clears, secret redaction, key creation/revocation, stale drafts,
lost-response recovery, instruction relocation, revision restore, and
key-token retention through rename. The tests use real resource APIs and
storage. The MCP target uses the existing local provider fixture. No
model run or provider login is claimed.
- Signing-key regressions cover both environment changes and real
in-place key-file rotation. The protected database save/fencing cases
pass after removing the cache. A local measurement of 1,000 file-backed
revision calculations took 48 ms.
- `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and Storybook
catalog checks pass.
- The full [PR CI
run](https://github.com/paperclipai/paperclip/actions/runs/40725425470)
passes on `34ed97bbf9`: all 48 jobs, including all eight browser shards.
Greptile is 5/5 on this commit, with no unresolved review threads. This
final commit refreshes CI after a runner-routing fallback; its source
tree matches `fb4cf488cf`.
- Paperclip Review and Superagent Security Scan ended neutral because
their external agents did not complete a valid assessment/receipt.
Superagent passed on `fb4cf488cf`, which has the identical source tree.
One request to retry the final scan returned HTTP 404. Neither check
reports a code finding.
- The local full-suite attempt was blocked by host System V semaphore
exhaustion. Acceptance and lifecycle verification used an isolated
PostgreSQL 18 container. Earlier CI runners were interrupted. A local
combined run hit hook/test timeouts; the full 88-test route file passed
after the builds finished. The final full CI run passes. Earlier failure
logs and browser traces remain retained outside the repository.

To run the browser regression:

```sh
pnpm exec playwright test --config tests/e2e/playwright.config.ts tests/e2e/agent-configuration.spec.ts
```

## Risks

- Multi-resource saves are sequential. Earlier operations can remain
saved if a later operation fails. The editor reports the completed steps
and requires reload.
- Core settings and managed instruction files have atomic revision/hash
checks. Other unversioned resource writes and external supporting files
retain a race window after preflight.
- Shared profile definitions affect other bindings. The editor requires
`updateSharedDefinition: true` for those edits.
- The editor follows native service normalization and experimental
settings. Canonical reload can add generated access profiles or mask
environment values.
- New editor dependencies require the repository's normal automated
lockfile update. This pull request does not edit the lockfile or add a
database migration.

## Model Used

OpenAI Codex, GPT-6 family. The exact current model version was not
exposed. The work used reasoning, repository tools, code execution, and
browser automation. Earlier work in this chat used the configured Codex
model before a model switch; its exact model ID and context window were
not exposed. The current context window size is also 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-28 11:49:24 -05:00
DottaandPaperclip 567c043b17 feat(server): expose bounded hot-upgrade readiness (#18037)
## Thinking Path

> - Paperclip coordinates agent work and keeps its authority in the
server.
> - Remote native runners can preserve execution through a server
replacement.
> - Deployment operators need evidence that current runs support that
recovery.
> - Process-local drain counters do not establish this fact.
> - This PR adds an optional, operator-only readiness observation from
existing records.
> - A deployment consumer can use that report while the existing runtime
retains recovery authority.

## Linked Issues or Issue Description

Refs #17439.

**What happened?**

A deployment cannot distinguish recoverable remote native executions
from runs that require a task drain. The existing status endpoint
reports only process-local counts.

**Expected behavior**

An instance operator can request a bounded readiness report without
stopping admission or exposing checkpoint material. Missing ownership or
persistence evidence must prevent readiness. Ordinary status reads must
keep their current cost.

**Steps to reproduce**

Run a remote native task. Read the task-drain status. It reports active
work but supplies no recovery eligibility. Deployment code therefore has
no affirmative signal to select an active-run handover.

## What Changed

- Add `GET /api/instance/task-drain?upgradeReadiness=1` for instance
administrators and existing Cloud control callers.
- Return aggregate eligibility from current run identities, controller
leases and bound opaque checkpoint headers. Unknown work, pending
admission and incomplete reads prevent a positive report.
- Bound the explicit read to 1,001 rows, encrypted headers of at most
256 KiB each and 8 MiB total, and a two-second SQL statement timeout in
a read-only transaction. Keep ordinary status reads in memory.
- Add PostgreSQL, count-transition and route authorization tests. Update
the API contract, operator docs and access maps.

## Verification

- All seven readiness cases pass against an isolated PostgreSQL 18
fixture. They cover missing checkpoints, legacy adapters, missing
process/session identities, foreign owners, expired leases, missing
lease tokens, failure state and in-flight work. The positive SQL fixture
uses the real Runner checkpoint writer and encryption. Regular sandbox
workspace identity and plugin environment-lease identity are tested with
independent IDs. Stopped/released/undispatched plugin tasks and every
mismatched identity field are rejected. Local/legacy/malformed/oversized
or mismatched headers are rejected. A held PostgreSQL table lock proves
the two-second cancellation budget, rollback/connection release and
unrelated query responsiveness.
- All 123 focused readiness, instance-settings and Cloud control
assertion tests pass, including operator-only access and no readiness
read on ordinary status requests. Runner’s 168 checkpoint tests pass.
Runner and server typechecks pass after review fixes.
- Workspace typecheck, full build, module-boundary and map checks passed
locally before the master rebase. Current-head GitHub CI is now green,
including typecheck, build, all grouped/serialized server and Runner
tests, browser shards, policy and review-dispatch checks. Greptile
completed cleanly at 5/5 for `f15fb0c7e9dfb975090cd5d791a1c8e6701275f8`;
all actionable threads are resolved.
- The broad local test run was stopped after the macOS embedded
PostgreSQL fixture failed to bootstrap. The SQL test was then run on the
isolated PostgreSQL fixture. No assertion or timeout was weakened. One
unrelated existing route test exceeded its 15-second limit under
concurrent local builds; it passed on one isolated retry and the
subsequent whole route suite passed.
- Hosted active-run upgrade acceptance has not run. This PR supplies an
observation; it does not change rollout policy or establish live
continuity by itself.

## Risks

This is an instance-wide observation, so company members and agent keys
must not receive it. A readiness snapshot can age as work changes;
shutdown and startup retain their existing execution authority and
fencing. The report does not validate a replacement artifact or
authorize a schema migration. It decrypts only bounded headers through
the checkpoint owner and delegates format/identity inspection to Runner;
full journal restoration and physical sandbox authentication remain with
recovery. No migration, recurring query, new checkpoint write or wire
protocol change is included. The additive Runner header inspection
contract reuses its existing parser.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, source inspection, tool
use and code execution. The host does not expose the exact serving model
ID or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 11:28:15 -05:00
DottaandPaperclip 820c458465 fix(runner): restore per-turn controller checkpoints before resume (#18018)
## Thinking Path

> - Paperclip coordinates agents and preserves their work between turns.
> - Remote native sessions save controller checkpoints in the database.
> - External persistence leaves a small identity marker on local disk.
> - A later `per_turn` continuation must restore that checkpoint before
it reads the controller identity.
> - The restore path handled warm sessions only, so valid per-turn
continuations failed before provider execution.
> - This PR restores the referenced checkpoint and retains the existing
ownership and lifecycle checks.

## Linked Issues or Issue Description

Related: #17439 added external controller persistence and the warm
restore path. #18011 repairs warm preparation and fresh bootstrap
checks; it does not cover ordinary per-turn continuation.

**What happened?**

A remote OpenCode run completed with `per_turn` lifecycle and saved its
controller checkpoint in the database. Its next turn reused the
normalized session. Admission read the remaining external-persistence
marker as a full controller file and failed with
`runner_state_identity_mismatch: durable_identity_unreadable`. The prior
run's complete checkpoint and harness backup still existed. The failure
occurred before provider work started.

**Expected behavior**

Restore the exact prior controller checkpoint before identity
inspection. Then apply the existing company, task, session, prior-owner
and suspended-state checks before a provider can start.

**Steps to reproduce**

1. Complete a remote native OpenCode task with `per_turn` lifecycle and
external controller persistence.
2. Send a follow-up that resumes the same saved session without a
session reset.
3. Observe admission reject the valid external controller marker before
provider execution.

**Paperclip version or commit**

Observed at `40c1ab36cdac70c85dc8fe5e912431834fdb691b`. The same
warm-only restore remains on current master.

**Deployment mode**

Hosted Linux with Daytona and native OpenCode. The original model was
`openrouter/deepseek/deepseek-v4.1-flash-1017`.

## What Changed

- Restore external controller state for ordinary remote per-turn
continuations through the existing checkpoint loader.
- Bind that read to the current company and task, the marker's run, and
the expected normalized session.
- Keep local, warm and restart-recovery paths, prior-owner checks and
harness backup checks intact.
- Refresh a prior-run projection from the latest checkpoint after a
rejected active-owner attempt. Keep current-run full state and the
existing legacy file-backed fallback intact.
- Add restoration and denial regressions, execution documentation and
session verification recipes.

## Verification

- Red: the real controller generated an external marker; a valid
per-turn OpenCode continuation failed with the exact
`durable_identity_unreadable` error before tool-authority construction.
The repair passed the same case and its ownership guards.
- Review regression red/green: a real controller advanced its checkpoint
after an active-owner rejection. Before the follow-up fix, a later valid
continuation retained a null attach seed. After the fix, it restored the
newer attach template and prepare command. Legacy full-file roots with
no database checkpoint retain their existing behavior.
- At current head `1f6589233e6121d082a0c0c4444ea895b6e8cd7c`, 86 focused
executor cases and all 14 execution-driver cases pass. Coverage includes
checkpoint restoration, direct/backup suspension, Codex, legacy files,
warm admission and canonical bootstrap, missing or malformed evidence,
wrong bindings, active/foreign owners and unsuspended runners. Tests
stop before provider launch.
- The real PostgreSQL encrypted-checkpoint integration passes, including
normalized-session refusal before write and stale-writer fencing.
Independent source review found no actionable safety defect.
- `node scripts/check-maps.mjs`, `git diff --check`, full `pnpm -r
typecheck` and `pnpm build` pass on current head.
- The local full suite did not complete: native PostgreSQL startup
failed under the host sandbox, an initial Docker rerun lacked
migrations, and the migrated retry crossed the review-fix revision
change. Logs are retained; that mixed-revision run was stopped and its
owned database removed. Full test evidence comes from current-head CI.
- Current-head CI passes: 53 successful checks, two intended Storybook
skips, none pending or failing. Greptile is 5/5 on that exact head with
no open review threads. The only manual merge conflict with #18011 was
in the verification recipes; both recipes and the unchanged per-turn
restore helper are preserved.

**Live continuation acceptance remains unverified, so this PR stays
draft.** Two disposable OpenCode/Daytona attempts never reached turns
two and three:

- At `72b49208b1`, the first turn executed tools and produced the exact
33-byte workspace note, but exceeded its four-minute settlement
deadline. The first completion lacked a registered attachment; the
second decorated a typed attachment reference with filename/size/hash
text. The strict UUID parser rejected that reference before checking a
valid criterion reference. The scoped attachment, asset and publication
receipt exist. Replaying the actual guard rejects the original input
before a database lookup; correcting only that reference passes against
the recovered row and receipt. This did not show a
publication-persistence or controller defect. The task remained
unsettled.
- At `1f6589233e`, a separately approved replacement used a temporary
prompt-only fixture change requiring exact `deliverable:<attachmentId>`
references, with metadata in `verification.detail`. Production code,
grading and deadlines were unchanged; the fixture patch was removed
afterward. This attempt had no recorded provider authentication,
harness-ready, model, tool or result event. Ingress acquisition took
84.072 seconds; transport connection took 205.835 seconds within the
239.832-second failed native execution. A local settlement GET also
timed out after 30 seconds. The underlying startup stall is unresolved;
these observations do not establish a remote provider outage. Final
recovery was blocked with `ambiguous_remote_recovery_evidence`; no
successful settlement or continuation is claimed.

Both attempts used a Darwin arm64 source host with Node 26.4.0, isolated
PostgreSQL 18, a Linux x64 runner and OpenCode 1.18.34. The
representative qualified model was
`openrouter/deepseek/deepseek-v4-flash-0731`; the original incident used
`openrouter/deepseek/deepseek-v4.1-flash-1017`. The controller defect
occurs before provider work. Runtime artifacts came from immutable build
`e7ea2e2961`, whose Runner package source is identical to the candidate.
The current-source manifest, artifact, distribution, asset and all 110
archive-hash checks passed. Each attempt had $10 company/agent model
budgets and zero automatic workflow/task retries. Accounting was
incomplete; zero recorded spend is not proof of zero cost.

Earlier setup failures are also retained: host PostgreSQL bootstrap
denial, cached-pack compatibility admission before provider work, and an
[official artifact
build](https://github.com/paperclipai/paperclip/actions/runs/40696838122)
that stopped during an unrelated Pi npm install at its 300-second bound.
No manifest or integrity guard was weakened. Owned local processes and
databases are stopped, and the temporary fixture patch is removed.
Standard fixture cleanup had left one replacement sandbox started; it
was stopped and deleted through the SDK. Every owned sandbox was then
verified absent with a final 404 readback. Resource cleanup does not
establish successful task finalization.

An earlier head retained one [voice-recovery timing
failure](https://github.com/paperclipai/paperclip/actions/runs/40695892339/job/122843005098):
a deadline test observed two failed-provider inspections instead of one.
A single isolated shard rerun passed all 1,579 tests without a source
change. Its timing explanation remains an inference. The current
reconciled head passed without a retry.

## Risks

Restoration writes a local projection before the existing admission
checks. The encrypted checkpoint loader validates company/task/run and
normalized session before writing. A later ordinary continuation
refreshes a prior-run projection so rejected admission cannot freeze an
active owner's older checkpoint. Active, foreign or unsuspended prior
owners still cannot start a successor. Missing or malformed evidence
remains blocked. The change adds no retry, credential, provider binary
or lifecycle-policy change; it preserves the existing legacy fallback.

This PR does not deploy the repair or recover the original hosted tasks.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, code execution and
collaborating agents. The session exposes GPT-6 as its model version; a
more specific model ID and context-window size are 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-28 09:49:32 -05:00
DottaandPaperclip 25f1070fbd fix(runner): preserve checkpoint proof across warm preparation (#18011)
## Thinking Path

> - Paperclip coordinates agent work and preserves its execution state.
> - Native Runner checkpoints preserve authority across controller
changes.
> - Warm sessions also need checkpoint writes while their successor
prepares.
> - External persistence replaces the local state file with a marker.
> - Two existing checks treated those valid states as lost ownership or
prior activity.
> - This PR uses the existing preparation lease and canonical controller
state to keep those checks accurate.
> - The result is safe warm-session retirement and fresh-session startup
on reused sandboxes.

## Linked Issues or Issue Description

Related: #17439 and #17320. The open #17401 changes the recovery welcome
window and does not cover these paths.

**What happened?**

A configuration change could fail before the next provider turn with
`runner did not durably suspend before checkpoint`. The task already
pointed to its preparing successor, but that successor did not yet have
a native coordinator. The old completed runner's maintenance checkpoint
was rejected.

A separate fresh session on a reused sandbox could fail with
`resumed_unavailable`. Checkpoint registration had replaced the full
local state file with an external-persistence marker. The bootstrap
check still required the old full-file format. Process supervision then
reported unconfirmed termination before launch.

**Expected behavior**

Retire the completed warm runner under the same process's live
preparation lease. Admit a fresh remote session only when the registered
controller proves exact identity, no prior activity and pending
bootstrap commands, and the remote session directory can be claimed
atomically.

**Steps to reproduce**

1. Complete a native warm turn with external checkpoint persistence.
2. Change configuration so instruction preparation must retire that
session, then submit a follow-up.
3. Separately, admit a fresh native session on a reused sandbox lease
after external checkpoint registration.

**Paperclip version or commit**

Reproduced in the checkpoint implementation introduced by #17439. Fixed
against current master.

**Deployment mode**

Source checkout tests and a hosted Docker/Daytona incident. No
deployment or original-task retry is part of this PR.

## What Changed

- Accept completed-run maintenance under the exact successor's live,
same-process preparation lease only before a native coordinator exists.
- Preserve original controller generation, accepted-result, no-new-work,
company and task checks.
- Pass the registered controller through the existing connection
callback and read its current canonical state for untouched-session
proof.
- Keep marker-only, identity, activity, backup and atomic
remote-directory guards.
- Add regressions and update execution semantics and session
verification recipes.

## Verification

- Warm retirement red: the real Postgres writer rejected the preparing
successor's `runner.suspend` checkpoint with
`native_runner_checkpoint_owner_lost`.
- Warm retirement green: 14 Postgres ownership cases pass, including
stale/foreign/expired owners, conflicting native authority and new
provider work.
- Bootstrap red: real controller registration and external persistence
caused the resumed and replacement positives to fail. Six external
negative cases passed.
- Bootstrap green: all 34 bootstrap cases, the bootstrap-state predicate
and 13 connection-driver cases pass (48 total).
- `node scripts/check-maps.mjs` and `git diff --check` pass.
- Full `pnpm -r typecheck` and `pnpm build` pass.
- Full local `pnpm test:run` remains partial/interrupted. The default
attempt could not initialize embedded Postgres on this Mac. A dedicated
Postgres 18 attempt ran for 17 minutes without a completed file result
before interruption; the generic helper separately confirmed unsupported
embedded Postgres (`initdb` failed after five attempts) and ignores the
external database URL. The generic probe skipped one test. Setup and
interrupted-run logs are retained; neither is claimed as a behavioral
red or a full local pass.
- Real source-hosted Codex/Daytona acceptance was attempted at
`6ce7fcacc4` with `gpt-6.1-sol`, `xhigh`. The actual task stopped before
provider work at `runner_ingress_auth_failed`, with zero authenticated
connections and zero source events. A separate environment-qualification
handshake reached challenge/response; that does not prove task
authentication. The three-turn warm reuse, configuration retirement,
useful output and reload workflow remains unverified, so this PR stays
draft.
- The live attempt used the cached Linux amd64 Runner binary
`7437a4e32a099180889be534fcfb2a086046514490c1448aba46c55848983ed8` from
the immutable Daytona image. The current staging binary could not be
copied because SSH timed out, and the configured current EXE image
returned registry 403. No compatible current local or CI-downloadable
artifact was available. Earlier setup failures and cleanup receipts are
retained; no provider success is claimed. Disposable test resources were
cleaned up.
- Exact-head Greptile completed at 5/5 with no open feedback:
https://github.com/paperclipai/paperclip/pull/18011#issuecomment-6469515952.
All current-head CI checks pass: 53 successful checks and two intended
Storybook skips.

## Risks

The preparation fallback affects maintenance checkpoints only after an
accepted result. An existing native coordinator prevents that fallback.
Stale controller generations, expired or foreign preparation leases,
wrong tasks and new provider work remain denied.

The bootstrap check retains the live controller object and reads current
state each time. It does not trust a marker or restore local state
beneath a live controller. Pending turns, prior events/connections,
backups and existing remote directories retain recovery gates. No
schema, provider binary, credential, permission or lifecycle-policy
change is required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, code execution and
collaborating agents. This session does not expose a more specific model
ID or context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 09:09:09 -05:00
Devin FoleyandPaperclip c9213d1be4 fix: send saved queued messages after Stop (#17959)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People can save follow-up messages while an agent runs.
> - Stop preserves those messages and stops the active execution.
> - The queue removed its delivery controls when that execution ended.
> - Native admission also refused an explicit resend of older queued
input.
> - This change adds Send for a stopped queue and records fresh board
intent.
> - The saved message can continue through normal cleanup and admission
checks.

## Linked Issues or Issue Description

**What happened?**

A person queued a message with a screenshot while an agent was starting.
Steering was not yet available. They stopped the run. The message
remained visible, but no control could send it. Native queue delivery
also rejected this transition.

**Expected behavior**

A stopped queue offers Send. The click preserves message IDs, content,
attachments and original authors. It starts at most one eligible
continuation. Stop remains effective until the person gives new
direction.

**Steps to reproduce**

1. Start a native task and queue a second message.
2. Stop the active run before it consumes that message.
3. Open the task after cleanup. Observe the saved message with no send
control.

Refs #16965 for the queue-control change and #15015 for stopped
conversation recovery. No open repair for this exact transition was
found.

## What Changed

- Show Send for a saved deferred queue with no active run.
- Accept the existing board queue action for a stopped native target.
Keep live native interruption restricted.
- Use the server-recorded click time to authorize older native messages.
Reject stale, malformed and wrong-actor intents.
- Reuse normal queue dispatch, revision checks, cleanup proofs and
execution admission, including a failed native predecessor after a
verified Send.
- Ignore a fully committed, successful recovered export when admitting a
fresh message, while retaining the wait for results still committing.
- Honor an applied `/new` conversation boundary while retaining native
execution holds until the existing stop and cleanup checks verify them.
Workspace holds also survive reset. Check the newest failed or cancelled
native execution even when older recovery actions exist.
- Keep native automatic delivery separate from the explicit Send action.
Update execution and access documentation.

## Verification

- Meaningful regressions failed before the fixes: stopped queues lacked
Send, native admission refused fresh intent, cleanup and dispatch
receipts were missing, deferred rows disappeared, live plan Interrupt
rejected its own receipt, and Agent Chat `/new` inherited an old
non-workspace execution hold.
- Six assembled-wakeup cases fail before the reset cleanup fix. All 11
reset/history cases pass after it: live processes, missing identity,
quarantined cleanup, remote leases and live controllers remain held;
verified cleanup proceeds and retires the hold. Two more cases fail
before the fallback fix and pass after it: Send verifies a stopped or
live native predecessor despite a later reset receipt and no recovery
record.
- **525 server tests pass** across seven queue admission, route,
dispatch, envelope, provenance, blocker and conversation files. **343
queue/thread UI tests** also pass. Server/UI TypeScript, token and map
guards pass. The final scoped server typecheck also builds native Runner
successfully.
- The latest regressions prove that completed recovered exports permit
fresh input, and clearing conversation history still requires old native
stop and cleanup verification; an unsafe workspace still blocks after
`/new`; failed native Send reaches actual continuation dispatch with the
original queued comment. A result still being committed remains
deferred. History plus a newer Stop cannot hide a missing
process/controller/lease receipt.
- The real Chromium Stop/Send journey passes on current head
`75fa5e7222c59f43ff7ac326e81093bc9da28330`: queue a follow-up, Stop,
reload, explicitly Send, then verify exactly one useful response and no
live run. Earlier browser journeys cover legacy Interrupt, interruption
during a write and Stop followed by a new direction. These use an
isolated app/database and controlled ACP fixture, not an external AI
account or a staging deployment.
- Negative cases retain actor, company, issue, assignee, queue and
cancellation-receipt bindings; cleanup/process/workspace/controller
holds; approvals; pause and budget gates. Typed responses keep their
original resolver and immutable result.
- Full local recursive typecheck stopped in unchanged Rust Runner
compilation with ENOSPC, so the chained full tests/build did not run.
All hosted CI gates pass on final commit
`75fa5e7222c59f43ff7ac326e81093bc9da28330`, including typecheck, tests,
build and E2E. Apex review on that commit is 5/5, with no unresolved
findings. Earlier unrelated CI failures involved PostgreSQL
fixture-cleanup deadlock and an unchanged decision-expiry deadline
assertion; the latter's 20 cases pass locally without source changes. No
assertions or limits were weakened. Local resource cleanup was limited
to this task's verified completed test processes and rebuildable npm
caches.

## Risks

- Send can authorize a new turn for a saved message after Stop. A Send
click must be newer than the stopped execution; a live plan Interrupt is
bound to the cancellation receipt produced by that same click. It does
not imply that cleanup finished or that an external action is safe to
replay.
- The existing endpoint and intent format are reused. No schema or
credential change is required. Live native steering and legacy
interruption keep their existing paths.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository inspection, tool
use and code execution. The session does not expose the exact serving
model ID or context window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 20:34:14 -07:00
DottaandPaperclip f52da40f08 fix: resume queued turns after maintenance (#17967)
Keep an accepted turn's starting input in task history, show its admission wait, and resume existing queued runs promptly when maintenance ends or expires.

Verified with behavioral red/green regressions, real PostgreSQL and process execution, browser/native Runner acceptance with a deterministic provider, workspace typecheck, production build, and current-head CI/review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-27 22:20:03 -05:00
DottaandPaperclip 09ad9adce2 feat(server): adopt running remote agents through durable controller checkpoints (#17439)
## Thinking Path

> - Paperclip must keep admitted remote work alive while its main server
is replaced.
> - Runner owns recovery mechanics and exposes opaque checkpoints
through #17097.
> - The server owns company scope, encryption, Stop, tool authority and
execution ownership.
> - A successor must prove current ownership before it adopts the
original execution.
> - Checkpoint bursts must also leave capacity for normal requests and
lease renewal.
> - This PR persists and adopts that authority through the existing
runtime boundaries.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Remote agents retain the original execution during a bounded main-server
outage.

**Current behavior**

A server restart can lose the controller's local state and connection.
An unsafe replacement could repeat a turn or an uncertain mutation.
Checkpoint writes in the request pool can also delay ordinary requests
during an aligned burst.

**Proposed behavior**

Restore encrypted control records from Postgres and adopt the original
runner under a fenced lease. Recover known tool receipts through current
tool authority. Give control checkpoints a shared pool capped at two
connections per database owner.

Depends on #17097. Successors are #17455 and #17456. Qualification and
presentation remain separate review slices.

## What Changed

- Add company/run-bound encrypted checkpoint records and migration 0394.
Keep the SQL idempotent after renumbering against current master.
- Recover startup and expired ownership through native runtime and
heartbeat. Preserve the sandbox lease, admitted runner artifact, harness
configuration, native session and active turn.
- Keep Stop, finalization, preparation ownership and stale-writer
fencing transactional. Preserve graceful detach and natural crash
takeover.
- Recover committed tool receipts through the existing authority.
Reauthorize reads and hold uncertain mutations.
- Bound startup retention with the existing coordinator and preserve
zero idle scans.
- Share at most two checkpoint connections per database client. Keep
application and liveness capacity separate. Close the checkpoint pool
during shutdown; late writes cannot reopen it.
- Count SQL across both application and checkpoint clients. Prove
request/liveness progress, command recovery and failure after pool
shutdown with real Postgres.

## Verification

Project creation recovery now uses the existing project activity receipt
owner. It retains authenticated input normalization, fingerprint checks
and current run authority after the receipt lock. An absent receipt
returns no result before mutation. The new lost-HTTP-response and
no-effect regression uses real API routes and Postgres. The seven
transport cases pass locally. This Mac skips all 20 database cases. On
current source `5de803c2cd`, Linux [job
122593415890](https://github.com/paperclipai/paperclip/actions/runs/40620576702/job/122593415890)
executes all 20 project-tool cases successfully (9.480 seconds),
including the committed-project lost-response regression. Its shard
passes 1,627 cases with three unrelated skips. Server typecheck passes.
The transport regression initially has two failures; a subsequent
incorrect expectation about schema defaults was corrected before the
final pass. Ordinary execution adds no checkpoint writes or recurring
work.

Current candidate `5de803c2cd` includes the project-creation receipt
recovery fix and master `2cd747d1b6`. Migration 0394 retains the prior
idempotent checkpoint DDL. Every master SQL file and journal entry is
preserved. Snapshots 0390–0394, migration checks and server typecheck
pass.

The ordinary warm-turn regression fails on its second turn before
`a219ab51ad`. After correction, three completed warm turns select the
correct prior checkpoint and preserve the original session. All 288
provider-wiring cases pass. The control plane, external persistence
callback, identity rotation and filesystem are real; the backend and
database-load seam are scripted. The 13 warm admission/configuration
variants also pass after final master integration. This does not qualify
an underlying harness.

At current source `5de803c2cd`, Linux [job
122593415907](https://github.com/paperclipai/paperclip/actions/runs/40620576702/job/122593415907)
passes all 940 native-session-executor cases (61.431 seconds), including
the warm external-checkpoint behavior; the shard passes 2,358 cases with
one skip. Current [Runner job
122593415475](https://github.com/paperclipai/paperclip/actions/runs/40620576702/job/122593415475)
passes the native recovery lane: 115 passes and five container-only
skips, including the encrypted restore guard, fresh preparation (63.189
seconds), blocked claim lock (1.226 seconds) and recovery beyond 101
blocked owners (3.897 seconds). The first lane passes 2,215 cases with
one skip. The SQL cost test reports zero idle and streaming SQL for both
output volumes; this is component evidence, not a production capacity
claim. At prior candidate `1ff7bb44f4`, Linux job 122549307215 passes
all 938 native-executor cases, including the three-turn
external-checkpoint regression. Job 122549306469 passes the native
recovery lane with 115 passes and five container-only skips, including
the encrypted-restore session guard, fresh preparation (63.664 seconds),
claim-lock contention (3.961 seconds), and 101-owner recovery (3.824
seconds). This Mac skips the real-Postgres suite. The earlier full local
executor attempt has 921 passes and 16 failures during embedded-Postgres
initialization before assertions. The original fixture collisions and
their corrections remain recorded.

At earlier candidate `8fbe62b41d`, server shard job 122535673841 has
3,876 passes, one failure and one skip in an unchanged expiry-worker
retry/drain timing test. The same server/database tree on qualification
source `b64cac6951` passes all 20 expiry cases and all 3,877 shard
cases. The single diagnostic retry, job 122541891915, passes all 20
expiry cases and all 3,877 shard cases (one skip). No assertion was
weakened. The original failure remains recorded and its exact timing
race is not proven. All Actions checks and legacy status passed on
`8fbe62b41d`, with completed Greptile 5/5 and no open feedback. The next
candidate `1ff7bb44f4` also passed all Actions checks and Greptile 5/5.
Its Paperclip Review remained queued before the new master conflict
required integration. The new candidate needs fresh exact-head CI and
reviews; old checks do not qualify it. Migration generation is
checkpoint-only, all master SQL and journal entries remain unchanged,
and migration checks, server typecheck and all 13 warm-owner variants
pass after integration. The first migration check was blocked by TSX
sandbox IPC; its permitted repeat passes. The first warm-test command
used an incorrect path and ran no tests; the corrected command supplies
the 13-case receipt.

All 16 database pool-lifetime/options/teardown cases pass after granting
loopback permission; the first batch had two EPERM failures and 14
passes. Earlier semantic-tool/HTTP recovery, adoption, encryption-batch,
zero-streaming-write and idle-SQL receipts remain source-attributed in
the [qualification
record](https://github.com/paperclipai/paperclip/blob/2ff66f57da0da35bac1c19a2366ea4b84d87a986/doc/plans/2026-10-22-hot-upgrade-qualification.md).
That record retains earlier assertion, setup and cleanup failures and
their corrections. No failed gate is waived.

The historical 300-session component campaign passes four after phases:
steady read p99 is 107–108 ms at 500 reads/s and 100 writes/s;
aligned-burst read p99 is 103–105 ms after the bounded pool, versus
584–689 ms before. This comparison isolates the persistence corrections.
It does not measure the final stack's hosted active-agent capacity. The
hosted zero-agent API pair leaves SQL and CPU essentially unchanged, but
both arms fail absolute latency gates and candidate peak cgroup memory
fails its gate. The active-agent/viewer matrix, different-artifact
upgrade and rollback remain open.

Run `PAPERCLIP_TEST_DATABASE_URL=<owned-disposable-postgres> pnpm
--filter @paperclipai/server exec vitest run
src/services/native-runtime/native-runner-restart-recovery.integration.test.ts`.

Previous head `f2db8a6568` had one failed workspace setup gate: [job
122555672441](https://github.com/paperclipai/paperclip/actions/runs/40608984238/job/122555672441)
passes all 4,169 UI tests and 285 CLI cases (one skip), but the company
import/export suite reaches its 30-second health deadline during doctor
startup. Its output does not reach the server-start step. The CLI,
server, database, shared, adapter and plugin trees are identical on
qualification source `a866619d7b`, whose [job
122555886663](https://github.com/paperclipai/paperclip/actions/runs/40609057937/job/122555886663)
passes that fixture and all 286 CLI cases. The one diagnostic retry,
[job
122561057225](https://github.com/paperclipai/paperclip/actions/runs/40608984238/job/122561057225),
passes the formerly failing fixture and all 286 CLI cases. All Actions
checks and legacy status on `f2db8a6568` pass. Its exact-head Greptile
completed at 5/5 with no open feedback. The current integrated head
requires fresh checks and a completed Paperclip Review before merge. The
original failure remains recorded; its exact timing cause is unproven. A
repeated failure requires investigation and repair rather than another
retry.

All current-head CI, legacy status, exact-head completed Greptile 5/5,
resolved feedback and ordinary GitHub merge eligibility remain required
before merge.

The latest integration preserves master’s published Copilot v70 profiles
and every published migration. Checkpoint migration
`0394_conscious_whizzer.sql` was generated with `pnpm db:generate` and
retains the prior idempotent DDL. The Runner vendor rebuild and replay
parity checks pass. Server typecheck and all 13 warm-owner variants pass
after that rebuild. The imported report-lock patch is byte-identical to
master; its intentional patch-context whitespace is retained, and the
feature delta passes whitespace checks. No hosted experiment was run.

## Risks

The pool adds up to two active connections per instance, shared across
agents. Checkpoint delivery can wait behind that bound; it still
requires its commit. Steady component-test Postgres CPU rises by about
1.7 percentage points of a two-CPU allocation. These corrections do not
remove the stack's control and renewal writes. The migration and key
must survive replacement. Fresh-database tests and local load do not
establish different-artifact hosted upgrade or rollback continuity.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools and code
execution. The runtime does not expose a more specific model ID or
context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 21:39:23 -05:00
DottaandPaperclip d40f9ac377 fix: enforce first-task completion decisions and retain E2E evidence (#17940)
## Thinking Path

> - Paperclip lets people delegate work to agents and approve proposed
work.
> - The onboarding first task asks for scope, proposes a task, and waits
for a human decision.
> - An answer to its opening question supplies scope. It does not
approve a proposal.
> - Task creation already checks the saved proposal decision.
> - Native completion used the general completion policy and could mark
the onboarding parent Done without that decision.
> - This PR checks the trusted decision before completion feedback and
again when the native status is committed.
> - The first task stays in review until a saved human decision permits
closure. Ordinary completion and acknowledged refusal keep their current
behavior.
> - The Product E2E guard also retains closed scalar evidence so future
failures show which boundary condition was observed.

## Linked Issues or Issue Description

Refs: #17914. Profile compatibility follow-up to #17922.

**What happened?**

A native onboarding run can submit a valid low-risk Done result after
only the opening answer. The native finalizer then marks the first task
Done even though no human has accepted or rejected a proposal.

**Expected behavior**

The opening answer must not permit completion. A trusted saved proposal
decision must permit it. A saved rejection permits acknowledgment and
closure, but does not authorize new work. A later pending proposal must
keep the task in review.

**Steps to reproduce**

Create a server-owned onboarding first task with an answered opening
question, no proposal decision, and a valid low-risk completion
contract. Pass a Done result through native completion feedback, the
control-plane port, and the finalizer. Before this fix, the persisted
status is Done. The regression expects In review. Ordinary completion
and acknowledged rejection pass as controls.

## What Changed

- Share the trusted latest-proposal and human-response checks with
completion admission. Keep task creation acceptance-only.
- Refuse premature native completion feedback. Keep an already saved
premature result in review during finalization.
- Check the decision again under the existing task and run locks before
committing Done.
- Cover accepted decisions, saved refusals, forged context, pending or
changed proposals, and a real database race.
- Retain a closed scalar receipt when the existing E2E pre-acceptance
guard fails. Validate and display it without task content, IDs,
filenames, or raw rows. Preserve the original failure, blocked
dependents, and historical reports.
- Include the evidence module in the journey definition hash. Bind the
receipt to its exact failure code and check its closed keys against the
full type.
- Repair base-branch profile drift found by the full harness check:
include the active Copilot v66 fixture in image hashing and update stale
Pi version/hash expectations from #17922. Keep all older image inputs
and strict hash checks.
- Update the onboarding feature and agent access maps and E2E evidence
documentation.

## Verification

- Semantic regression before implementation: one failure and two passing
controls on PostgreSQL 18. The failed assertion observed Done instead of
In review.
- The local database uses an owned disposable container with an
immutable image digest. Actual migrations, feedback, control-plane port,
finalizer, and status commit run against PostgreSQL. A temporary test
adapter replaces only the embedded database transport because this host
has exhausted its PostgreSQL semaphores.
- Native control-plane suite: 55 tests passed, including 17 new
controls. Existing task-creation admission: 25 passed. Existing
completion feedback: 19 passed.
- Credential-free E2E support: 206 Vitest suites passed, 4,407 tests
passed, and two skipped. All 137 Node support checks passed. Harness
typecheck passed.
- The failure-receipt regression had 11 failed assertions before capture
was implemented. Two failure-code binding assertions fail without their
gate. Eight placement/binding cases first validate the receipt-free
control, then reject the misplaced receipt.
- The untouched base reproduced the three profile compatibility
failures. The narrow repair passed all 83 affected tests before the full
harness run.
- Private workflow preparation and credential-free onboarding preview:
nine compatibility checks passed. Ownership, recovery, evidence,
shared-contract and workflow compatibility: 77 passed. The actual
provider preview also confirms immediate success deletion, earlier
declared failure eligibility, limits, and zero retries without
credential access. Map checks and git diff checks passed.
- Required repository typecheck passed for the product fix. The combined
branch build passed. The local full repository suite was stopped after
repeated PostgreSQL startup failures; a separate initdb probe confirmed
host SysV semaphore exhaustion. No shared IPC resources were changed.
[Hosted
CI](https://github.com/paperclipai/paperclip/actions/runs/40591020873)
passed the full database suites, typecheck, build, runner checks,
serialized suites, and browser shards on final head
`1ac4c23605a03bfd1f1f8a017b14ce29fda85f6b` (55 success, two expected
skips, one advisory neutral).
- Independent source review approved the product guard, atomic race
regression, evidence contract, and maps with no actionable findings.
Both automated reviews are 5/5 on final head
`1ac4c23605a03bfd1f1f8a017b14ce29fda85f6b`; prior findings are fixed and
resolved. Final CI is green and the PR is conflict-free.
- No Cloud workspace, provider call, release publication, or deployment
is part of this verification. These tests do not identify a historical
Cloud failure or qualify live onboarding.
- Local dependency installation uses the existing CI-generated lockfile
from #17811. No lockfile change is included.

## Risks

- Existing onboarding runs without a trusted saved proposal decision
remain in review even when the agent reports success. This is the
intended approval boundary.
- Decision changes can race completion. The status commit checks the
decision under its existing locks and uses the existing status-race
recovery path.
- A saved refusal permits closure only. Creation admission still rejects
it.
- Evidence readers reject malformed receipts and unrelated failure
codes. The version-1 key registry is checked against every receipt field
at compile time. Existing attempts do not gain evidence after the fact.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`), ultra reasoning, through Codex. Used
repository inspection, code execution, and collaborating coding agents.
The runtime did not report 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 references)
- [x] My branch name describes the change and contains no internal
ticket 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-27 17:07:50 -05:00
DottaandPaperclip f60ac29cf1 fix(runner): migrate Grok Build with native reasoning effort (#17922)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Harness selection maps supported agents to Paperclip Runner.
> - The native Runner already supports Grok Build, but its migration
mapping excludes Grok.
> - Grok agents also have a thinking-effort setting that the native
execution contract does not carry.
> - This pull request adds the migration path and preserves explicit
Grok effort through startup and resume.
> - Operators can upgrade an existing Grok agent without silently losing
its model, account, or effort.

## Linked Issues or Issue Description

**What happened?**

Existing Grok Build agents have no Runner selector or upgrade action.
Adding only the mapping would route conversion through the Codex
fallback and lose Grok execution semantics. Native execution also
ignores the legacy reasoning-effort field.

**Expected behavior**

A qualified Grok agent can explicitly upgrade. The saved model, account,
instructions, history, and supported effort remain intact. Unsupported
legacy settings fail before saving. The provider must acknowledge the
selected effort before inference.

**Steps to reproduce**

1. Open the runtime page of an existing Grok Build agent on a qualified
Linux x64 or macOS ARM64 computer.
2. Observe that the Runner selector and upgrade action are absent.
3. Compare the native execution input with the saved legacy
reasoning-effort setting.

Related work: #13882 introduced native Grok Build. #15422 covers the
earlier default-runner work. This change extends the current shared
selection contract.

## What Changed

- Add the Grok harness mapping, qualified platform limits, upgrade
action, and company-scoped computer qualification.
- Translate Grok settings to ACPX without changing the selected account
or explicit model. Resolve the legacy default model to the native
default. Preserve the effective legacy search policy. Reject
incompatible command, argument, permission, and turn-limit settings.
- Add native execution input v10 for explicit Grok effort and search
policy. Preserve historical schemas. Enforce disabled search through
Grok requirements and bind it across startup and recovery.
- Apply and verify ACP `reasoning_effort` before prompting. Bind the
value to provider descriptors, checkpoints, runtime identity, and resume
checks.
- Use the Grok catalog and effort choices in the task composer. Apply
task model and effort overrides while retaining the agent account and
search policy. Update runtime controls, portability/default handling,
documentation, and capability maps.
- Advance Pi and Copilot source attestations for changed shared
transport and recovery code. Keep historical identities intact and
update all Rust integration fixtures.

## Verification

- Migration and review regressions were reproduced before the fixes.
Coverage includes the Grok mapping, default model, explicit effort,
implicit search policy, task overrides, and incompatible legacy
settings. The broad migration, route, immutable-input, and composer
check passed 478 tests. The final catalog and task-input check passed
135 tests.
- Runner startup, recovery, search policy, and profile checks passed 361
tests, with one platform skip. The final source-identity,
search-admission, and transport event-pump check passed 89 tests.
- All 757 Rust workspace tests passed for the broad implementation.
After the final source attestation update, all 55 ACPX profile/session
tests passed.
- `pnpm -r typecheck` and `pnpm build` passed for the implementation.
Server and Runner typecheck passed after the final production change.
Server `tsc --noEmit` passed after the final test-fixture change. Docker
context integrity, token gates, maps, generated protocol data, and
replay goldens passed.
- The v10 startup fixture initially used an ambient local Grok login and
failed on CI. An explicitly empty credential home reproduced all four
failures. The fixture now supplies a synthetic key and a private empty
home. A separate case checks that missing credentials fail closed. All
seven selected Grok v10 and Claude v9 startup cases pass without host
credentials.
- The full local suite could not complete because embedded PostgreSQL
failed before database-backed fixture setup. The broad executor-suite
attempt hit the same limit and was stopped. Neither attempt is counted
as passing. Current-head CI must verify those paths before merge.
- Earlier CI found missing Rust input fields, stale source attestations
and exact fixture pins, a missing Docker context entry, and an outdated
import expectation. Those failures were fixed and checked locally. The
CI logs retain the original failures.
- Different earlier CI runs also failed unchanged cleanup pagination,
device-login timeout, and chat lost-response recovery cases. Later
attempts passed the cleanup and login cases without changes to those
implementations. Their causes remain unproven. The original evidence
remains in [the first
run](https://github.com/paperclipai/paperclip/actions/runs/40563402840),
[the login
run](https://github.com/paperclipai/paperclip/actions/runs/40571128328),
and [the chat
run](https://github.com/paperclipai/paperclip/actions/runs/40573072163).
A passing retry does not establish a root-cause fix.
- Both reviews rate current head
`16fba9b4cdf12bc7945e6628912e79da42959f35` 5/5. All current-head CI
gates pass in [run
40576580699](https://github.com/paperclipai/paperclip/actions/runs/40576580699).
All 60 check runs completed cleanly, including the four intentional
skips and the neutral 5/5 Paperclip review. The legacy security status
is successful. No review threads remain unresolved.
- Staging migration and a real shell task are pending deployment. This
PR does not claim full Grok provider qualification. Reviewers can verify
the operator path by upgrading a qualified Grok agent, checking its
saved model and effort, and running a shell task through native
execution.

## Risks

- Explicit effort and search policy require the matching Runner and
sidecar build. Older immutable execution inputs keep their existing
schemas.
- Providers that omit or reject the selected effort fail before a
prompt. Unsupported effort does not fall back silently.
- Existing agents retain their saved runner until an explicit change.
New Grok agents use native execution only on qualified platforms.
- Grok token and cost reporting remain unverified, as before.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and
context-window capacity are not exposed in this session. Used reasoning,
source editing, shell execution, and browser inspection.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 15:28:42 -05:00
DottaandPaperclip 50b932a142 fix(server): require approval before onboarding task creation (#17914)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/78/changes/paperclip/78
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages agent work and human decisions.
> - Onboarding asks the first agent to propose a task before it starts
work.
> - The first-task skill requires human acceptance before task creation.
> - The native tool could create and schedule that task without
acceptance.
> - REST task creation had the same gap.
> - This change checks saved acceptance in the shared creation
transaction.
> - Valid approvals and ordinary delegation keep their existing
behavior.

## Linked Issues or Issue Description

**What happened?**

An agent could create a task from the canonical onboarding first task
before the user accepted its proposal. A real journey caught this after
the agent read the first-task skill. A local database regression
reproduces the missing check in the native tool and both REST creation
endpoints.

**Expected behavior**

New task creation must wait for saved human acceptance of the latest
ordinary proposal. A different parent or a standalone task must not
bypass that check.

**Steps to reproduce**

1. Bind an authenticated agent run to a server-created onboarding first
task.
2. Leave its proposal unaccepted.
3. Call native `create_task`, `POST /api/companies/:companyId/issues`,
or `POST /api/issues/:issueId/children`.
4. Before this fix, creation succeeds. After this fix, it is denied
before a child or wake is committed.

**Paperclip version or commit**

Reproduced on `3be54534c24fc279533ff421e62a77ad15b72954` before the fix.

## What Changed

- Add a shared check for new task creation from an authenticated
onboarding run.
- Read the latest ordinary confirmation across both confirmation kinds
under the source task lock.
- Require a human card decision or validated conversational acceptance.
Require the current revision for a saved plan.
- Preserve ordinary delegation, committed replay, and dispatch recovery.
- Add database regressions and update execution and onboarding map
documentation.

## Verification

- Real PostgreSQL regression before the fix: 17 failures and four
passing approval/delegation controls. No skips.
- Exact published source: 102 tests passed across admission,
conversational confirmation, and project tools, including all 25
admission regressions. Real Linux PostgreSQL, no skips.
- `pnpm build` and `pnpm -r typecheck` passed locally.
- Map checks and `git diff --check` passed.
- `pnpm test:run` was attempted locally. Existing suites failed because
the host exhausted PostgreSQL semaphore sets. The remaining owned test
process was stopped; its failed log is preserved. No unrelated database
was stopped. Current-head Linux CI passed, including build, typecheck,
and browser E2E. The first CI attempt lost runners; its evidence is
preserved, and interrupted jobs passed one CI rerun.
- The live Cloud attempt remains failed. Local tests do not qualify
Cloud onboarding, artifact delivery, or native tracing. No deployment or
model retry is part of this change.

## Risks

A stricter creation check could reject a valid approval. Tests cover
direct, conversational, checkbox, dismissed-card, and clock-skew cases.
The check applies only to new tasks from the canonical onboarding run.
It does not change existing task updates, execution policy, or wake
recovery.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The
session does not expose a more specific serving model ID or
context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 12:30:50 -05:00
DottaandPaperclip 6e781e0ab2 fix(connections): preserve removed grants when saving installs (#17906)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections give agents access to external tools through access
profiles.
> - Operators can remove a broad app profile and keep a limited profile.
> - Saving a connection's agent list restored the broad profile to
existing installation targets.
> - Those restored grants could permit write tools that the limited
profile omitted.
> - This pull request grants the app profile only to new installation
targets.
> - The benefit is stable permission choices when an operator edits an
installation list.

## Linked Issues or Issue Description

**What happened?**

`PUT /api/tool-connections/{connectionId}/installs` attached the app
profile to every target in the submitted list. An existing target
received the profile again if an operator had removed it. Adding an
agent, removing another agent, or saving the same list could therefore
restore broad tool permissions. The activity log recorded each restored
binding as `tool_connection.install_access_extended`.

**Expected behavior**

Targets that remain installed keep their saved profile assignments. A
removed app-profile assignment stays removed. New installation targets
receive the current app-profile defaults. Removing an installation still
removes its install-derived binding.

**Steps to reproduce**

1. Install a connection with read and write tools on two agents.
2. Give one agent a read-only profile and remove its broad app-profile
assignment.
3. Save the installation list, add an agent, or remove the other agent.
4. Check the first agent's permission to use the write tool.

Before this change, the write tool becomes allowed again. After this
change, it stays denied.

Related: #17422 adds an agent-edit permission check to direct profile
bind and unbind operations. This PR preserves removed assignments during
installation-list updates. The duplicate search found no open PR for
this defect.

## What Changed

- Attach app-profile bindings only for new installation targets.
- Preserve removed grants for existing agent and company installations.
- Keep legacy connection-wide include cleanup on every non-empty
installation save, including saves with no added targets.
- Add six PostgreSQL regressions. All six use the real install HTTP
route with a local operator fixture.
- Check effective read/write decisions, saved assignments, new-agent
defaults, uninstall cleanup, legacy-rule cleanup, and access-extension
audit records.
- Document the behavior in the connector runbook and both access maps.

## Verification

- Red: all four new regressions fail before the fix. The policy returns
`allow_profile` where the tests require `deny_default`.
- Review regression: the two legacy-rule cases fail before the review
correction. The original four cases still pass.
- Green after review: all six regressions and five existing
profile-precedence tests pass after the correction.
- Command: `pnpm exec vitest run
server/src/__tests__/tool-connection-installs.test.ts
server/src/services/tool-profile-binding-precedence.test.ts`.
- The local regression used `PAPERCLIP_TOOL_ACCESS_TEST_DATABASE_URL`
with a separate, fully migrated PostgreSQL 17 test database. Embedded
PostgreSQL could not start because the host had reached its semaphore
limit. Skipped tests were not counted as a regression pass.
- `pnpm -r typecheck` and `pnpm build` passed for the initial fix.
Server `tsc --noEmit` also passes after the review correction.
- `node scripts/check-maps.mjs`, `node
scripts/check-module-boundaries.mjs`, and `git diff --check` pass.
- `pnpm test:run` was started, then stopped after 16 tests in the
native-session suite failed during embedded PostgreSQL startup. A
focused rerun of its `collect` case confirmed the database startup
error. Direct `initdb` output reported `could not create semaphores: No
space left on device`. The full local suite is incomplete. All six new
regressions executed against the separate test database and passed.
- [Initial-fix
CI](https://github.com/paperclipai/paperclip/actions/runs/40541191695)
passed at `23253ee332b90f142e48df3f553aeaaa7f6fa298`. Greptile gave that
commit 5/5. Ponytail found the legacy cleanup gap; this revision
restores that cleanup and adds both regression cases.
- [Current-commit
CI](https://github.com/paperclipai/paperclip/actions/runs/40547366181)
passes for `729c487cf2ffaae261a820de0cf9a033a0365fd4`, including type
checks, build, test shards, and both `ci / verify` and `ci / e2e`
aggregate checks.
- The first CI attempt hit a 30-second module-import timeout in the
unchanged `issue-agent-mutation-ownership-routes.test.ts` suite. All 179
tests passed locally. One [job
retry](https://github.com/paperclipai/paperclip/actions/runs/40547366181/job/122349226221)
passed without a code change. The cause of the import slowdown was not
established. The failed attempt remains recorded in CI history.
- Greptile and Ponytail both give the current commit 5/5 with no
actionable findings. Ponytail confirms the legacy cleanup finding is
fixed. The review thread is resolved, and the PR has no merge conflicts.
Ponytail's advisory check has a neutral conclusion with a 5/5
assessment.

## Risks

- New installations retain the current app-profile defaults. Removing
and then reinstalling a target is a new installation.
- A repeated installation save no longer restores a missing profile
assignment. Operators must use an explicit profile assignment when they
want to restore that grant.
- Existing unwanted grants still require a separate access review and
repair. This PR does not change stored grants, reconnect identity
behavior, or the default access model.
- No database migration or API schema change is required.

## Model Used

- OpenAI GPT-6 in Codex, with reasoning, repository tools, and code
execution. The session does not expose the exact routed model ID or
context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 12:25:01 -05:00
DottaandPaperclip 585b4e6af8 fix(chat): preserve deferred Retry source batches (#17883)
## Thinking Path

> - Paperclip manages agent work through tasks and governed execution.
> - Connected conversations retain the source and authority for each
request.
> - Task Retry pins the full saved GitHub input batch before it waits
for cleanup.
> - Resuming that wait could append an independent board queue after
authorization.
> - Dispatch then rejected the changed batch before the provider
started.
> - This pull request keeps the authorized batch intact and restores
certified undelivered input from historical failed attempts.
> - Each board message retains a separate turn and its own admission
checks.

## Linked Issues or Issue Description

**What happened?**
A deferred GitHub task Retry could consume a separate board message
while promoting its saved receipt. The new run then failed with
`chat_failed_run_retry_not_authorized`. A second Retry could also fail
because the historical run retained the mixed batch.

**Expected behavior**
Retry must preserve the source batch it authorized. Separate board input
must keep its own execution path. Historical input may be restored only
when durable evidence proves that the rejected attempt never started a
provider.

**Steps to reproduce**
1. Retain ten authorized GitHub requests behind a failed native turn.
2. Start task Retry while the predecessor still lacks its exact
termination receipt.
3. Save an independent board message.
4. Complete cleanup and resume the same Retry receipt.
5. Observe the mixed batch rejected during dispatch. Retry that failed
attempt to reproduce the second refusal.

Refs #17725 for the existing saved-input Retry contract. This change
repairs the later queue merge and its retained failed state. Related
#17878 covers snapshot continuation and later turns in recovered
directories; its workspace repair can be reviewed independently.

## What Changed

- Keep deferred chat Retry promotion scoped to its exact receipt.
Ordinary board Retry coalescing retains its existing behavior.
- Let a new explicit task Retry restore a historical mixed batch only
after strict never-started, source, ownership, allocation, board-comment
and prior-delivery checks.
- Preserve failed-run history and original budget-skipped receipts.
Record restored queue ownership in activity.
- Add production queue and HTTP-route regressions. Update the execution
contract and verification maps.

## Verification

- Before the repair, the deferred ten-input batch failed before identity
initialization. The same regression now reaches the real initializer
with the exact GitHub batch. The independent board message then reaches
its own initializer in a separate turn.
- Before historical recovery, ordinary task Retry refused the persisted
mixed failed batch. The repair passes that case without changing the
failed run. HTTP duplicate requests retain one Retry owner. An
additional compatibility probe restored the old queue candidate
predicate and removed all historical mixed-state fixture writes: the
real producer created the exact batch and the complete historical HTTP
recovery case passed (1/1). The fixed-source historical fixture now uses
the production serializers.
- The affected Retry group passes 86 cases on commit
`325c00158df5569f5b42731cda4ecc4584909d99`, including already-coalesced
external receipts. Refusals cover edited sources, active controllers,
unresolved allocations, changed receipts, foreign external receipt
ownership and prior delivery of either board or GitHub input, including
immutable budget-skipped receipts.
- Full workspace `pnpm -r typecheck` and `pnpm build` pass with these
source changes. Map, module-boundary and diff checks pass.
- Full local `pnpm test:run` was started. The host cannot create
additional PostgreSQL semaphores; database-dependent suites fail or skip
at startup. The affected database group runs against a separate migrated
PostgreSQL 17.10 test database with Node 24.22.0 on macOS arm64.
- The regression deliberately stops after the real identity initializer
to avoid provider allocation. It proves HTTP, queue, source
authorization, identity and separate continuation behavior. It does not
claim a live model result, GitHub publication, deployment or recovery of
the original hosted task.
- Current head `325c00158df5569f5b42731cda4ecc4584909d99`: all checks
are terminal with no failures or pending checks; required `ci / verify`
and `ci / e2e` pass. Conditional Storybook checks are skipped. Greptile
and Paperclip each reviewed this exact commit at 5/5. Both earlier
review threads are resolved. Paperclip retains one optional robustness
suggestion for batch ordering; the verified historical producer order
remains a strict recovery contract.

## Risks

Restoring input could repeat work if the prior turn had executed. The
existing strict bootstrap proof rejects provider output, native state,
process or controller evidence, and allocations. Restoration also checks
current external authority, unchanged board revisions and other run
history. An uncertain executor remains held. No migration, provider
fallback or relaxation of dispatch validation is included.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository inspection,
code editing and test execution. The exact runtime model ID and
context-window size are not exposed in this session. A separately shared
regression supplied independent reproduction evidence.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 11:34:18 -05:00
DottaandPaperclip 2f3516f6fd fix(github): authenticate external contributor lookups (#17902)
## Thinking Path

> - Paperclip manages AI agents and their access to external services.
> - A GitHub bot connection can add external contributors by username.
> - The lookup sent an anonymous request even when the bot had an App
installation.
> - Anonymous requests share the server IP quota and can fail for a
valid username.
> - This pull request uses the selected bot installation for the lookup.
> - It also gives users clear errors without exposing credentials or
provider response text.

## Linked Issues or Issue Description

**What happened?**

The Access tab could reject a valid external contributor username with a
generic GitHub error. The lookup did not use the connected bot's
identity.

**Expected behavior**

The lookup uses the selected bot's active App installation. It returns
the numeric user identity or a clear account, rate limit, or
installation error.

**Steps to reproduce**

1. Configure a GitHub review bot and open its Access tab.
2. Exhaust the server IP's anonymous GitHub quota.
3. Look up a valid external contributor username.
4. Observe the generic rejection even though the bot has an
installation.

The original provider HTTP status was not retained. Source inspection
proves the anonymous request. The historical cause remains unconfirmed.

**Paperclip version or commit**

The defect is present at `eda2a03bfe5213ffef2fbbdefdf572be775f1e14`.

**Deployment mode**

Server deployment with an active GitHub App bot connection.

## What Changed

- Pass the endpoint ID from the existing authorized lookup route.
- Issue a short-lived installation token with metadata read permission.
- Reject inactive connections and invalid installation IDs without an
anonymous fallback.
- Distinguish missing accounts, rate limits, and installation access
failures.
- Add 25 lookup tests and update the connector guide and both access
maps.

The GitHub management service owns the provider behavior. The shared
route only passes its authorized endpoint ID. The request body and
response shape stay the same.

## Verification

- Passed: [full
CI](https://github.com/paperclipai/paperclip/actions/runs/40535979115)
on `38d1ebcebb08553f159b3b81ee1bb31d1fbbba8e`, including typecheck,
build, server and workspace tests, Runner checks, serialized suites,
eight E2E shards, and the final verification gate.
- Passed: Greptile 5/5 for the same head, with no open review threads.
- Passed: 25 lookup regression tests on the final test fixtures.
- Passed: 91 tests across five GitHub service suites before the
fixture-only change.
- Passed: `node scripts/check-maps.mjs` and `git diff --check`.
- The tests exercise actual GitHub request construction with provider
response fixtures. They assert the installation identity, metadata-only
token request, request count, and sanitized error details.
- `pnpm build` and `pnpm -r typecheck` could not complete because this
environment has no Cargo executable.
- Two standalone server TypeScript attempts were killed. The second ran
after the full suite was stopped, with a 5120 MiB Node heap limit. The 8
GiB container recorded two OOM kills. Neither attempt produced a
typecheck verdict.
- `pnpm test:run` was started, then interrupted after resource
exhaustion. Its first server phase did not produce a final verdict.
These local attempts remain incomplete. Full CI later passed for the
same head. A live authenticated bot lookup remains unverified.
- The initial frozen install stopped on an existing patch configuration
mismatch. Installation then succeeded with lockfile writes disabled. No
dependency or lockfile changes are included.
- GitHub documents installation-token support for [Get a
user](https://docs.github.com/en/rest/users/users#get-a-user) without
extra user permissions.

## Risks

- The lookup now requires an active bot connection and a saved
installation ID.
- GitHub rate limits can still occur. The error keeps the retry metadata
and tells the user to retry.
- No database migration or permission-policy change is included.
- This PR does not prove that a deployment contains the fix.

## Model Used

OpenAI Codex, GPT-6 family, with code editing, tool use, and test
execution. The recovered implementation was assisted by `gpt-6.1-sol`.
This session does not expose its exact model ID or context window limit.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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-27 11:19:14 -05:00
DottaandPaperclip b8f6d9b23f docs: clarify delegated connection feature and access maps (#17882)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The feature and agent access maps describe user journeys and their
permission boundaries.
> - PRs #17737 and #17739 added delegated connection setup across
several existing areas.
> - The maps include those operations, but some recipes and board-only
statements are stale.
> - This PR adds usable setup recipes and corrects the access
descriptions.
> - The benefit is a clearer verification path that preserves human and
agent authority boundaries.

## Linked Issues or Issue Description

Refs: #17737, #17739.

Related: #17862 changes connection setup advice and catalog choices.
This PR only clarifies the existing maps.

**Issue type**

Outdated and missing documentation.

**Where is the issue?**

The paired connection setup, app permissions, chat channels, model
accounts, and gateway maps under `maps/`.

**What's wrong?**

Delegated setup guidance sits under Gotchas without a matching driving
recipe. Some model-account text still groups supported account sign-in
with board-only host controls. A few callback, privacy, and native
admission descriptions omit important limits.

**Suggested fix**

Add the missing recipes. State the current route and service boundaries.
Keep existing capability IDs and distinguish source review, fixture
tests, and live provider proof.

## What Changed

- Add paired entry points and driving recipes for delegated setup,
permission changes, and managed AI sign-in.
- Describe Google consent restoration, GitHub requested credential
fields and saved rotation, and Vercel personal credential attribution.
- Correct the Vercel callback state checks and chat
conversation/test-status privacy scope. Name the separate GitHub
registration handoff endpoint.
- Replace blanket board-only AI login wording with the specific
managed-account and host/session boundaries.
- Link the five access maps to shared native admission and work-mode
limits. State the permitted self-targeted policy administration
boundary.

## Verification

- `node scripts/check-maps.mjs` passed: 35 paired areas and 192 stable
capability IDs. This checks structure and references.
- `node scripts/storybook-catalog.mjs` passed. Generated output remains
ignored.
- `git diff --check` passed.
- Eleven selected cases in
`server/src/__tests__/connection-management.integration.test.ts` passed
on source `db70c5acd9`, the unchanged base of this documentation commit.
They use a fresh PostgreSQL database, actual agent keys/run JWTs, human
sessions, and deterministic provider fixtures. The other 61 cases were
not selected.
- The selected cases cover connection/profile creation, Google saved
choices, native API entry points, Slack caller/target policy, GitHub
import and identity confirmation, durable gateway authority, AI
accounts/pools, saved human handoffs, revocation, scope, trust, and
Ask/Plan denial.
- Read-only source reviews checked all five areas. The disposable
database was removed after the run.
- Full workspace typecheck, build, and test sweep were not rerun for
this Markdown-only change. Live provider login and browser journeys were
not run. Per-operation source-only/not-run labels remain unchanged.

## Risks

Low risk. Incorrect documentation could misstate a permission boundary
or imply broader verification. The changes cite the owning routes and
services and retain fixture and live-provider limits. No runtime,
schema, lockfile, or workflow files change.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and read-only source-review agents. The session does not
expose a more specific deployment ID or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 09:40:41 -05:00
DottaandPaperclip bd382eee53 fix(recovery): explain retained source verification failures (#17773)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Workspace recovery must prove the identity of retained work before
it uses an allocation.
> - The verifier rejects several different contracts with the same
`source_binding_invalid` code.
> - A saved Retry can therefore stop before file preservation without
enough evidence for a safe repair.
> - Operators need a bounded observation of the selected source without
another attempt or weaker guards.
> - This pull request records closed failure reasons and adds an
explicit read-only inspection on the run page.
> - The benefit is a precise next diagnostic step while the saved work,
intent, and ownership fences remain intact.

## Linked Issues or Issue Description

Refs: #17741, #17053. This is a diagnostic follow-up. It does not change
recovery admission or the retained-source acceptance policy.

**What happened?**

A retained-source recovery exhausted in `verify_execution` with only
`source_binding_invalid`. Run and task diagnostics could not distinguish
an invalid reference, lease policy, source binding, or reopened
allocation. The normal recovery-actions read can also revalidate
recovery state, so it was not a safe substitute for a current read-only
inspection.

**Expected behavior**

Record an allowlisted reason at the rejected guard. Allow a reader to
inspect one exact task/run/action without changing its attempts, saved
input, receipts, or ownership. Clearly separate the recorded failure
from current identity observations.

**Steps to reproduce**

1. Prepare a terminal native run with a retained-source action and a
lease policy of `reuse_by_environment`.
2. Attempt source verification. The guard must still reject that policy.
3. Open the failed run and choose Inspect recovery, then Inspect current
source. The diagnostic should name `lease_policy_not_retained` and the
allowlisted policy.

## What Changed

- Split existing source-binding guards into closed reason codes. Keep
each acceptance predicate and physical recovery action unchanged.
- Persist validated, path-free reason/policy detail with future system
recovery failures. Keep historical generic records compatible.
- Add an explicit query on the existing task recovery-actions GET. Exact
company/task/run/action selection bypasses read revalidation. Run
selection lists at most 20 actions; inspection stops before per-lease
lookup when a record has more than eight sources.
- Add a manual inspection control on native export-failure run pages.
Keep resolved retained actions inspectable. Show recorded failure and
current recorded-source identity separately.
- Update execution semantics and feature/access recipes. The shared type
is the normalized server/UI contract; it contains no provider payload or
secret.

## Verification

- RED: the prior verifier failed both reason assertions for rejected
warm policy and foreign-run lease binding. GREEN: the final focused
source/HTTP, system-state, and UI suites pass 23 tests. The UI follow-up
passes 8 tests after the review fixes.
- HTTP tests prove exact selection, cross-company denial,
resolved-action access, reused-allocation rejection, redaction, and
unchanged actions, runs, leases, tasks, wakeup receipts, workspace
operations, and activity. A nine-source case proves bounded inspection
while the existing worker verifier still accepts all nine valid sources.
- Review follow-up: show allowlisted saved detail beside a changed
current observation, preserve all listed actions, and follow
exact-action selection in verified/limited/error tests. The prior
component fails the saved/current drift regression in an in-memory RED
control; the current component passes. UI typecheck/build pass again.
- `pnpm -r typecheck` and `pnpm build` pass. Token gates, maps, module
boundaries, and `git diff --check` pass.
- Rebased onto master `46de15ff4b` without conflicts. Range-diff proves
both diagnostic commits are unchanged. On new head
`a7e2bc87fcea75e76b6b736304d1287257f71174`, all 23 focused tests, full
typecheck/build, token gates, maps, and module checks pass again. Both
fresh reviews are 5/5 with zero unresolved threads. Final exact-head
GitHub status is CLEAN: 55 success, 2 skipped, 1 neutral, no pending
checks or failures. The [ci / verify
aggregate](https://github.com/paperclipai/paperclip/actions/runs/40387002325/job/121802415824)
passed in eight seconds. All test/build/typecheck/E2E lanes passed.
- Existing full workspace recovery suite: 56/56 pass (103.5 seconds)
before the byte-equivalent rebase. `pnpm test:run` hit repeated embedded
PostgreSQL initialization failure before database-suite assertions and
was stopped. No full local suite pass is claimed. The owned external
`_test` database provided the focused HTTP/source verification. The
prior browser attempt also stalled at Network.enable before its click;
that attempt did not establish browser acceptance.
- Current-head local browser acceptance passes through the actual run
page: Inspect recovery lists the exact action, Inspect current source
shows recorded generic failure separately from the current rejected
policy, and reload resets inspection to the explicit control. Explicit
selection works again after reload. The app used isolated data, an empty
inherited environment, a paused synthetic agent, and no provider
credentials. Final state remains failed/exhausted with zero attempts,
zero wakeup receipts, zero workspace operations, and unchanged original
generic failure. The local app and temporary tab were stopped. This
proves the diagnostic journey, not the deployed source's actual lease
policy or its recovery.
- Final merge verification at
`a7e2bc87fcea75e76b6b736304d1287257f71174`: GitHub reports CLEAN and
mergeable. Both repository-required checks, `ci / verify` and `ci /
e2e`, pass, as does the exact-head Greptile check (5/5, zero unresolved
threads). The separate [Entire
trail](https://entire.com/gh/paperclipai/paperclip/trails/7) has no
recorded reviewer approval; no such approval is claimed. It is not a
configured GitHub merge gate.
- Initial local setup failures were distinct from product assertions:
localhost sandbox EPERM required scoped local access; a browser harness
import path was corrected. A test UUID type inference error and
historical native-export UI selection gap were corrected before the
green run. The live task remains blocked; this diagnostic does not claim
it recovered.

## Risks

- This change improves evidence. It does not prove provider termination,
local descriptor integrity, or successful file preservation, and it does
not repair the original source.
- Current inspection spans multiple database reads. It is an
observation, not a historical cause or execution authority. It performs
no provider/filesystem calls and starts no retry or executor.
- The optional persisted detail is backward compatible. Unknown values
and extra fields are excluded. Oversized source lists remain uninspected
through this explicit diagnostic path; physical recovery rules do not
change.

## Model Used

OpenAI Codex based on GPT-6, with code execution and browser tools. The
exact serving model ID and context window were not exposed in this
session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:21:28 -05:00
DottaandPaperclip 0c9d10d695 feat(connections): complete saved setup guidance and coverage maps (#17739)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product and agent access maps describe the same capability IDs.
> - Agent connection management changes the callable operations and
permission boundaries.
> - Reviewers need an operation inventory that distinguishes API access,
human handoffs, and fixture evidence.
> - This pull request adds saved setup screens and updates the maps for
#17737.
> - The benefit is that users and contributors can inspect the coverage
and remaining boundaries.

## Linked Issues or Issue Description

**Subsystem affected**

Product and permission documentation, saved authentication setup UI and
consent metadata, and product/agent access maps.

**Problem or motivation**

The current maps describe board-only management paths. They need to
match delegated connection management and distinguish administration
from ordinary tool execution.

**Proposed solution**

Record route operations, required grants, responsible-user limits,
transport, saved authentication handoffs, provider-fixture evidence, and
explicit local-operator boundaries for every connection family.

**Roadmap alignment**

This is the documentation companion to #17737. It covers existing
Connected Apps, governed MCP gateways, chat channels, and
personal/shared AI accounts. It uses existing server setup operations
and adds their saved handoffs to the existing UI.

## What Changed

- Show saved AI sign-in and connection setup handoffs in the existing
UI.
- Open GitHub import and rotation links at the required human step.
Resume a committed rotation after reload without asking for another
secret.
- Restore saved Google service choices for the addressed user while
preserving newer consent. Successful direct/cloud consent records its
own timestamp, independently of refresh or lease writes; existing
refresh paths preserve it.
- Update product, implementation, and permission-default documentation.
- Reconcile app permissions, connection setup, chat channels,
profiles/gateways, and model account coverage.
- Use matching capability IDs in the product and agent access maps.
- Label source-reviewed operations separately from fixture-tested
operations and live provider setup.

- Preserve catalog creator attribution under the responsible user, with
the actual agent still recorded. This follow-up moved from the
implementation to keep both reviews below 100 files. This companion now
changes 38 files, including the preserved Vercel personal-credential and
OAuth callback attribution follow-ups alongside consent and catalog
ownership.

- Name the addressed-human browser-session and consent step for Slack
managed authorization and installation. Preserve source-only evidence
for those individual operations.

## Verification

- Current companion head: `04d40cdd605452d91cf4931476eb292a210825af`,
including implementation `2ecd6451d0` and master `ea727dc3c2`, 38 files.
All intended companion files survive: 35 are byte-identical to the
previous companion; two chat maps and qualification add current
evidence. Exact-head Superagent passed and Paperclip Review supplied an
actual neutral5/5 assessment with no findings and explicit
no-independent-runtime/live/current-CI verification limits. Exact-head
Greptile also completed at5/5 with no findings; both formerly failed
shards and their verification aggregate passed on attempt2; full
exact-head Linux CI workflow40446969603 completed SUCCESS. All current
checks and statuses are terminal clean, with no unresolved findings.
This PR remains dependent on #17737 and needs fresh checks after its
required post-squash replay. The preceding 605 head’s reviews are
historical after this update. Older b0ea Linux workflow success after
its single rerun also remains historical.
- Earlier preserved-stack verification passed **2,165 tests**: 70
assembled-server actual-auth scenarios, 27 OpenAPI contracts, 2,022
native API tests and 46 saved GitHub wizard cases in fresh PostgreSQL.
The parent also passed **141 existing gateway/policy tests**. Workspace
typecheck/build, maps and token gates passed. The initial typecheck IPC
denial and all material intermediate regressions remain in the
qualification record; no full local sweep or live provider setup is
claimed.
- Operation maps now cover issuer/target gateway policy intersection and
post-approval revocation, bounded activity pagination through
private-only windows, and native local-login encrypted receipts. The
companion preserves the Vercel OAuth callback ownership change with its
existing credential ownership follow-up.

- Parent CI has one retained connection-intent e2e failure from a
periodic-recovery timing race. GitHub refused the first job-rerun
attempt while its workflow was nonterminal. Once completed, the single
failed-job rerun was accepted as attempt 2 and passed, including the
full parent Linux workflow.

- Companion Linux server shard 4/12 retained a cleanup-idleness timeout
in `login-cleanup-work.test.ts` (active work was still 1 after its
five-second wait). The same unchanged cleanup suite passed all 16 cases
in the parent Linux job 121950185096 and all 16 cases locally against a
fresh disposable PostgreSQL database. Relevant cleanup/reaper/scheduling
runtime code is unchanged. The single unchanged-code failed-job rerun
was accepted as **attempt 2** on the previous `b0ea3c940f` head
(workflow 40431671705). The failed shard and complete Linux workflow
passed on attempt 2; no additional unchanged-code rerun was used for
this failure. The first local attempt failed the existing dedicated
`_test` database-name guard before running tests; the correctly named
fixture passed without weakening the guard.

- **Earlier 82 GitHub UI tests passed**. All three new replacement cases
were red before the fix. A confirmed unchanged generation preserves the
earlier copy; a changed or unreadable generation blocks copying and
reconnecting. An explicit status check can restore the copy when it is
still current. All earlier import, rotation, verification, and retry
states remain covered.
- The complete stack passed **82 API/OpenAPI tests** in fresh
PostgreSQL, including 55 scenarios with real agent keys, run JWTs, human
sessions, production defaults, persistence, and deterministic providers.
The parent also passed **60 Copilot installation tests**, preserving
published v62 and binding combined guidance as v63.
- **Earlier 10 focused Google/OAuth tests passed**: eight picker cases
and two local-HTTP protocol cases proving consent metadata survives
concurrent token refresh. The refresh and legacy UI cases were red
before the fix. These protocol fixtures use the existing injected board
actor and do not count as agent-authenticated proof.
- Workspace typecheck/build passed after the consent change; normal
migration generation reported no SQL changes for the additive JSON
metadata. The parent's latest caller-authorization correction passed
server typecheck/build. Map validation and token gates passed. Maps
cover 35 areas and 192 capability IDs. The specification names migration
`0380_broken_aqueduct.sql`.
- The test-call operation maps now record the full caller/target tool
access decision (profiles, policies, and explicit grants), credential
identity for every auth label, approval, and rate checks. The
profile-only precondition was removed after the new permitted-access
cases failed; those cases and the no-auth identity regression now pass.
Saved test status requires its originating principal and current
linked-task access; actual key/JWT privacy-denial evidence is recorded.
- Tool-connection activity is now operation-verified: 100 events over
two tasks require two capability decisions and at most two run captures
(previously 100/102), preserve private-event filtering, and deny the
next request after audit revocation. The regression was red before the
fix.
- Cloud enrollment creation and callback entries now name
instance-administrator and company/principal checks. The callback is a
browser return with HTML or a 303 redirect. Status reads retain their
separate board-actor rule.
- Operation maps identify the API, transport, authorization, evidence,
and human/operator boundaries. Structural checks do not establish live
provider behavior. Earlier failures and fixture corrections remain in
`doc/plans/2026-10-13-connection-api-parity.md`.
- An earlier companion head (`26edbe17`) received an actual Paperclip
Review assessment of 5/5 with no actionable findings, published with
neutral status. That review did not run tests or confirm CI, and it is
historical for this new head. The prior incomplete execution result is
not counted as a passed assessment. Fresh review remains pending. The
duplicate enrollment findings have explanatory replies and are resolved.
- The latest implementation correction passed all 55 actual-auth
scenarios and 27 OpenAPI contracts (separate commands). It repairs
unavailable old credential material, preserves fresh import versus
configured reconnect links, and distinguishes credential field
sets/completion modes in handoff keys. The new fresh-link and collision
cases were red before the fix. All 41 GitHub wizard tests now pass,
including filling the fresh saved handoff and asserting App import
rather than reconnect; UI typecheck, maps and token gates also pass.
Qualification retains the earlier failures and an incorrect OpenAPI
filename that selected only the integration module before the correct
separate contract run.
- Configured GitHub credential-entry links carry canonical requested
fields and all/any mode. The form displays and submits those values
through human reconnect while retaining other saved credentials. Two
webhook/client-secret cases were red before the fix; combined all/any
and legacy-link cases also pass. The current UI fixes the old bf760912
baseline referenced by the duplicate main review finding.
- After merging master baec3abd67 and regenerating migration0380, the
complete stack passed **128 tests** (55 actual-auth, 27 OpenAPI and 46
GitHub wizard cases), workspace typecheck/build, maps and token gates.
Eight current Google UI cases also passed. The two local-HTTP OAuth
cases could not initialize embedded PostgreSQL in this fresh attempt, so
that attempt is not a protocol pass; the earlier ten-case evidence is
historical and fresh Linux CI remains required.
- The reproduced Linux automatic-Slack challenge failure is fixed by
retaining verification only for the same signing fingerprint and
callback URL; all eight neighboring provider compatibility cases pass.
Qualification also retains the uncommitted GitHub field variant that
failed initial-secret compatibility before the extension was narrowed to
reconnect, and the first unmigrated external-database diagnostic.
Upstream 0379 remains intact; normal generation/pruning produced
additive/idempotent 0380, with repeated application verified.
- Both PRs must ship together. The user authorized merging when checks
pass. Merge #17737 first, replay only this companion's changes onto
master, retarget this PR, and require fresh current-head CI and review
before its squash merge.

- The updated maps distinguish authorized bot-token/API-key setup from
human verification-key entry and forbid generic channel secret-reference
replacement. Actual key/JWT security baselines were red before both
guards; all 82 API/OpenAPI cases, eight native receipt protections, and
49 policy-service tests now pass. The qualification record preserves the
initial lifecycle/fixture/union-assertion diagnostics and the preceding
Linux CI assertion failures. Maps pass on this updated stack. Fresh
exact-head CI and reviews remain required.

- The parent now preserves a per-field credential-change boundary before
retiring saved credential-entry cards. Old health, unchanged entry,
unrelated repair and retries cannot bypass it. Current authority is
checked before and inside credential persistence; a real provider-time
revocation regression was red before the fix. Final 82 API/OpenAPI
tests, four neighboring lifecycle cases, and server typecheck/build
pass. Maps pass, and qualification retains the hidden-metadata fixture
failure and the measured minute-boundary rate-test failure. Production
rate behavior is unchanged; only the relevant test Date clock is fixed.

- After the current master/parent refresh, all **341 affected UI
cases**, combined workspace typecheck/build, maps and token gates pass.
The updated parent also passed **97 actual-auth/OpenAPI cases**, **141
gateway/policy cases** and **61 profile installation cases**. Published
upstream Copilotv62/v63 remain unchanged; combined guidance is now v64
(`sha256:22e31f95ef972bcead98a4a707c9f33433558fd111e390e027a2bbb4346e112a`).
Qualification retains the initial source-identity failure and fixture
port/migration setup failures. No full local sweep, fresh local OAuth
protocol run or live acceptance is claimed; fresh Linux CI must qualify
this successor.

- Latest review follow-up: the parent fixes caller-policy bypass in
Slack tests/invitations and premature identity-handoff completion. The
maps now name caller/target Block/Ask/rate intersection, one charge for
a shared bucket, and the addressed human’s exact current identity link.
Parent verification passes all **99 actual-auth/OpenAPI tests**,
typecheck and build. The preserved combined companion passes the four
focused tests (including twelve Slack policy/recipient combinations and
the actual human OAuth confirmation path), workspace typecheck/build and
maps. The 50 embedded-PG continuation cases were skipped locally because
their database could not start; fresh Linux CI remains required. All
material red/intermediate results and corrected-fixture evidence are
retained in the qualification record.

- Current `04d40cdd60` CI workflow40446969603 retained two new failures:
server1/12 `workspace-runtime.test.ts` could not reach a fixture
subprocess’s health endpoint within its ten-second readiness window
(job122001926052), and chat2/3 `wakes Slack session sync from
publication commit and leaves settled action queues quiet` observed one
select after its idle predicate (job122001925936). Both same cases
passed in parent `2ecd6451d0` Linux jobs122001920494/122001920581. The
runtime and queue implementations are unchanged by this companion. Both
failing cases also pass unchanged locally: two real-subprocess runtime
readiness/reuse tests and the exact Slack quietness assertion against a
fresh migrated PostgreSQL database. Logs:
`/tmp/parity-04d-server1-failure.log`,
`/tmp/parity-04d-chat2-failure.log`,
`/tmp/parity-2ecd-server1-green.log`,
`/tmp/parity-2ecd-chat2-green.log`,
`/tmp/parity-04d-runtime-qualified.log`,
`/tmp/parity-04d-chat-quiet-qualified.log`. The single standard
unchanged-code failed-job rerun was **accepted as attempt2** on the
unchanged exact head at `2026-10-27T04:24:30.513973+00:00` after the
workflow completed. Both new failure retry allowances are now
**consumed**; both failed shards and the complete Linux workflow have
now passed on attempt2, including the verification aggregate. No
additional unchanged-code rerun will be requested for either failure. No
timing, assertion, idle-work guard or policy was weakened. If either
case fails again, investigate/fix rather than rerun again. The older
5b/b0ea rerun allowances remain consumed and separate.

## Risks

- Saved handoff links depend on the API changes in #17737, including the
nonsecret credential-generation metadata. Both PRs must ship together.
- A map can overstate operation coverage. Entries identify their
evidence and retain human authentication and trusted-host limits.
- Structural map checks do not prove live provider behavior.

## Model Used

- OpenAI Codex, GPT-6 family, with reasoning, repository tools, and code
execution. The runtime does not expose a more specific deployment ID or
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass — focused UI/guidance and
map checks
- [x] I have added or updated tests where applicable — saved setup UI
tests and map validation apply
- [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 — exact `04d40cdd60` full Linux
CI completed SUCCESS on attempt2; all current checks/statuses are
terminal clean, with an actual neutral5/5 Paperclip assessment
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
exact `04d40cdd60` review completed with no findings
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:21:02 -05:00
DottaandPaperclip db32bdf98b fix(github): recover review replay and preserve passive summaries (#17726)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/8/changes/paperclip/8
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - GitHub tools save review assessments and publish their confirmed
receipts.
> - A timeout before publication staging can leave an invocation with no
saved publication.
> - Exact replay must repeat only the authorized preflight and converge
on one publication.
> - PR requests also share an App-owned summary comment. Progress and
maintenance must preserve its final content.
> - A native turn can intentionally wait for an author without sending
another reply.
> - This pull request repairs unstaged replay and prevents queued or
passive-wait notices from replacing a published assessment.

## Linked Issues or Issue Description

Related repairs: Refs #16883, Refs #16284, Refs #16275 recover saved
publication receipts. Refs #17183 covers unavailable approved replay
output. Refs #17714 fixes a separate publication lock-order problem.

**What happened?**

Exact review retries can return null `begin_review` output or
`github_publication_unavailable` after an upstream read times out before
publication staging. Separately, response maintenance can replace a
completed PR assessment with “Review queued…” or a generic
missing-response notice after an authorized no-new-work reply. The
latter run can correctly commit a passive wait while its external
summary is still overwritten.

**Expected behavior**

Exact retries repeat only the authorized preflight. A saved or uncertain
publication keeps its existing recovery owner. Queued acknowledgements
preserve final App-owned summary content. A committed native passive
wait settles its current acknowledgement without writing a response or
treating an old summary as a new-run reply. Success before presentation
remains held until a durable decision exists; exact current-run
confirmed receipts can retire their placeholders. Genuine missing/error
responses retain fallback handling.

**Steps to reproduce**

1. Hold a GitHub metadata read until an authorized gateway call times
out before publication staging. Repeat the exact request.
2. Publish a valid PR assessment. Send an ordinary author reply that
asks for no new work and no duplicate comment.
3. Commit the native `response_wake` with a no-comment server
presentation decision. Run response maintenance twice.
4. The base returns the invalid replay result or replaces the assessment
with progress/fallback text.

**Paperclip version or commit**

Replay regression: `41c42895fa862c586ff841f8c50200d93ffc83a4`.
Maintenance regression: the previous PR head
`c7553d2325df53d98d9febff7023ade4b1e704eb`. Both use real PostgreSQL and
simulated GitHub responses. The maintenance failure was also observed in
normal hosted use.

**Deployment mode**

Source checkout on macOS arm64 with isolated PostgreSQL 18, followed by
a dedicated QA qualification. No production rollout is included.

## What Changed

- Route exact `begin_review` replay through its typed owner. Repeat
unstaged preflight only with the complete request digest and no
successful invocation result.
- Preserve current policy, immutable assessments, unique action keys,
receipt recovery, and provider leases.
- Preserve a verified App/marker-owned final shared PR comment during
acknowledgements. New canonical assessments can still replace it at the
same or a new head.
- Project only a bounded server-committed native wait decision. Settle
the current main-PR acknowledgement without provider writes or a
fabricated current-run reply receipt.
- Hold succeeded native runs while presentation is undecided, including
the committed-before-presentation window. An exact current-run confirmed
receipt can still retire its placeholder.
- Keep missing/error fallback and uncertain publication checks. Update
the bot guide, execution semantics, maps, and real-database regressions.

## Verification

- **Causal RED:** exact begin replay returned null; exact unstaged
submit replay returned unavailable. The new real-database maintenance
test then reproduced the exact generic summary overwrite. Its first
repair also exposed an earlier queued-acknowledgement overwrite. Both
publication boundaries are repaired. Four additional ordering
regressions reproduced the generic PATCH while native presentation was
undecided; the corrected tests hold until the same row settles.
- **Local GREEN:** 196 complete GitHub workflow cases pass on an empty
migrated PostgreSQL fixture. This includes queued/running preservation,
both success-before-presentation windows, null/scalar/invalid decisions,
exact-current versus predecessor receipts, durable acknowledgement
settlement, repeated no-op maintenance, eventual genuine missing/error
fallback, pending writes and same/new-head canonical replacement.
Workspace typecheck, exact-head build, maps and whitespace checks pass.
The real database respects the actual selected-column projection.
- **Command:** `PAPERCLIP_TEST_DATABASE_URL=<owned-postgres-18> pnpm
--filter @paperclipai/server exec vitest run
src/__tests__/chat-channels.integration.test.ts -t 'GitHub agent review
workflow'`.
- **CI/review:** historical heads
`c7553d2325df53d98d9febff7023ade4b1e704eb` and
`4d00d3af6f2ccbda8f38a98f81d392d82dd3c59c` had Greptile 5/5. Final
readiness head `2d267f1e4aa0b835a11aede97798fbd800d9cd96` passed
independent source review with no actionable finding and fresh Greptile
5/5 with zero unresolved threads; all 54 check runs pass with 2 intended
skips; Snyk is successful and the merge state is CLEAN. The dedicated QA
destination acceptance also passed.
- **Full-suite limitation:** the earlier `pnpm test:run` attempt
produced no final summary. Its retained log reports failures in
unchanged workspace-runtime tests and 15-second gateway-audit and
stale-question timeouts. Their cause remains unknown. Do not treat the
targeted results as a full local-suite pass.
- **Live evidence and limits:** normal native OpenCode/DeepSeek review
delivery published a useful assessment, inline finding and App check at
the exact reviewed head. A separate ordinary author reply delivered a
useful answer and settled. Those are ordinary delivery proofs, not live
injected-timeout proofs. A later no-new-work reply exposed the
maintenance overwrite. The final combined source
`070e9c4ead9341cd497b23f533a91bf194475e79` includes the exact
publication repair and passed normal review → ordinary author reply →
quiet destination acceptance. A normal current-head review restored the
legitimate assessment; the ordinary no-new-work reply then committed a
passive wait without new GitHub tools. The same 1,436-character summary
stayed identical while queued/running, after terminal settlement, and
more than 3 minutes 50 seconds after successful cleanup. Review rows and
receipts stayed unchanged, with no owner, live run or queued input.

The timeout fault fixtures prove replay and single-publication safety.
The historical first upstream timeout producer remains unknown. The live
board reads do not expose the raw acknowledgement action row: its
terminal cancellation and next-pass no-op are real-PostgreSQL fixture
proofs, while the hosted checks prove actual destination stability. The
hosted journey did not inject a timeout or pause the
terminal/presentation writer window. Private destinations, raw receipts
and internal task identifiers remain outside this PR.

## Risks

- Original and repeated metadata reads can overlap. The immutable
assessment, action uniqueness and publication lease must remain
authoritative.
- Missing complete request identity or a deleted completed receipt
remains held. The gateway does not reconstruct receipts or relax
approval.
- Passive suppression requires actual native mode/committed phase,
current source ownership and the server's no-comment decision. It
applies only to the main PR review surface. Uncertain current writes
stay held; other surfaces keep normal placeholder retirement.
- There is no migration, credential change, dependency or new retry
scheduler.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) in Codex assisted with diagnosis,
implementation, tests, and source review. It used reasoning, repository
tools and code execution. The context window size is not exposed in this
session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 22:22:57 -05:00
DottaandPaperclip 208a093d19 fix(chat): preserve resumed review waits and retry newer saved input (#17725)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/36/changes/paperclip/36
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - GitHub review agents publish findings and wait for an authorized
reply or head change.
> - Review tools could retain the requester after resume while
completion lost that same wait proof.
> - A yielded report could then queue its own continuation or repeat a
missing-wait error.
> - Ordinary Retry could also select an older failed turn while a newer
saved request had no admission.
> - This change shares the existing authority proofs and canonical
admission owners.
> - Current access, publication, execution and budget gates remain
required.

## Linked Issues or Issue Description

Refs #17318. Builds on the canonical saved-input retry owner in #17733.
Related #16550 covers deferred legacy comments after ownership waits.
The separate recovery repair in #17724 owns the cleanup-to-saved-input
handoff; this PR does not add a second admission owner.

A resumed review could publish an assessment, then turn its
`response_wake` into an immediate `issue_status_changed` wake. A
provider that omitted its continuation could instead repeat a completion
error. A newer linked-human message saved during a budget hold could
also remain unstarted because Retry selected the older failed source.

## What Changed

- Resolve passive review waits through the accepted requester ledger
used by GitHub tools. Require the latest reviewed head, exact company,
task, agent, repository and processed publication under current access.
- Fill omitted/null yielded continuation from that server proof. Permit
an inherited normal tree resume only through its accepted parent
identity. Permit an ordinary follow-up only after this run has a
processed useful reply linked to its exact inbound message. Reject
acknowledgements, partial assessments, pending or uncertain writes as
that reply proof.
- Recheck the same run/review/head/source proof during feedback,
finalization and final status commit. Preserve explicit malformed-input
rejection and Done policy. Add no monitor permission or publication
grant.
- Keep heartbeat and publication projections narrow. Preserve both
published Copilot v62 identities and generate source-bound v63 from the
pinned merged base. No v63 live qualification is claimed.
- Certify the structured isolated-directory binding failure only at its
pre-allocation boundary and only through canonical task Retry. Other
workspace validation reasons and unknown effects remain denied.
- Route Retry to eligible newer saved input through the existing
canonical owner. Preserve the old result and skipped receipt. Require
current principal, source, App, runtime fence, budget, native ownership
and exact cleanup proof.
- Recover absent historical App metadata only through an earlier trusted
processed response receipt and an immutable non-null endpoint claim.
Explicit malformed or conflicting metadata stays denied.
- Revalidate execution through the exact claimed wake, coalesced task
Retry and resolved user-continuation receipt after admission. A second
normal Retry can recover the exact never-started authorization failure
with unchanged saved input. Require empty execution evidence, exact
diagnostics and no allocated or active executor.
- Explain when a recorded result prevents exact replay. Ordinary board
Retry directs a new task message to continue from saved work. Inherited
requester identity alone never grants replay.
- Keep accepted board-message preparation failures with the canonical
task Retry owner. Certify the exact unchanged comment, original user
wake, accepted same-user identity and absence of provider execution. Pin
that source, recheck it at admission, and bind identity initialization
to the coalesced intent and exact claimed successor receipt.
Uncertifiable sources retain an actionable fresh-message refusal.
- Return safe named authority categories for board Retry refusals.
Update execution documentation and capability maps. Add no schema or
polling loop.

## Verification

- A fresh external review request exposed a separate isolated-directory
preparation failure before allocation. Its first normal Retry saved an
intent but admitted no successor. This follow-up certifies only that
exact structured preparation boundary through the existing canonical
Retry owner, with trusted failed settlement and no executor, lease,
result or output. A real HTTP/queue regression reproduces the missing
successor before the repair. Twenty-three current-source safety cases
and the final 98-case Retry/HTTP group pass, including a fresh click
after a denied intent, source revocation, accepted results and the older
direct API remaining denied. The warning case uses actual configuration
preparation and production event append; unknown warning shape or
provider provenance stays denied. Full workspace typecheck, build, maps
and diff checks pass. Renewed hosted normal Retry now succeeds on the
final combined source: it preserves the exact saved request and linked
requester, starts one native successor in a fresh attempt workspace,
publishes the current-head 2/5 assessment and commits In review with
passive response wake.

- A later hosted normal Retry published a low-score assessment but lost
its accepted source identity because the previous attempt failed before
identity initialization. It repeated continuation errors, then submitted
Done. This is failed acceptance, not a successful qualification. The
initializer now retains the exact source only after execution-time
failed-chat Retry authorization; generic Retry and Done policy are
unchanged. A real queue/initializer regression fails with a null source
on the previous code and passes with the newer saved source. Two real
database completion cases verify that source yields the authoritative
wait and commits In review. Renewed hosted normal Retry now retains the
accepted source and exposes the authoritative current-review wait. It
completed after two semantic feedback corrections (wrong contract
revision, then wrong criterion IDs); the correct contract was present in
emitted input. The third finish was accepted and committed In review,
with no missing-wait loop or Done escalation.
- Repeated board-message preparation failures now walk their canonical
intent, failed dispatch and accepted parent identity, rechecking each
contained predecessor. A production queue regression fails the second
ordinary HTTP Retry before the repair and passes afterward. Changed
source, contradictory execution evidence and cyclic receipts remain
denied; traversal stops after twenty links.

- New inherited omission cases failed before the repair. The final full
PostgreSQL 18 wait/status suite passes **252 tests** under Node 24.22.
It covers omitted/null input, malformed-first recovery, same-head
resume, exact-source replies, changed heads, revoked access,
pending/uncertain/mixed publications, final commit revalidation, no
duplicate review and no self-wake.
- **15 existing publication tests passed before the pinned merge** on a
separate fresh database. They retain default partial-delivery and
failure-fallback behavior. Context reads remain below the unchanged 16
KiB heartbeat and publication response limits with large saved output
present.
- Saved-input tests cover a real signed PR webhook, production
accounting-budget refusal, normal policy recovery and canonical Retry.
Historical producer-shaped tests prove the missing-App case red, then
check trusted prior receipts and malformed, late, revoked or mismatched
proof. A broader order-coupled test was reproduced on the prior source;
its global fault injector now targets its own authorization query. The
43-case sequence passes without changing production behavior or its
safety assertions.
- New signed-ingress and real heartbeat execution tests reproduced the
admitted-successor failure, then the next normal Retry failure. The
final pinned merged source passes 249 full GitHub review/publication and
Retry cases on a fresh database, including all 49 saved-input cases. A
separate 74-case Retry/HTTP run also passes. Exact dispatch negatives
cover source, company, agent, task, successor, receipt, pause,
assignment, accepted success, controller and cleanup proof. Bootstrap
contradictions remain denied. The canonical Retry suite passes 16 cases
through its supported external PostgreSQL test connection.
- The normal board HTTP route reproduced the unusable inherited-result
refusal. It now returns actionable guidance without starting a
successor. The actual UI Retry hook and banner tests pass 12 cases.
- A production-shaped accepted board comment followed by a pre-provider
qualification failure reproduced HTTP 409 before the repair. The final
real HTTP/queue test certifies one canonical successor and preserves the
accepted identity. It rejects changed source, actor, task, agent,
result, controller, process, profile, allocation and receipt evidence. A
post-acceptance source change keeps the same intent pending. Execution
revalidation rejects removed or mismatched proof. The probe stops
deliberately after production identity initialization; it does not claim
provider execution. The final source passes the 75-case Retry group, the
focused two-case board/inherited-policy group and 19 canonical Retry
cases. Full workspace typecheck, build and map checks pass.
- Full workspace `pnpm -r typecheck` and `pnpm build` pass. Map,
module-boundary and diff checks pass. Full local `pnpm test:run` remains
unverified. The 256-case explicit-native suite cannot initialize its
packaged PostgreSQL because libzstd is absent; an existing
command-scoped fallback did not resolve it. Current-head remote
full-suite checks are required. Merged-source full GitHub+Retry (249),
separate Retry/HTTP (74), full wait/status (252), profile/history and
completion (75), and visible Retry hook/banner (12) checks pass. The
fresh owned PostgreSQL 18 databases applied all 377 migrations.
- Actual Rust Runner, OpenCode 1.18.34 and exact DeepSeek used unchanged
production-generated synthetic contexts. Resume finished with an
explicit server wait. The author-reply trial omitted continuation twice:
its first report failed the existing empty-criteria check; the corrected
second report still omitted continuation and received the exact server
wait. It completed once with no missing-wait loop or Done escalation.
Controller acknowledgments were synthetic; these probes do not establish
hosted publication or board state.
- Hosted combined testing proved automatic admission of the exact saved
author reply, a useful GitHub answer and committed passive wait. It
required two malformed-continuation rejections before a nullish fallback
succeeded. A later normal Pause/Resume completed in one finish with
explicit response_wake and no new review/comment. The admitted normal
Retry then exposed the execution guard gap repaired here. Those remain
checkpoint results. On the final combined source, renewed normal Retry
completed actual native provider work and GitHub publication, committed
the passive wait, released ownership and cleaned up its environment. A
subsequent ordinary unmentioned author reply woke once, made no GitHub
tool calls or new assessment, and completed its first finish with an
explicit response wake. Both exact leases expired with successful
cleanup and the queue was empty. However, final destination inspection
found a separate automatic fallback overwrote the existing summary with
a generic no-final-response message. External summary preservation
therefore remains failed acceptance; the separate publication repair in
#17726 owns that producer. Full combined publication preservation has
not passed. These hosted runs include the pinned-base native additions;
they do not qualify Copilot v63.
- Current-head automated review is 5/5 with zero unresolved threads. All
current-head CI gates passed (54 successful checks/contexts, four
skipped, none pending). The earlier login-cleanup idle-work assertion
also reproduced locally while its controlled baseline passed; its cause
remains unknown, but the exact assertion passed in the fresh
current-head CI shard. No timeout, assertion or production workaround
was added. This PR is ready for review within its source, authority,
native finalization, state, wake and cleanup scope. The independent
automatic fallback publication regression is tracked by #17726; no
complete combined workflow pass is claimed.

## Risks

- The latest saved review defines the durable head boundary. Ingress
must record a new head before admission. A reply receipt proves delivery
only for its exact saved source; a shared GitHub comment ID alone cannot
authorize this wait.
- Historical App recovery cannot infer identity without direct proof or
an earlier valid server response receipt. It never replays that
response.
- This does not infer review-score policy from instructions or override
Done. No deployment, merge or repair of historical tasks is claimed by
the PR.

## Model Used

OpenAI `gpt-6.1-sol`, with reasoning, repository inspection, code
editing and test execution. The context-window size is not exposed in
this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 22:22:47 -05:00
DottaandPaperclip f0877a9c7c fix: recover native work and requalify saved computers (#17724)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/32/changes/paperclip/32
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages AI agents and preserves their work after an
interruption.
> - Native Stop must confirm termination and save the workspace.
> - Task and run views must show the current recovery receipt.
> - A new external reply can arrive while that cleanup is pending.
> - The reply must return to its original chat owner after cleanup.
> - A successful fresh retry also becomes the task’s bound workspace for
its next ordinary turn.
> - Managed computer updates can invalidate a saved snapshot
qualification.
> - This pull request fixes those instructions, acknowledgements,
handoffs and the existing native-agent Test path.
> - The operator can continue with new input while the stopped turn
remains preserved.

## Linked Issues or Issue Description

**What happened?**

Stopped native runs could keep the initial workspace-repair instruction
after files were recovered. Native Stop could also leave the shared
cancellation state at requested after remote termination was confirmed.
A new GitHub reply saved during cleanup could then remain queued because
cleanup did not ask its original inbound owner to reconsider the
receipt. After a managed snapshot update, an existing native agent could
also need qualification while the generic environment Test required
instance-admin access.

**Expected behavior**

Show the current saved-work state. Acknowledge Stop only after exact
termination proof. Let an authorized operator use the existing
saved-agent Run test to qualify its current computer. After cleanup,
recheck the saved reply's current authority and admit it once as new
input. Preserve the stopped run and uncertain external effects.

**Steps to reproduce**

1. Stop an active native turn before it returns a semantic result.
2. Send a new authorized external reply while cleanup is pending.
3. Let workspace recovery and provider cleanup finish. Inspect the run
instruction, Stop acknowledgement and queued reply.

Related work: #17594 preserves native processes through controller
outages. #17401 addresses a separate bootstrap failure. This pull
request does not replace those fixes.

## What Changed

- Use the exact run's workspace recovery receipt for task and run
guidance, including the Activity ledger.
- Retire an obsolete exact-session notice through the existing bounded
reconciler. Preserve the separate no-replay hold.
- Write the shared native Stop acknowledgement only after the audited
Stop intent and every exact remote lease receipt match.
- Delegate saved external input to the live inbound owner. Recheck its
source, actor, endpoint, principal and conversation generation. Promote
the same receipt in the transaction that creates its new run.
- Use that owner from the cleanup callback and existing stranded-queue
catch-up after a lost callback or restart. A denied source cannot abort
other items.
- Reuse the current private task directory after a successful fresh
retry. Re-read the company/task/workspace binding and validate the
canonical stable or attempt namespace without recreating missing files;
keep a later fresh retry separate.
- Extend the existing agent-scoped qualification owner to native agents.
The clean saved-agent Test qualifies its exact computer before runtime
testing. Reuse a current proof; require a real probe and verified
cleanup for a stale proof. Preserve draft tests and metadata-only
external/pool previews.
- Update execution semantics, capability maps and the recovery
verification recipe. Add a production-page Storybook interaction for the
normal native Test.

## Verification

- **Red:** persisted recovery states returned stale instructions; an
exact terminated native lease left shared Stop requested; the real
GitHub subscribed-message fixture left zero successors after cleanup.
The controlled baseline restored the previous production source,
reproduced the failure, then restored the fixed bytes with matching
SHA-256 hashes.
- **Green:** 382 durable-chat, native-continuation, Stop and recovery
tests pass. The real GitHub/PostgreSQL handoff matrix passes 12/12. It
covers callback, application restart, callback/sweep race, valid input
behind a deleted source, and denial for unknown stop, wrong allocation,
paused endpoint, revoked principal, deleted or changed source, changed
conversation generation and foreign scope. Repeated callbacks preserve
one receipt, its actor, one successor and the unchanged stopped
predecessor.
- **Workspace continuation red/green:** the real PostgreSQL preparation
flow created a fresh attempt and saved a marker, then rejected the next
ordinary turn with the same binding mismatch observed in deployed use.
The repaired preparation and filesystem suites pass 86/86: stable and
attempt-root reuse, saved-marker preservation, a later clean sibling,
changed current bindings, foreign company/task, closed workspace,
traversal, missing path and symlink refusal. No task row reset or
old-turn replay is used.
- **Qualification red/green:** a native saved-agent qualification
returned 422, and its normal Test skipped qualification. The repaired
path passes 224 qualification/immutable-snapshot/environment tests and
176 UI/upgrade tests. It covers revoked authority, foreign or changed
computer, current-proof reuse, failed/missing proof, draft settings,
settings changed during the probe, and external/pool previews. On exact
current source, the real local Harness / Runtime UI also qualified a
newly saved disposable Computer with missing proof through actual
Daytona, then completed the actual OpenCode/OpenRouter hello probe using
`openrouter/deepseek/deepseek-v4.1-flash-1017`. Supported availability
changed from Legacy-only to Paperclip Runner after proof persistence.
Qualification and runtime leases both completed normal release/cleanup.
The five prior task run IDs were unchanged; no task wake was created.
This is macOS source-server/UI with real Linux Daytona and provider
services, not a hosted UI claim. Test probes are archived by the
existing inspection contract; release does not claim physical deletion.
- Full workspace `pnpm -r typecheck`, `pnpm build`, token, map and diff
checks pass at `f6450f4739fc8141815b8b7c35fde22a655c5f90`. The broad
local `pnpm test:run` passed 24,899 tests and reported one existing
nested-clone test timeout at 15 seconds. The complete failing file then
passed 21/21 with the normal timeout; the exact case also passed on the
pinned earlier baseline. The broad runner stopped before its later
groups. No timeout or production workaround was added. Prior head
`f6450f4` has 53 successful checks, two conditional Storybook skips and
Greptile 5/5 with no inline threads. New workspace-reuse head
`fcb13399ec70f92f71bd8250081251dca3f48962` passes workspace typecheck,
full build, 86 scoped tests, maps and diff checks; Current-head CI has
53 successful checks and two conditional Storybook skips; Greptile is
5/5 with no inline findings. Deployed ordinary-turn reuse acceptance
passed as described below.

- **Hosted Stop proof:** the real GitHub issue-mention path used native
OpenCode, `openrouter/deepseek/deepseek-v4.1-flash-1017`, Daytona and an
exact low-trust task boundary. Normal UI Stop interrupted an active Bash
call. Native and shared acknowledgements matched the exact lease.
Automatic recovery saved exactly `STARTED\n` (8 bytes), with no finish
marker. Reload showed Stopped and saved work recovered. Only the
original cancelled run remained. Normal five-minute cleanup completed
its exact provider-destruction transition.
- **Limits:** the provider buffered command output, so the marker was
read after recovery. The approved local provider credential could not
inspect the hosted sandbox; its 404 is not deletion proof. Cleanup
success comes from the exact lease's platform destruction transition. An
earlier hosted stale instruction disappeared after rollout with
unchanged raw run/action data; that historical cause remains
unexplained. Original incident holds and publication receipts were
untouched.
- **Hosted handoff proof:** after QA deployed the combined candidate
containing `46b2e99`, startup admitted the previously saved GitHub
author reply without another comment, Retry or manual action. The new
native run used the exact original wake receipt and saved comment. It
completed once, committed an external-response wait, preserved the
stopped predecessor, emptied the queue and left the task In review. The
answer appeared in the original GitHub conversation. Workspace
finalization and the exact lease's normal destruction transition
succeeded.
- **Hosted workspace proof:** on the combined candidate containing
`fcb13399`, normal Retry preserved the original authenticated GitHub
request and completed a fresh native attempt. One later ordinary
same-head author reply then completed in the exact same workspace ID and
attempt directory, with no Retry/fresh directive. Its input tree digest
matched the Retry's finalized digest; final copyback preserved that
digest. The persisted assessment row and all five prior run records were
unchanged, exactly one new reply run completed, and the task returned to
In review with an empty queue and no live run. Both exact leases
completed normal verified destruction. This used real native OpenCode,
the exact DeepSeek/OpenRouter model and Daytona, without workspace-row
repair or a new remote marker.
- **Publication limit:** the workspace audit compares the persisted
assessment and run history. The ordinary reply exposed a separate
destination-summary fallback that changed the visible GitHub summary
despite the preserved assessment row. The publication track is repairing
that behavior; this proof does not claim the visible summary was
preserved.
- **Deployment boundary:** current-head CI/review and hosted same-source
Retry/ordinary-workspace reuse acceptance passed. The separate
visible-summary publication failure remains owned by the publication
track. Combined hosted UI confirmation of the native-agent Test path is
coordinated separately. Actual missing-proof UI/provider qualification
has passed in the isolated local instance above; prior hosted Stop and
same-input handoff proof remains separate. No merge or deployment is
performed by this pull request.

## Risks

Recovery state and termination receipts must match the exact source run
and allocation. Missing or foreign proof keeps the hold. The chat owner
must retain the original receipt and actor and recheck current
authority. Cleanup cannot grant authority or replay the stopped turn.
Existing native ownership, Stop, budget, permission and uncertain-effect
guards remain in place.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex, with reasoning,
repository tools, source editing and test execution. The context-window
size is not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 22:21:58 -05:00
Devin FoleyandPaperclip 832c44f26a fix: resume user follow-ups that reassign a task (#17821)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The execution control plane saves user messages while an earlier run
needs recovery.
> - A user comment can also assign a task back to its agent.
> - That update creates an assignment wake, but continuation accepted
only comment wake reasons.
> - The saved question could stay blocked after workspace recovery and
confirmed process cleanup.
> - This pull request admits assignment wakes that carry a valid,
undelivered user comment through the existing continuation checks.
> - The same rule applies to new messages and saved requests already
waiting for recovery.

## Linked Issues or Issue Description

**What happened?**

A human follow-up that also assigns a task back to its agent produces
`issue_assigned`. After a native run stops during handoff, the
continuation policy rejects that wake reason. The question remains saved
behind the execution recovery hold even after the workspace is recovered
and the old sandbox is destroyed.

**Expected behavior**

Deliver the saved human question once after the existing stop,
ownership, authority, and execution gates pass. Assignment alone must
not grant permission to continue.

**Steps to reproduce**

1. Finish task work by assigning it to a human for review. Let the
native run stop with `issue_reassigned` and retain its recovery hold.
2. Recover the workspace and confirm destruction of the old sandbox.
3. Post a new human question while assigning the task back to the agent.
4. Observe that the assignment wake stays deferred instead of delivering
the question.

Refs: #17288, #14156. These related changes cover legacy reassignment
and assignments without comments. This change covers a human comment
carried by an assignment wake behind a native or legacy continuation
hold.

## What Changed

- Share the comment-bearing wake classification between continuation
admission and saved-request recovery.
- Accept `issue_assigned` only through the existing persisted
user-comment validation and execution gates.
- Add database regressions for new and saved assignment wakes,
concurrent recovery, single delivery, and unchanged prior run results.
- Check that bare assignments, invalid authors and comments, changed
ownership, active execution, and pending approvals or questions retain
their holds. Cover native and legacy cleanup paths.
- Update execution semantics and both recovery maps.

## Verification

- Red: both new and saved assignment-with-comment cases stayed deferred
without a successor on the original code.
- Green: the final continuation suite passes all 284 tests. The four
companion recovery, retry, and queue suites pass another 208 tests.
- `pnpm -r typecheck` and `pnpm build` pass.
- `git diff --check`, `node scripts/check-maps.mjs`, and `node
scripts/check-module-boundaries.mjs` pass.
- Apex review is 5/5 on `56c9c2d90dcda55b3f760946c9aba6aee448c361`, with
no unresolved review threads. The only earlier finding concerned the
contribution rule against new source comments; those comments were
removed.
- Full `pnpm test:run` is still running locally. CI is waiting for the
`paperclip-public-pr-x64` runner fleet; the superseded workflow was
cancelled so the current head could proceed. No passing CI claim is made
yet.
- Live recovery: corrected one existing saved wake to the supported
comment reason. The normal server admitted one successor with the exact
saved question and prior-run context, then started real tool calls. This
verifies admission on the existing deployment; the new source change is
not deployed yet. The resumed turn later failed with a separate provider
terminal event whose error was null, followed by a workspace restore
failure. The task is blocked again on that failure. Its useful answer
has not been delivered, so end-to-end completion remains unverified.

## Risks

- Assignment wakes now reach continuation validation when they carry a
comment. The persisted comment must still belong to the task and
requesting human, follow the stopped run, and remain undelivered.
- The existing stop proof, cleanup, current assignment, approval, pause,
budget, and competing-execution checks remain effective. Regression
cases cover both native and legacy paths.
- No schema migration or data rewrite is required for saved requests.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 20:19:16 -07:00
Nicky Leach baec3abd67 Authorize background project Git with explicit Connector consent (#17798) 2026-10-26 17:22:49 -07:00
DottaandPaperclip 32ec84db2e fix(native): restore plugin checkpoints for same-run retries (#17814)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native sessions retain provider state across execution attempts.
> - A same-run retry can receive a replacement plugin task lease.
> - The executor loaded the old task checkpoint only for crash recovery.
> - An ordinary retry could fail its local authority check before
reading that checkpoint.
> - This change restores the checkpoint through the existing authorized
lease transfer.

## Linked Issues or Issue Description

**What happened?**

A native provider turn ended without its completion result. Paperclip
scheduled an exact-checkpoint retry on the same heartbeat run. The retry
acquired a new plugin task lease, then failed with
`runner_state_identity_mismatch: authority_indeterminate`.

The checkpoint restore branch required a `resume_dead_runner` restart
claim. Ordinary same-run retries have no such claim. A controlled
fixture with a retained remote checkpoint and no local lifecycle receipt
reproduces the error. The original controller file contents were
unavailable, so that part of the incident mechanism remains inferred.

**Expected behavior**

Load the retained plugin checkpoint after the existing policy proves the
lease transfer is safe. Keep the original run, session, and saved
control journal. Reject an unverified predecessor or a changed
checkpoint identity.

**Steps to reproduce**

1. Start a native session through a plugin task environment.
2. End its provider turn without a completion result and retain its
checkpoint.
3. Retry the same run on a replacement task lease without a restart
claim.
4. With no local lifecycle receipt, observe the authority error before
the checkpoint read.

**Paperclip version or commit**

Reproduced against source `507dc70be26c191e372f09e58dc0965e73bf8f57`.

**Deployment mode**

Native Runner with a plugin task environment. The observed provider used
ACPX Claude. The controlled executor fixture uses the shared native
boundary.

Related work: #17439 concerns recovery after controller replacement.
This fix uses the existing checkpoint contract and does not depend on
that PR.

## What Changed

- Restore prior plugin state for an ordinary same-run attempt when its
lease changes.
- Keep the existing company, agent, workspace, retained-state, and
termination checks.
- Extend executor regressions for ordinary retries, mismatched
checkpoints, and missing stop proof.
- Exercise the same-run checkpoint read through the database-backed task
API.
- Document the recovery rule and verification recipes.

## Verification

- Failing before: the ordinary retry reproduces
`authority_indeterminate`. Both new denial cases also fail because the
old branch never reaches the transfer policy.
- Passing after: all six focused checkpoint cases pass. The saved
control journal stays byte-for-byte unchanged. Rejected cases do not
construct a provider backend.
- `pnpm -r typecheck` passes.
- Map and module-boundary checks pass.
- All 858 executor, database lease-authority, plugin task, and ownership
tests pass. `pnpm build` passes.
- The broad local `pnpm test:run` attempt did not complete. It hit a
20-second timeout in the existing historical workspace-recovery HTTP
Retry case. That exact case then passed in isolation on the unchanged
head. The broad local attempt was stopped after the full CI matrix
passed; it is not counted as a local pass.
- Greptile reviewed current head
`5bc11fa978ab87d3d9c5d575fa9666185aaafc2c` at 5/5 with no actionable
findings. The full current-head CI matrix passed on attempt 2: 55 checks
passed, no pending or failed checks, and two expected Storybook jobs
skipped.
- The first broader local attempt could not bind embedded PostgreSQL
inside the sandbox (`EPERM`). It was stopped and restarted with loopback
access. This was a setup failure, separate from the observed red
regression.
- The first CI attempt failed two existing checks: the process-adapter
signoff happy path exhausted its run wait budget, and the workspace
export scheduler did not reach `complete` within 20 seconds. Both tests
pass in isolated local runs on the unchanged head. Both failed shards
passed on their single rerun without code changes. The initial failures
remain recorded. Their timing cause is not proven by the later passes.
- Live acceptance at the fixed revision has not run. The hosted
workspace still serves the earlier release. No deployment or retry of
the original task is claimed.

## Risks

The new checkpoint read runs only for same-run plugin recovery with a
replacement lease. Missing termination proof, changed scope, or a
changed Runner identity still stops execution. The lease resolver owns
these checks. The fix does not replay tools or change retry budgets. A
turn that omitted its completion result still needs the existing bounded
continuation to finish useful work.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The runtime does not expose a more specific backend model ID
or context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 18:01:55 -05:00
Nicky LeachandPaperclip 835966dec8 Prepare agent-owned environments during hiring (#17761)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/1/changes/paperclip/1
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages agents and their execution environments.
> - New agent setup saves an inactive agent before model connection
tests.
> - Some plugins need that agent to prepare its execution resource.
> - The wizard tested without the agent ID, while the setup hold
prevented preparation.
> - Environment changes also discarded the selected model account.
> - This change prepares the saved draft during setup and keeps normal
execution held.
> - Users can test the prepared resource before they finish hiring.

## Linked Issues or Issue Description

**What happened?**

An agent-owned plugin environment could not acquire a test lease during
hiring. Changing environments also returned the user to Connect and
cleared the selected account.

**Expected behavior**

Keep the selected account, invalidate its test, and prepare the saved
agent resource in the background. Test that same agent before finishing
setup.

**Steps to reproduce**

1. Start a new Claude or Codex agent and select a saved account.
2. Change to an agent-owned plugin environment.
3. Try to finish setup or reconnect the account.

Related: #17750 defers probes until after hire submission. This change
implements preparation during the wizard instead. The related PR search
and ROADMAP review found no other implementation of this setup
preparation path.

## What Changed

- Add the optional `requiresAgent` driver declaration. Require agent
lifecycle participation when it is set.
- Prepare saved drafts on creation or environment changes. Keep the
setup hold and wait in `verifying` without background verification
scans.
- Bind tests to the saved agent. Return a warning without allocating a
lease when the required agent is absent or still preparing.
- Preserve the account and configuration step when the environment
changes. Save the selection and invalidate the old test.
- Show active preparation and support authorized retries. Keep approval,
company, budget, and normal task admission controls.
- Document the contract and cover lifecycle, lease, manifest, and wizard
behavior.

## Verification

- Server and UI TypeScript checks passed.
- 112 wizard and setup helper tests passed. The shared manifest suite
passed.
- 123 lifecycle, policy, lease, and environment-test API cases passed
after the approval-gate fix. The diagnostic and driver suites and all 80
agent adapter route tests also passed.
- Token gates, module boundaries, map validation, and whitespace checks
passed.
- All 66 lifecycle/policy cases passed after the stopping-draft
permission fix. The new real-DB route case verifies creator success,
other-creator denial, and refusal to complete a hire while stopping.
- Full workspace typecheck and build were attempted. Both stop at the
unchanged Rust Runner step because Cargo is not installed on this host.
- CI on 43be3c93d passed all automated checks, including full test
shards, typecheck, build, Rust checks, browser suites, and canary
checks:
https://github.com/paperclipai/paperclip/actions/runs/40368174530.
- The full local repository test command was started. Two unchanged
workspace tests assume Git's initial branch is master; this host
defaults to main. Both fail in isolation under the host default and pass
with process-scoped init.defaultBranch=master. The broad run was stopped
after those confirmed fixture failures; CI supplies the full clean
check.
- Early new-test failures were fixture collisions and an unscoped sweep
assertion; the fixtures and assertion were corrected. One route-suite
load raced with SDK output regeneration; rebuilding first and running
the suite afterward passed.
- Initial CI exposed a route mock missing the new prerequisite lookup.
The fixture was updated and a real HTTP no-lease case was added; all 54
cases in that route suite pass. Security review identified allocation
before required approval; the new approval gate and its tests address
it.
- CI on 50b5a08af reported 32 of 33 expected calls in the unchanged
cleanup-history scheduling test. Its isolated case passed locally
without cleanup-code changes; the original failure remains recorded and
the final CI run passes on the current head.
- Standard Greptile reviewed 43be3c93d at 5/5. A subsequent deeper
review identified runner selection, stale detail reads, error retention,
and test file size issues; 70343387b addresses all four with resolved
threads. Standard review returned 5/5 on that commit and again on
rebased head fda42c5ab. The rebase preserves master's new managed
environment skill declarations alongside requiresAgent. Full CI on
fda42c5ab passes: 55 successful checks, two intentional skips, no
failures. Run:
https://github.com/paperclipai/paperclip/actions/runs/40405121641.
- After those fixes, 133 UI tests and 61 lifecycle/policy cases pass;
all eight focused UI regressions fail against the previous
implementation and pass with the fix. Token, map, and whitespace gates
pass. The stale-read fixture initially omitted the setup URL because
navigation is mocked; following the URL activates the real detail query
and reproduces the race.
- UI TypeScript passes. This host's server dependency links now point to
a separate scratch checkout lacking requiresAgent, so the ordinary
server check reports that missing property. A no-emit check pinned to
this branch's shared declarations passes; it disables declaration
generation and supplies explicit local type roots. The first temporary
configuration lacked those type roots; the corrected configuration
passes. CI remains the full workspace verification.
- After rebasing onto 8373d7867, all 133 UI, 61 lifecycle/policy, and 44
manifest cases pass again, as do UI TypeScript, token, map, and
whitespace checks. The server no-emit check now hits three mismatched
SDK/Runner declarations from the scratch dependency links; these are
outside this change. Full CI builds the complete dependency set.
- Review cycle: the first Apex review scored 3/5 with four findings. All
were fixed together, the branch was rebased to resolve a schema
conflict, full CI and standard Greptile passed, and a second Apex review
returned 5/5 on fda42c5ab with zero new comments. All six review threads
are resolved, and the PR is conflict-free. Review:
https://github.com/paperclipai/paperclip/pull/17761#issuecomment-6422635718.
- No live provider resource was created and no deployment was performed.

## Risks

Plugins must opt in and ship a compatible declaration. Companies
requiring hire approval keep drafts paused and defer allocation and
verification until approval. Other companies prepare drafts during the
wizard under their existing agent-creation authority; the setup hold
still blocks ordinary work. Preparation uses existing lifecycle
ownership, retry, and cleanup paths. The open wizard polls only while
preparation or stopping is active. No database migration is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact serving model ID and context window size are 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 described the issue in-PR using the bug report fields
- [x] I have not referenced internal or instance-local issues or links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run the targeted tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented the risks
- [x] All Paperclip gates are green — 55 successful checks and two
intentional skips on fda42c5ab
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 15:21:47 -07:00
DottaandPaperclip 718c73dafe fix(native): require verified remote process exit receipts (#17799)
Require fresh ESRCH or an exact matching zombie generation before treating a remote Runner as stopped. Preserve uncertain ownership through adoption and transport close, retire local controller resources after failed close, and check Node before remote launch.

Bind the shared transport change in Copilot profile 62 while retaining historical profile decoding. Add red-green process, permission, launch, adoption and cleanup regressions.

Thanks to @hsm-lv for the original investigation in #17073.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-26 21:39:04 +00:00
DottaandPaperclip 8373d78679 fix(recovery): register missing native preservation on Retry (#17800)
## Thinking Path

> - Paperclip lets people manage agents and their saved work.
> - Native runs can leave a prepared remote workspace after a control
deadline.
> - The deadline repair in #17788 records preservation for future
failures.
> - Older failed runs can still have an active lease without a
preservation owner.
> - Retry correctly refuses another executor, but nothing can finish the
missing preservation.
> - This pull request registers the exact prepared source through the
existing recovery services when the user retries.
> - The bounded maintenance worker can then stop the provider and save
its files before normal admission continues.

## Linked Issues or Issue Description

**What happened?**

A historical failed native run has a prepared workspace and an active
retained allocation. It has no workspace preservation record. Ordinary
Retry cannot prove that the old executor stopped and has no maintenance
owner to produce that proof.

**Expected behavior**

A deliberate Retry registers missing preservation for the exact unowned
source. Existing recovery proves termination and saves the files.
Existing admission then checks current user authority, effects, pause
and budget gates before one successor can enter the queue.

**Steps to reproduce**

1. Persist a failed native run with a prepared workspace, an active
lease and a terminal, unowned finalization.
2. Omit the workspace preservation record, as an older deadline handler
did.
3. Call the normal task Retry route. Before this fix, preservation
remains absent and Retry cannot continue.

**Paperclip version or commit**

The regression fails on `46de15ff4b99bbee59c38f32f4f30b80ad5bbd24`,
which already includes #17788.

Related: Refs #17788 (future deadline failures), #17741 (committed
recovery wakes), #17733 (connected Retry authority). #17773 adds source
diagnostics and does not repair this missing registration.

## What Changed

- Use native workspace preservation inside the existing issue-locked
Retry transaction. A live finalization owner remains held.
- Adopt a valid unowned preservation obligation through the existing
bounded maintenance service. Bind it to the deliberate Retry intent
without resetting an active generation.
- Add real PostgreSQL regressions for exact, mismatched and owned
sources. Verify that registration cannot create a termination receipt or
a successor.
- Exercise the HTTP route, worker, real temporary file merge and queue
admission with the stop reply held. Duplicate requests admit one queued
turn after preservation.
- Extend connected GitHub and Telegram Retry coverage for missing
historical preservation. Document the contract and access boundaries.

## Verification

- Red: the new historical-state regression fails on the base commit
because `workspaceRestoreRecovery` remains absent. The mismatched and
owned negative controls pass.
- Green: the three focused historical-state cases pass with the fix
against isolated local PostgreSQL 17.
- The local HTTP journey restores saved files and retains newer host
edits. It admits no successor while the provider stop reply is held. It
admits one successor after verified preservation. The real GitHub and
Telegram admission paths wait behind that recovery.
- `pnpm -r typecheck`, `pnpm build`, `node scripts/check-maps.mjs` and
`git diff --check` pass.
- Green: 152 tests across four relevant suites, including all connected
Retry safety cases. The six new cases pass again on final head
`b8900801a3181fa673ea45f1129f968bbb08d1fd`.
- Final-head GitHub checks: 55 successful, two intentionally skipped
Storybook checks, and one neutral Paperclip bot review. Greptile is 5/5
with no unresolved threads. The Paperclip bot stopped before finishing
and supplied no approval.
- The full local command imported an earlier fixture revision before its
assertions were corrected. It reported those two stale connected-fixture
assertions and later hit the host PostgreSQL semaphore limit again. It
was stopped after final-head CI completed. It is not counted as a full
local pass; the complete CI test lanes passed on the final head.
- The first local rerun hit the Mac PostgreSQL semaphore limit before
assertions. Verification moved to an isolated disposable PostgreSQL
container. Early assembled fixtures also exposed the existing
destruction-cleanup gate; the retained-workspace fixture now uses its
actual `keep_running` disposition. This fix does not weaken cleanup.

## Risks

- Retry now registers maintenance for historical native failures. Exact
descriptor, allocation and coordinator checks remain owned by the
existing preservation service. Physical recovery still requires its
existing exclusive owner and provider stop receipt. Registration alone
grants no execution authority.
- No database migration or provider protocol changes. No model, trust,
assignment, retry-budget or external identity changes.
- Local recovery uses real database, filesystem, HTTP, worker and
admission code. Only the provider lifecycle boundary is simulated. No
hosted allocation or live model turn has been verified for this new
change.
- The workspace recovery test file crosses 1,000 lines because this case
shares its real database, filesystem and assembled route fixture.
Keeping it there avoids duplicating that fixture or extracting unrelated
production behavior.

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 16:22:36 -05:00
DottaandPaperclip 2ee36a4c0a test: add chat feature scenarios and real task workflow evals (#17794)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat lets a person assign work through a conversation.
> - Feature and API maps do not prove that a natural request produces
the right saved result.
> - Product E2E already owns isolated fixtures, browser runs, evidence
and cleanup.
> - This pull request adds a chat scenario catalog and two real task
workflows in that framework.
> - Independent checks verify the task, its author, the saved output and
the reply in chat.
> - The benefit is a small executable foundation for broader chat
coverage.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

It adds real task creation and delegation coverage for Agent Chat.

**Current behavior**

Existing maps describe features and agent access. Existing chat evals
cover specific protocols and handoffs. They do not connect a broad
human-request catalog to independent saved-state checks.

**Proposed behavior**

Keep 244 planned scenarios across 35 feature areas. Promote two requests
into the explicit-only `chat-features` suite. One saves a backlog task
without starting work. The other delegates an announcement and returns
the saved result to the original chat.

**Reason and benefit**

A successful tool call or confident reply does not prove the requested
result exists. These evals check public API state, attribution and
browser access after a real model run.

**Breaking changes**

No API or data schema changes. Chat instructions now require actual
relative task links. The local E2E private-state scanner recognizes
Codex account ownership metadata while continuing to reject credentials
and model-visible identity leaks.

**Additional context**

Related prior work: #13969 and #13762. This improves verification of the
existing Agent Chat roadmap item. It does not add a new core product
feature.

## What Changed

- Add YAML scenarios with capability IDs, starting context, user
requests and expected outcomes. Validate all area files against their
schema, global ID uniqueness and exact feature-map capability coverage.
- Add two local native Codex subscription cells. Send the exact catalog
request once through Chromium.
- Seed only prerequisites through public APIs. Use shipped agent
instructions and explicit disposable budget policies for unpriced
subscription usage.
- Check task ownership, creation audit, no premature execution, current
worker-authored output, automatic completion delivery and usable links
after reload.
- Keep private Codex account ownership metadata distinct from bearer
credentials. Scan rollout message content, all tokens and published
evidence as before.
- Teach normal chat instructions to use relative task links instead of
invented hosts. Update tests, maps and the runbook.
- Repair existing E2E contract drift: include the active Copilot
identity in the image digest and update Pi profile expectations. Keep
global catalog cardinality in its owning catalog test.

Product E2E owns the new flow and grader. Its existing launch and report
paths remain in use. The shared scanner change is limited to
owner-private temporary Codex runtime metadata. Other callers retain the
full secret scan. No UI, endpoint, schema or permission behavior
changes.

## Verification

- `node scripts/check-maps.mjs` passed: 35 areas and 191 capability IDs.
- Product E2E typecheck and focused tests passed before rebase: 225
Vitest tests and 137 Node tests. Conversation service tests passed
40/40. Five existing runner turn-binding regressions passed.
- Historical live measurement used real Chromium, server, database and
native Codex with no automatic retries. The initial same-definition
batch passed 5/6 cells. Backlog passed 3/3; delegation passed 2/3. One
CEO startup failed because the runner did not receive a provider turn
identity. The cause is unresolved.
- An unchanged follow-up passed delegation three times and backlog
twice. Combined evidence is backlog 5/5 and delegation 5/6. Each attempt
passed cleanup. Later passes do not erase the earlier failure or prove a
runner repair.
- Earlier failed revisions exposed an invented task hostname, private
account metadata false positives and missing funding for unpriced
subscription usage. Those led to the specific changes above; the failed
records remain retained locally.
- The runbook records campaign identifiers and definition provenance.
Generated result artifacts are not committed. Historical live results
predate this branch rebase; fresh PR-source live evidence and final
validation are recorded below.
- Full workspace typecheck and production build passed on the rebased
branch. Product E2E typecheck passed.
- The full Product E2E support suite first reproduced four baseline
failures: two missing active Copilot image-identity inputs and two stale
Pi/catalog expectations. The narrow contract fixes above resolved them.
The full rerun passed 4,282 Vitest tests plus 137 Node tests, with two
skipped. Image checks verify mutation changes the hash, unchanged input
stays stable, and an input closure without Copilot is unaffected.
Original failed logs remain retained.
- The repo-wide local Vitest run has reported two failures in unchanged
service files. The Workspace connection test passed an isolated recheck
and its full file passed 469/469 unchanged. The recovery test hit a
15-second timeout; its full file passed 89/89 unchanged. The run later
hit explicit PostgreSQL `semget` resource exhaustion and was interrupted
after those observed failures; no final aggregate counts or full local
pass are claimed. Its complete available log is retained. No assertion
or timeout was weakened. Matching remote server CI passed on the same
source.
- On clean PR head `39ad80b523ce194c90aafafd077d48dd9a36b4c5`, backlog
passed in `local-2026-10-26T19-24-13-014Z`. The parallel delegation
fixture failed during PostgreSQL initdb, before browser or model
execution; its failed cleanup grade is retained. A disposable standalone
initdb probe then passed. No semaphore sets or kernel settings were
changed before that probe/recheck. After confirming no remaining fixture
process, its private temporary files were removed.
- One separate delegation recheck passed in
`local-2026-10-26T19-29-24-800Z`, with one attempt, zero automatic
retries and successful cleanup. Both passing current-source cells use
definition
`3f2c9ba2d03e3dcddde47ddab3b43bc52de977f25e256fceae0a24c9128e204b`. The
earlier bootstrap failure and the historical provider startup failure
remain distinct. These local results omit automatic source-SHA metadata;
the clean checkout SHA is recorded here from the execution session.
- The later broad local run reported `could not create semaphores: No
space left on device`. A bounded cleanup removed 32 current-user
PostgreSQL sets with 17 members, marker 537, a dead recorded creator and
zero waiters. No live process or kernel limit was changed by that
cleanup. The test process group was subsequently stopped; no broad rerun
is planned. This direct later resource failure does not prove the
precise cause of the earlier live initdb failure.
- Review follow-up adds only static catalog validation and documentation
of the existing five-minute journey bound. The executable definition is
unchanged. Focused catalog/oracle tests passed 28/28; no redundant live
run is claimed.
- Final head `30fcb36ac9ae1f0270a589dbfafcec91ca6a03f3` passed all
required and underlying CI checks in [run
40391402347](https://github.com/paperclipai/paperclip/actions/runs/40391402347),
including `ci / verify` and `ci / e2e`. Greptile and Paperclip Review
both scored this head 5/5, with all review threads resolved. The static
follow-up leaves every executable definition input byte-identical to the
live-tested source at `39ad80b`.

Normal squash auto-merge is enabled. Actual merge is pending eligible
code-owner approval for the owned dependency manifest; no protection is
bypassed.

## Risks

- Live model behavior can vary. One missing turn-start event remains
unexplained; this PR does not claim provider reliability or broad
catalog qualification.
- Subscription costs are unpriced. Explicit fixture funding admits that
usage. Run counts and deadlines remain bounded, but the dollar limit
cannot cap unknown cost.
- Account identity exceptions apply only to known private Codex runtime
files. Token reuse, unknown files and model-visible rollout content
remain blocking findings.
- Deterministic checks establish saved state, output structure, required
brief facts and access. They do not score all prose quality. Initial
samples also require human inspection.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code execution, browser and
repository tools. The precise model revision and context window are not
exposed to this session. Live eval agents used `gpt-5.6-sol`; that is
the evaluated model, not a claim about the authoring model.

## 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 local tests; focused suites pass and the interrupted
full-run failures are documented above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 16:19:39 -05:00
DottaandPaperclip 5061ab7b35 perf(ui): speed up task and inbox cold opens (#17756)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task lists and inboxes are the main entry points to that work.
> - Cold opens fetch overlapping task lists, task descriptions, and run
details before useful rows settle.
> - Independent responses can insert rows above content that a person
has started to read.
> - This pull request loads a small task index first and adds details
only for visible rows.
> - It keeps row order and geometry stable while those details arrive.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Cold opens of Tasks and Inbox, including the shared navigation badge.

**Subsystem affected**

Server list reads, shared response contracts, and the React UI.

**Current behavior**

The badge fetches full task bodies. Mine fetches several overlapping
lists. Historical diagnostics and row metadata add work before the first
useful list. A fast failed-run response can appear before task rows,
then move down when tasks arrive.

**Proposed behavior**

Load the selected inbox source and its required context together. Use an
index without task descriptions or recovery diagnostics. Fetch
diagnostic details for up to 50 visible rows. Keep skeletons, recovery
indicators, external status, and live metadata in fixed space.

**Reason and benefit**

Reduce work on a cold open and prevent loading-induced row movement. On
the same 100 local fixture tasks, the compact response was 262,441
decoded bytes and the index was 110,909 bytes. This comparison excludes
compression and is not a page latency benchmark.

**Breaking changes**

Existing full and compact responses remain available. New index/row
projections are opt-in and marked as partial data. Mine keeps its
existing most-recent-100 display limit, now selected on the server.
Existing filters and group preferences remain in the client. No database
migration.

**Additional context**

Refs: #17593. Related: #13095, #17428, #13803. This change addresses
collection overfetch and layout stability. It does not replace the
blocked-inbox query work or the database activity-index work.

## What Changed

- Add authorized index and row projections, with bounded task and parent
ID batches.
- Replace badge list downloads with unread IDs and aggregate counts.
Preserve actor privacy, dismissals, and local archive behavior.
- Load only the selected inbox source, plus bounded parent and
failed-run context. Return only relevant failures from the bounded run
window.
- Batch hierarchy reads, including at most one authorized child per
collapsed parent in one request. Collapsed markers do not consume the
expanded row budget, and partial descendant counts are not shown as
totals. Enrich visible rows without replacing membership, ordering,
titles, or read state.
- Reserve row geometry on desktop and mobile. Reveal the initial inbox
only after its sources settle. Preserve legacy task-list reads.
- Start collection module downloads during access checks. Keep partial
rows out of the task-detail cache.
- Keep ETags and concurrent request sharing for the new projections, but
skip the short server response TTL so archive undo sees fresh state.

## Verification

- On final head `ef6afb2a56`, the full CI workflow passed, including
build, typecheck, server/workspace/runner suites, and all eight browser
shards. A server shard reported **1,489 passing tests** before runner
shutdown canceled the job; its single infrastructure retry passed. Both
Greptile and Paperclip Review are **5/5**, with zero unresolved review
threads.
- The optional external **Entire Gates** check remains `unassessed`
because it has no active assessed Change for this comparison. Entire is
not set up in this checkout. The repository ruleset requires `ci /
verify` and `ci / e2e`; both passed. No gate configuration was changed.

- Passed workspace typecheck after the final API batching change. The
full production build also passed on the final commit; the exact-retry
E2E run built the shipped UI.
- Passed token gates and map validation. The final batch-preview pass
has 91 passing route/hierarchy/component tests, including privacy,
request bounds, 30 collapsed parents in one read, and a 120-child parent
alongside a sibling.
- Passed the 166-test focused UI/inbox/badge run, 47 additional UI
regression tests, and 34 issue-list route tests. The latest regressions
cover low-trust agent badge IDs, cold company selection, 30
description-only Mine matches with archive actions, retrying optional
row details, and collapsed/expanded siblings.
- The full local `pnpm test:run` spanned the rebase and reported
failures in five suites before it was stopped; it is not claimed as a
complete pass. A fresh serial rerun of all five suites passed
**452/452** tests (tool gateway, native resume, project repositories,
workspace recovery, and runner selection). Full current-commit coverage
is checked by CI.
- Real browser: delayed index and row-detail responses on Tasks and
Mine. The first placeholder and first row had the same origin and
44-pixel height. Twelve rows on each page had zero position, height, or
title-width change after recovery details arrived.
- Real browser: reviewed long titles and recovery status at a 390 by 844
viewport. Task text stays on one line and recovery uses a compact
indicator.
- Three fresh document loads per page on final commit `260893bf92`, with
HTTP cache retained on a warm local development server: Tasks
1.031–1.190 seconds; Mine 0.999–1.193 seconds. Browser-control overhead
is included. These values must not be compared directly with staging
latency or the earlier local samples taken during a full test run.
- The browser archive test exposed stale results after Undo. The new
projections now bypass the server TTL; immediate-mutation regression
tests pass. The final browser retry passed: Archive followed by Undo
restored exactly one row and the badge count.

- CI exposed a hook-order crash when company selection resolved after
the first inbox render. The hook now runs before the empty-company
return. All seven affected exact-retry and legacy-continuation browser
scenarios pass locally after the fix.
- Real browser review regressions: 97 description-only source matches
retained Archive actions; deliberately failed optional row reads
displayed a retry notice while all 12 observed row positions and heights
stayed unchanged. Retry restored the recovery indicator. Network fault
injection was removed.

- The final production build and workspace typecheck passed. Final
focused verification passed 153 UI/helper tests and 26 heartbeat privacy
route tests. Final review regressions cover newer diagnostics arriving
during the index read, reloading diagnostics when the same task ID
changes version, optional source failure/retry without hiding available
rows, and required external-status filter failure. The latest-failures
route test verifies bounded selection, agent filtering, success
suppressing an older failure, and private-run redaction.
- Real browser: deliberately failed the run source, then retried it.
Twelve available task rows kept the same position and 44-pixel height
before, during, and after retry. No loading skeleton replaced them.
Fault injection was removed.
- Hierarchy review decision: the cold-open barrier stays because
inserting ancestors or expanded children after revealing index rows
would cause layout shifts. Existing hierarchy context now survives
subsequent requests, with a regression proving a new ancestor read does
not blank the list. The bounded recursive tree read can still add
latency for unusually deep expanded trees.

- Tasks now handles a failed external-status filter with an explicit
error and Retry, suppressing a false empty state. All 52 Tasks component
tests pass, including failure-to-success retry. One existing large-tree
test timed out while workspace typechecking ran concurrently; the whole
component suite passed when rerun without that competing work. Workspace
typecheck, the full production build, and token gates passed for this
fix.

## Risks

- Saved filters and grouping still operate on the existing bounded
collection. This is not a new global server pagination model.
- Fixed row slots reduce available title width. Long titles remain
accessible through task navigation.
- Recovery and related diagnostics arrive after core rows. Their
responses cannot replace ordering fields, and stale versions are
rejected.
- Index/row requests now revalidate against current data instead of a
short server TTL. They still share concurrent reads and use ETags.
- This has not been deployed by this pull request. Staging latency must
be measured after deployment under comparable conditions.

## Model Used

OpenAI Codex, GPT-6 family. The exact runtime model ID and
context-window size are not exposed in this session. Used code editing,
terminal execution, and real-browser diagnostics.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 14:29:20 -05:00
DottaandPaperclip 46de15ff4b fix(recovery): preserve native workspaces after control deadlines (#17788)
## Thinking Path

> - Paperclip lets people manage agents and their saved work.
> - Native runs can prepare a remote workspace before provider
execution.
> - A finalization deadline can stop a run outside its normal exception
path.
> - That handler marked the run failed without recording its prepared
files for recovery.
> - Retry then waited for a lease whose preservation had no durable
owner.
> - This pull request records the exact source in the deadline
transaction through the existing recovery service.
> - Existing containment and file recovery can then settle the source
before another executor starts.

## Linked Issues or Issue Description

**What happened?**

A native run failed at its control deadline with a prepared workspace
and no accepted result. Its environment lease remained active. The run
had no workspace preservation record. A saved Retry waited for remote
cleanup without a preservation operation to finish that cleanup.

**Expected behavior**

Record unfinished files when the deadline marks a native run failed. Use
the existing stop-and-retain worker. Keep accepted results, exact source
binding, and current task ownership authoritative.

**Steps to reproduce**

1. Persist a native run with a prepared workspace, an active lease, and
an expired control deadline.
2. Reconcile the deadline twice.
3. Inspect the source lease and the run's workspace recovery record.

**Paperclip version or commit**

Reproduced against `a67a18c171816b097f46eae78fc58c7e55c9c565`.

**Deployment mode**

Hosted native Runner with a remote sandbox. The regression uses real
local PostgreSQL and no provider mocks.

Related: Refs #17741 for committed Retry delivery. Refs #17073 for
remote process-exit verification. This change records file preservation
after a deadline; it does not change either policy.

## What Changed

- Call the existing native workspace preservation service in the
transaction that fails an abandoned run.
- Preserve files after reassignment without changing the current task
owner or state.
- Add real-database cases for prepared, finalized, mismatched,
reassigned, and accepted-result states. Repeated reconciliation retains
one source obligation and creates no successor.
- Document the deadline behavior and its existing access boundaries.

## Verification

- Red: on unchanged production code, the prepared-workspace case failed
because its recovery record was null. Finalized and mismatched controls
passed.
- Green: all 10 deadline reconciliation tests pass. The existing native
workspace recovery suite passes all 48 cases.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- Map checks, module-boundary checks, and `git diff --check` passed.
- Current-head CI passes on `23bf2aa4b50d2c4b74a9ee2ee47034ae542d25c2`:
all GitHub Actions CI lanes, including grouped/serialized tests, Runner
verification, typecheck, build, E2E, and Canary Dry Run, succeeded. Two
Storybook-only checks were skipped. Greptile is 5/5 with no findings.
Superagent Security Scan also passed. Entire Gates reports passing
checks/findings and fails only because no reviewer has approved trail
#10.
- The first server shard 11/12 attempt passed all 1,750 assertions but
reported an unhandled early process-exit rejection in the unchanged
workspace-exposure fixture. Its focused local suite passed (28 passed, 3
skipped); one CI rerun passed.
- Full local `pnpm test:run` was started, then interrupted after the
complete CI lanes passed to avoid duplicate work. No full local suite
pass is claimed. Local targeted tests, typecheck, and build passed.
- On the affected staging instance, the existing deployed preservation
helper registered the exact failed source. Normal Retry then drove
actual sandbox stop, file recovery, and a persisted successful recovery
receipt. A successor reached a separate remote process-fingerprint
failure before provider execution. The automatic deadline change is not
deployed; task execution recovery remains incomplete.
- Initial local setup attempts did not reach product assertions: skipped
dependency lifecycle scripts left native PostgreSQL library links
absent, and the restricted shell blocked localhost binding. The
package's link hydration and an authorized isolated listener resolved
those setup prerequisites. One new negative-control assertion also
required null-safe access; the final red run retained only the intended
behavioral failure.

## Risks

- File preservation must not certify provider termination. The existing
stop receipt, source binding, copyback, and admission checks remain in
force.
- Preservation failure rolls back the deadline transaction, leaving its
durable deadline eligible for another bounded attempt.
- Reassignment preserves old files without changing the new owner's
task. Accepted results retain their current finalizer.
- No schema, credential, provider, or polling change. Historical failed
runs still require scoped recovery; this patch does not replay them.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (targeted suites; full
local suite interrupted after CI passed)
- [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 (CI lanes pass; external Entire
reviewer-approval gate remains pending)
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 14:18:53 -05:00
DottaandPaperclip 063a498b54 Bound native OpenCode assigned-tool catalog projection (#17740)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents use assigned connection tools through a governed
gateway.
> - OpenCode received the gateway catalog directly, outside the bounded
server tool projection.
> - A large catalog can exceed a provider grammar compiler's capacity
even when it fits the transport limits.
> - Synthetic requests reproduced the Fireworks grammar timeout on the
configured DeepSeek model.
> - This pull request gives OpenCode two assigned-tool discovery and
call schemas through the existing server relay.
> - The gateway keeps the same grants, validation, approvals,
revocation, and audit rules.

## Linked Issues or Issue Description

**What happened?**

A native OpenCode run could fail during provider grammar compilation
before its first assigned-tool call. OpenCode advertised the full
assigned gateway catalog. A synthetic catalog of 741 tool schemas
reproduced `Grammar processing took too much time` on Fireworks through
OpenRouter with `deepseek/deepseek-v4.1-flash-1017`. The same model and
backend accepted a compact two-tool discovery/call catalog. This
reproduces the mechanism; it does not replay a historical private
request.

**Expected behavior**

Assigned-tool discovery must keep provider grammar size bounded. Every
call must retain the run's original gateway binding and permissions.

**Steps to reproduce**

1. Give a native OpenCode run a large assigned connection catalog.
2. Use a provider that compiles tool schemas into a constrained output
grammar.
3. Observe the full catalog in the provider tool surface before this
change.
4. After this change, observe only `paperclip_search_assigned_tools` and
`paperclip_call_assigned_tool` for assigned tools. Discover and call a
permitted tool through its pinned alias.

**Paperclip version or commit**

Source checkout based on current `master`.

**Deployment mode**

Native local or sandbox execution with OpenCode 1.18.34.

Related work: Refs #14258 (discovery paging), #16678 (local adapter MCP
launch), and #17688 (gateway capability advertisement). This change
covers native OpenCode catalog projection.

## What Changed

- Route native OpenCode assigned tools through the existing server-owned
authenticated relay.
- Use bounded discovery/call schemas for OpenCode, including small
catalogs. Preserve transport capacity checks.
- Keep assigned gateway credentials on the controller. Ignore gateway
and credential values in tool arguments.
- Preserve exact declared MCP operation names through admission and
driver dispatch. Resolve transport prefixes only against the closed
catalog. Reject unknown or shortened names.
- Refresh former OpenCode direct-catalog and shortened-name checkpoints.
Keep the existing fingerprints for other providers.
- Add local and remote wiring, catalog capacity, alias, scope,
work-mode, approval, and revocation tests.
- Allow the native test files to use a validated dedicated external test
database when embedded PostgreSQL is unavailable.
- Document the assigned-tool execution contract.

- Bound OpenCode discovery pages to 32 KiB and large-schema chunks to
16K characters. Keep other harness budgets unchanged.
- Test medium pages and escaped large schemas through the actual HTTP
MCP bridge on the explicit Runner testing surface.

## Verification

- Red before the catalog fix: OpenCode did not create the server relay,
and forced compact delivery advertised 1 or 741 direct schemas.
- Red before the alias repair: HTTP MCP changed declared operation
names, and the driver sent `search_assigned_tools` instead of the
authorized `paperclip_search_assigned_tools`.
- Current repair tests: 112 OpenCode/proxy tests pass, plus one actual
Rust/proxy/HTTP MCP regression. Two checkpoint regressions fail with the
former scoped revision and pass with the new revision. Other providers
keep their prior fingerprints.
- The combined QA candidate with this exact PR head passes all 916
native tests and all 113 transport tests on supported Node 24.22. An
earlier Node 26.4/macOS run passed the 113 assertions but had an
uncaught networking error. That non-clean run remains recorded; its
stack matches [the upstream Undici
defect](https://github.com/nodejs/undici/issues/5544). No production
workaround or error suppression was added.
- `pnpm -r typecheck`, `pnpm build`, and `git diff --check` pass on
`bc41ba72be2195eabeb0d7727227ee0cd02e8532`. The maps structural check
passes.
- The local `pnpm test:run` attempt stopped after host embedded
PostgreSQL initialization failures. The relevant database suites pass
with isolated PostgreSQL 18. All repository CI gates, including
aggregate `ci / verify`, pass on the current head.
- Synthetic live provider comparison: 741 invented schemas produced the
exact Fireworks grammar timeout in 20.9 seconds. Two compact invented
schemas produced a discovery call in 585 ms on the same model and
backend.
- The first hosted QA attempt exposed the alias failure described above.
On the patched source, a real local Rust runner → proxy → OpenCode
1.18.34 → exact DeepSeek smoke completed discovery, one synthetic
gateway read, and `paperclip_finish`, then emitted `turn/completed`. It
used the production compact projection and unchanged Rust allowlist.
- Two earlier local smoke attempts exposed missing terminal authority
and completion-contract fields in the smoke harness. Those failures
remain recorded. The corrected ordinary bindings produced the clean
result.
- Fresh Greptile: 5/5 on `bc41ba72be2195eabeb0d7727227ee0cd02e8532`,
with no new actionable findings or unresolved threads.
- Hosted QA publication and lifecycle acceptance remain pending. The
separate deployed-agent `Paperclip Review` check is also pending; it
follows a task that failed on the earlier deployed runtime.

- Local OpenCode/OpenRouter acceptance at `bc41ba72`: 530 synthetic
tools were authorized and installed. A simple model-ID reply completed
in 17.3 seconds with no app calls. A discovery task completed in 37.6
seconds, used the search/call relay, made one upstream call, and
returned the exact synthetic value. This is local source acceptance, not
a staging sandbox timing comparison.
- The large-result review finding has a failing-before/passing-after
HTTP MCP regression. Five medium schemas now page without invalid JSON.
A large schema with escaped text reconstructs exactly through bounded
chunks. All 35 assigned-tool tests and the server typecheck pass after
this follow-up.
- Final head `d84ce4856a6e65a35ad5fb8b561492598b525f4e`: all CI gates
pass. Greptile and Paperclip Review both rate the change 5/5. No review
threads remain open. The final full build, server typecheck, and 35
assigned-tool tests pass locally.

## Risks

- OpenCode uses discovery before it calls an assigned tool, including
for small catalogs. This can add a model turn.
- An existing OpenCode provider checkpoint rotates once because it
retains the former tool declarations. Paperclip task history remains
available.
- The historical filtered catalog was not captured. The synthetic
comparison proves the failure mechanism, not the exact cardinality of an
earlier private request.
- No model, provider route, permission, or automatic retry policy
changes.

## Model Used

The bounded-result follow-up also used OpenAI Codex (GPT-6 family). The
exact backend model ID and context-window size were not exposed for that
session. It used reasoning, code execution, and tool use.

OpenAI `gpt-6.1-sol` in Codex, with reasoning, tool use, code execution,
and source inspection. The runtime 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
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 10:49:23 -05:00
DottaandPaperclip 0373f9f261 fix(recovery): wake retained workspace preservation after Retry (#17741)
## Thinking Path

> - Paperclip lets people manage AI agents and their saved work.
> - A stopped run can owe workspace preservation before saved input can
continue.
> - Retry saved a recovery request but did not wake the worker that owns
preservation.
> - Older recovery records could also take the bounded scan slots before
a due request.
> - A second Retry could change the revision while the physical owner
was still saving files.
> - This pull request wakes a separate worker after commit, selects due
work first, and keeps the active owner's revision.
> - Saved work can progress without replaying the stopped provider turn
or blocking other finalization.

## Linked Issues or Issue Description

**What happened?**

An operator approved a saved design and selected Retry after native
workspace finalization failed. The API accepted one canonical request.
The source remained scheduled at zero preservation attempts for more
than 30 minutes. No new provider turn started. A local regression also
found that repeated Retry during export invalidated the physical owner's
completion revision.

**Expected behavior**

Committed Retry must wake bounded source preservation. Due recovery must
progress ahead of passive cleanup obligations and unrelated history.
Duplicate requests must keep one physical attempt. Saved input must
still pass normal admission after verified recovery.

**Steps to reproduce**

1. Retain a terminal run with an exhausted workspace recovery and saved
authorized input.
2. Let the delivery coordinator become quiet, then request Retry.
3. Observe the recovery state and physical preservation receipt. Repeat
Retry while the export is held.

**Paperclip version or commit**

Observed on served commit `4b89eec644d6e1a99d58926e77ae58927c3fa87b`.
Local baseline: `a1f77821b9cd5c9c846fdf7a0fa5cc620ad2b6bb`.

Related work: Refs #17053, #17267, #17094. This change repairs explicit
Retry delivery. It is separate from the run instruction projection in
#17724 and historical unsafe-export discovery in #17687.

## What Changed

- Notify a dedicated workspace recovery duty from the transaction that
saves Retry, recovery admission, adoption, or recovery progress.
- Reconstruct work and saved retry deadlines at startup. Fill each free
export slot independently, track physical work for idle drain, and join
the dedicated worker's exports on shutdown.
- Drain one bounded pass through completed cleanup and saved-input
obligations. Restart that pass after committed changes without
repeatedly rechecking paused input.
- Share source eligibility between deadline selection and candidate
consumption. Keep resolved files-only obligations and ignore unrelated
resolved or cancelled history.
- Select due unfinished preservation before passive historical records.
Rotate past source locks held by other workers and retain the indexed
source lookup.
- Bind the canonical Retry intent without changing an active physical
attempt's generation or revision. Preserve that binding across later
progress writes.
- Add real producer, physical preservation, startup, deadline, idle, and
independent finalization regressions. Document the delivery contract.

## Verification

- Red controls: Retry without a notification stayed scheduled; duplicate
Retry invalidated the active export; whole-batch waiting stranded a
third Retry; a scan without cursor rotation starved a source behind two
actual advisory locks. Removing unfinished-first selection left HTTP
Retry scheduled behind five real recovered sources still owing cleanup.
The fixture explicitly verifies their eligibility with the worker's
actual query filter.
- Further red controls: the previous worker visits only two of three
eligible completed sources. Disabling the committed-change cursor reset
misses a new earlier source arriving while two callbacks are held. Both
pass with the final worker.
- Green: the public Retry HTTP route, registered production worker, real
file copyback, duplicate canonical receipts, and public recovery receipt
reload passed on an owned local fixture. Its agent is paused to keep
this files-only check from starting a provider turn.
- Full workspace recovery suite passed 56 tests, including the
foreign-lock regression.
- Execution-control lifecycle suite passed 24 tests. It covers idle SQL,
stored deadlines, cancelled and resolved history, independent
finalization, and shutdown. One, three, and seven paused completed
sources are each visited in a bounded pass, then stay deferred without a
successor or SQL during 90 seconds of fake-clock idle time. A committed
earlier source is evaluated when it arrives during two held callbacks.
- Both GitHub and Telegram `automatic_running` continuation regressions
passed with the new canonical intent binding.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `node scripts/check-maps.mjs` and `node
scripts/check-module-boundaries.mjs` passed.
- Local `pnpm test:run` could not complete: embedded PostgreSQL
repeatedly failed to start. The owned run was stopped after this setup
failure repeated. Latest-head CI supplies broad coverage.
- Earlier setup failures included a localhost sandbox denial and loss of
the owned disposable Docker database. These were separate from the
product red controls above.
- Local database tests use an explicitly named disposable PostgreSQL
`_test` database. That opt-in database is reset before the suite.
Default embedded test behavior is unchanged.
- Exact-head CI is green at `ef7dcf1ba1060864c9d216c33b51f4d9f8f57fbd`;
Greptile and Ponytail both rate it 5/5, with no unresolved review
threads. Earlier CI caught the indexed discovery assertion and two exact
chat intent-binding regressions; all three were fixed and pass locally
and in CI. A separate chat shard lost contact with its self-hosted
runner without a product assertion result. A later shared runner
shutdown interrupted several jobs; one infrastructure rerun passed
before the final test-and-worker follow-up triggered a fresh green run.
- No staging deployment is part of this PR. The original approval
remains saved; deployed recovery still needs acceptance after rollout.

## Risks

- More recovery writes now wake a bounded maintenance duty. Completed
history must not keep it active. Idle and deadline tests cover this
boundary.
- Resolved files-only obligations must remain eligible without granting
replay. The startup regression checks that path.
- Provider stop proof, copyback ownership, source binding, retry
budgets, and normal execution admission remain required. There is no
schema or public API change.

## Model Used

- OpenAI Codex based on GPT-6, with code execution and browser tools.
The exact serving model ID and context window are not exposed in this
session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 10:28:12 -05:00
DottaandPaperclip 338bf75761 fix(chat): admit task Retry after GitHub reconnect (#17733)
## Thinking Path

> - Paperclip manages agents and their tasks.
> - Task Retry must preserve saved input and enforce current access.
> - A GitHub reconnect invalidates old runtime callbacks.
> - Retry reused that old callback authority and rejected valid new
intent.
> - Retry also replayed an older failed request when a follow-up was
already saved.
> - This change admits a deliberate Retry under current authority and
transfers saved input once.

## Linked Issues or Issue Description

Refs #16965, #17053 and #17317. These repairs preserve work and contain
old executors. This change fixes the subsequent chat admission boundary.
A search found no overlapping open reconnect/admission fix.

**What happened?**

Ordinary task Retry returned `chat_failed_run_retry_not_authorized`
after the same GitHub App reconnected. The endpoint was healthy, but the
saved request still carried its old runtime generation. A newer queued
follow-up also made Retry reject the older failed request instead of
continuing the follow-up. No successor was admitted.

HTTP qualification found two related defects. Concurrent clicks could
omit the canonical chat action from a response. Signed-in board dispatch
also passed an incomplete task resource to the permission resolver,
which rejected a permitted mutation.

**Expected behavior**

A deliberate Retry checks current authority for the same App, sender,
repository, conversation and task. It continues saved input once. A
later reconnect, changed App, revoked access or changed source prevents
dispatch. Old runtime callbacks remain invalid.

**Steps to reproduce**

1. Admit a GitHub request and record a failed native run.
2. Save a follow-up while execution is blocked.
3. Reconnect the same GitHub App.
4. Click ordinary task Retry.
5. Before this change, admission returns 409. Without reconnect, the
newer input alone also causes 409.

**Paperclip version or commit**

Baseline source: `41c42895fa862c586ff841f8c50200d93ffc83a4`.

**Deployment mode**

Source checkout on macOS. Regressions use real PostgreSQL transactions
and the assembled chat, HTTP route and heartbeat admission services.
Provider boundaries are simulated. No hosted recovery is claimed.

## What Changed

- Record the admitting App identity for new GitHub deliveries.
Historical deliveries can use their original working-comment binding.
Reauthorize deliberate Retry under a pinned current generation and
credential-reference fingerprint.
- Select the complete saved-input queue from the failed run's actual
conversation before replaying the older failed batch. Keep exact-run
Retry bounded while ordinary task Retry supports larger queues. Transfer
its receipts with the dispatch transaction. Recover the same ownership
after restart or a lost response. Release unadmitted input after a
definitive rejection.
- Preserve canonical chat action IDs across concurrent clicks. Supply
current task status and assignment fields to board mutation checks.
- Keep exact-run Retry, stale webhook, containment, source integrity,
publication, pause and budget checks. Update recovery contracts and
verification recipes.

## Verification

- Red: all three new PostgreSQL regressions failed on unchanged
production code. Reconnect failed at chat authorization. Newer input
failed at the obsolete-source guard. The combined case also failed.
- Green: 61 selected chat integration cases passed. These include 27 new
cases and 34 existing cases for containment, retained-source recovery,
exact batches and source revocation.
- A further red/green PostgreSQL regression reproduces the 51-message
overflow identified during review. All 51 messages reach one successor,
including a later Retry of that successor. A separate 52-message
consumed-batch regression also passes.
- A competing conversation retains its own deferred message. Distinct
automatic policy contexts are checked independently; revoking only the
later policy blocks the whole unadmitted batch. Batch validation still
rejects a later message with a changed App binding or deleted source. A
real PostgreSQL query capture reduced the 51-message preparation from
1,103 calls to fewer than 180.
- All 16 durable task Retry tests passed.
- The real HTTP route returns 202 and admits one queued successor for
concurrent deliveries. Fault injection covers rollback during input
handoff, response loss after dispatch commit, and permission loss when
resuming an existing durable wait. A wait only adopts input after
current admission succeeds; a one-shot settlement marker keeps status
projection read-only. A new deliberate Retry works after another
reconnect or a failed successor.
- Current-App, repository, sender, source edit/delete, reassignment,
endpoint pause and board-permission controls passed. Historical
deliveries remain unchanged.
- Final-head CI: 55 checks passed, three expected skips. The unchanged
minute-bucket rate-limit assertion passed locally against PostgreSQL and
on its one CI rerun. Greptile reviewed the final commit at 5/5 with no
unresolved threads.
- Workspace typecheck and full build passed. Map alignment, module
boundaries, UI token gates and `git diff --check` passed.
- Hosted task recovery and a live provider turn remain unverified. The
local tests hold agent capacity to inspect admission without starting a
model or publishing a GitHub response.

## Risks

- A deliberate GitHub Retry can admit old saved input under current
connection authority. It requires the same App binding and current
access. It pins that admission; it does not rewrite the historical
delivery or make stale callbacks valid.
- The durable chat queue has an optional admission callback. It
transfers input only when the transaction contains a valid queued
execution or saved wait. Other chat consumers have no callback and
retain their behavior.
- No migration, Cloud dependency, deployment, configuration change or
workspace cleanup is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, source inspection, code
execution and GitHub 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-26 10:26:45 -05:00
DottaandPaperclip a1f77821b9 perf(tasks): show recent conversation before historical activity (#17593)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A task page must show the instruction and current conversation
quickly.
> - The current page waits for related task data and historical run
transcripts.
> - These reads grow with task history, even when the reader only needs
the latest answer.
> - This pull request gives cold opens a small initial view and loads
older history on demand.
> - Messages and runs observed while the page stays open remain visible.
> - The benefit is a readable task before historical diagnostics finish
loading.

## Linked Issues or Issue Description

Related: #14667 and #16229. The first changes the reveal gate and scroll
anchors. The second adds general history pagination. This PR adds a core
task read and a folded recent-conversation view. It preserves the
default full-read API contracts. The shared files will need coordination
if either related PR lands first.

**What existing behavior does this improve?**

Cold opening an ordinary task with a long conversation or large run
logs.

**Current behavior**

Task enrichment and historical transcripts delay the readable
conversation. A cold open can fetch several megabytes of tool activity
before revealing saved messages.

**Proposed behavior**

Show the task instruction, recent saved replies, latest human input, and
the latest run's conversation data first. Fetch older messages and full
run activity when the reader chooses **More messages**. Retain new
messages while the page stays open.

## What Changed

- Add an authorized core issue view that skips related enrichment. Keep
enrichment on the existing detail read. Share task mutation, rollback
and invalidation updates with the core cache.
- Add a bounded recent-comment read. Preserve the first human
instruction when no description exists, including legacy rows with a
NULL author type. Keep company and task access checks and comment
redaction.
- Add optional recent activity and run-summary views. Fetch original
input receipts for visible comments separately so delivered messages
stay out of the queue. Reconcile watched unfinished runs after a
reconnect beyond the preview window, removing deleted runs after
reconciliation.
- Filter the latest native run's initial events to assistant messages,
request lifecycles and terminal results. Full event reads remain
available on expansion. Legacy fallback reads use a small tail extended
to the first complete record. HTTP cancellation aborts the storage read.
- Retain observed messages across cursor catch-up and new runs. Apply
local cancellation and deletion to both caches and their task aliases.
Refetch locally seeded history pages on expansion. Preserve expansion
across identifier and UUID links. Keep deep links, classic tasks and
Agent Chat on their existing full-history path.
- Update API documentation, design guidance, capability maps and
regression coverage.

## Verification

- Final acceptance on `9ea0b15ae44d9f6d2c9a9f824b4835f299f92979`: all CI
gates passed, including server/UI tests, all eight browser shards,
runner checks, full typecheck and build. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/40326990328).
GitHub reports 55 successful checks, two intentionally skipped checks,
and one neutral Paperclip Review check described below. No checks are
pending or failed; Greptile is 5/5 and no review threads remain open.
- October 26 merge update: merged current `master`. The only conflict
was in task-page imports; both the compact-history hook and the new
live-update hooks remain. All CI tests and build jobs passed on
`044fd6733d`. Fresh review found canceled-comment cache drift, legacy
human-comment filtering, send-then-expand truncation, and partial legacy
log records. These defects were fixed in `af3d66a5bd`.
- Review-fix verification: 470 tests pass across ten affected suites,
including all six PostgreSQL cold-open tests without a helper override.
Cancellation/delete and send-then-expand regression tests failed before
the fixes and pass afterward. Coverage includes task identifier/UUID
reopen, stale in-flight reads, legacy NULL author types, local-file and
object-storage tails cut inside UTF-8 text, route forwarding, and
request cancellation. Full workspace typecheck and production build,
token gates, map validation and diff checks pass.
- Follow-up review found that a failed expanded legacy read lost its
record-alignment state on retry. `9ea0b15ae4` commits the expanded
window only after a successful read. The new regression fails before the
fix and passes afterward; all 19 transcript tests, UI typecheck, UI
build and token gates pass. Greptile reviewed this commit at 5/5 with no
actionable findings, and all review threads are resolved.
- The final Paperclip Review check ended neutral because its execution
did not complete; no passing Paperclip assessment is claimed. Its
earlier four concrete findings were fixed and regression-tested.
Greptile and the security scans completed successfully on the final
commit.
- The preceding `af3d66a5bd` CI run was canceled when superseded by the
retry fix. Its server shard 11 check briefly reported failure, but the
job API records cancellation and its test step passed all 1,750 tests.
This superseded run is not used as final CI acceptance.
- 549 focused tests pass on the final implementation across nine task
UI, activity-route, OpenAPI and PostgreSQL suites. These cover pending
history, desktop/mobile visibility, expansion, retained runs, message
bursts, cancellation recovery and queued-comment removal in both views.
- Legacy expansion keeps the latest answer visible while fetching and
deduplicating older output.
- Five PostgreSQL tests pass for core access denial, recent comments,
missing-description instructions, event paging and bounded activity/run
reads. macOS could not start another PostgreSQL cluster because it
exhausted its semaphore limit. These tests used a separate disposable
database on an existing local server through a temporary test setup
override. The helper was restored afterward.
- Full workspace typecheck and build pass with the final state fixes, as
do token gates and capability-map validation.
- Token gates, capability-map validation and `git diff --check` pass.
- Browser proof used a disposable task with 80 comments and six large
run histories. The cold view showed the instruction and recent exchange.
**More messages** revealed older comments. Navigation away and back
preserved expansion.
- Local HTTP sample: core 50 ms, recent comments 24 ms, recent run
summaries 17 ms. The latest native conversation response was 839 JSON
characters / 8 ms; its full event response was 1,099,005 / 86 ms.
Browser content paint was 1.34 seconds with development assets cached.
These are local observations, not staging latency claims.
- The first CI run passed every job except four board-send browser cases
and the review threshold. Those browser fixtures only mocked the old
comments endpoint; they now serve both recent and full reads, retaining
all message and attachment assertions. Both initial review findings were
fixed with regression tests. The next CI run passed every job. The
deeper review identified core-cache mutation, older delivery receipt and
retained run-status gaps; those are now fixed with regression coverage.
Final review is 5/5 with zero unresolved findings. Final-head CI
initially failed one unchanged runner shutdown test
(`runnerd-codex-transport.test.ts`, timeout-attachment case) with
`NativeSessionCloseUnrecoverableError`; all other CI jobs passed. The
same runner code passed on 971a762f80. A targeted local reproduction
also failed during provider drain. The failure is outside the changed
task loading paths; its underlying cause remains unresolved. The single
failed-job retry passed on the same head; this demonstrates recovery,
not a root-cause fix. All CI gates passed on the previous implementation
head `9004f94f28`: [CI run and
retry](https://github.com/paperclipai/paperclip/actions/runs/40192334629).
- `pnpm test:run` was attempted and stopped after repeated embedded
PostgreSQL startup failures. The native session suite recorded 15
database-related failures; other database suites could not start. No
complete local suite pass is claimed.

## Risks

- The compact view intentionally omits older diagnostics until
expansion. Existing open questions and approvals still use the current
interaction and run paths.
- Previously observed comment and activity rows remain cached while
open. The newest preview and incoming cursor pages refresh; this does
not add a general historical-edit synchronization protocol.
- Recent views are optional. Existing full API callers retain their
response shape and behavior. No migration is required.
- A legacy tail can exceed the requested byte limit by the prefix of its
first log record. Backward reads stop at the preceding record boundary
and honor cancellation.
- Staging has not been deployed or qualified with this change. Instance
startup latency is separate from task history loading.
- The related open PRs touch the same task-history files.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository editing, shell
tools and browser testing. The exact serving model identifier and
context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 08:11:39 -05:00