Commit Graph
82 Commits
Author SHA1 Message Date
4c56702e06 fix(server): schedule retained native-session cleanup (#17717)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs can retain a local session after an interrupted durable
suspend.
> - The orphan reaper repeatedly scans completed history for that
cleanup duty.
> - Idle scans keep the database active. Removing them requires complete
wake and ownership paths.
> - This pull request moves retained-session cleanup to committed
signals, local release events and saved deadlines.
> - Existing physical proof checks still decide whether cleanup is safe.
The shared scheduler does not grant execution authority.
> - The benefit is quiet retained history with recoverable cleanup and
owned shutdown.

## Linked Issues or Issue Description

Refs #17709 and #18135. This is slice 51 of the existing
recurring-server sleep stack. Both referenced dependencies have merged.
The target is `master`.

**What happened?**

The periodic orphan pass scans retained native sessions even after their
cleanup is complete or no automatic action is safe. Some eligible
sessions also depend on a local session, environment lease or original
maintenance callback releasing ownership. An earlier decision
notification can be consumed before the run's later terminal projection
commits.

**Expected behavior**

Reconstruct existing work at startup. Wake from committed writes and
actual owner release. Register the saved claim expiry or a probe for a
specific live process. Stop recurring discovery when no obligation
remains. Preserve original callback ownership and all existing cleanup
proof checks.

**Steps to reproduce**

1. Retain completed native runs with a durable-suspend close failure.
2. Let the periodic orphan pass run with no new work.
3. Observe repeated cleanup discovery. Separately, delay terminal
projection after its decision notification is consumed and observe the
missing cleanup wake.

**Paperclip version or commit**

Parent #17709 at reviewed head
`3b75f4bc1da1370304f069fc287af3d693575716`, landed as
`df6156c2e37f542a69f393dde31e357b82b7cac1`. Current integrated master:
`31b927e3013a8a4b3266854b740cf40a24753788`.

## What Changed

- Move scoped, paged discovery to the retained cleanup owner. Preserve
explicit manual recovery.
- Register the duty with the shared scheduler and remove it from the
periodic orphan pass. Keep concrete lease expiry and live-process probe
obligations.
- Use typed outcomes for settled/refused work and process, session,
environment, maintenance or lease waits. Keep physical proof and
quarantine decisions in the executor.
- Wake from committed finalization and terminal projection writes,
durable process/lease release, and local session or callback settlement.
Routine company-only finalization hints leave dormant cleanup quiet.
- Join duplicate cleanup and serialize inspections on one database lane.
Keep original Runner callbacks owned until settlement and shutdown.
- Preserve all master profile fixtures and the branch's historical
identities. Save the colliding sleep profile 79 separately. Generate
combined Copilot profile 80 from its source and retain master's other
provider profiles.
- Add the owner audit and regression coverage. No new table, migration
or independent maintenance timer is added.

## Verification

- Server acceptance: **2,342 distinct passing cases in 18 complete
files**. The 14-file unaffected group contributes 1,532 passes. Full
startup contributes 76, process recovery 410, environment service 51,
and external-chat response 273. The 29-case cleanup worker suite and
977-case executor suite run in full. No case in these files is skipped.
- Controlled scope regression: removing only the ordinary finalization
issue/run guard wakes dormant retained cleanup; the same assertion
passes after restoring it. A real local owner release still resumes the
durable candidate.
- Preserve the first broad failure: 1,607 passed and one startup
shutdown case failed because the coordinator mock lacked `stop()`. Add
only that mock method. All 76 unchanged startup cases then pass. Do not
treat the first broad command as green.
- Dedicated PostgreSQL 17 databases use the existing migration 413
schema. Embedded-only fixtures use the existing recovery helper with
fresh per-call databases. All temporary imports are restored byte-exact.
No assertion or timeout is relaxed.
- Current-master integration preserves both complete source histories.
The server, UI and database trees are identical to the server-tested
source. All master historical profile fixtures remain byte-exact. The
prepared sleep profile 79 remains independently inspectable.
- Current runtime validation at
`d08f764e3efe75e96929173afe7ee8739121ad9f` passes all 12 commands (22
installed ACPX/Grok contract cases and 26 native-provider Rust cases):
`pnpm install --frozen-lockfile --ignore-scripts`; Copilot/Grok identity
and generated profile checks; Runner and server typechecking; server
build; Copilot/Pi installation, profile compatibility and transport
settlement files (130 passed; one opt-in closed Pi snapshot case skipped
because its distribution root is not configured); installed ACPX
model/reconnect package contract and Grok identity tests; Rust
native-provider backend tests; module boundaries and migration order.
- Earlier 94-case installation/settlement acceptance applies to the
prepared profile 79 source. It is retained as history and does not
substitute for the current profile 80 validation above.
- Failure history and duty-specific evidence remain in
`doc/plans/2026-10-26-retained-native-session-cleanup-sleep-audit.md`.
Exact-current-head acceptance: all 60 checks are clean, including
protected CI and security; Greptile gives 5/5 for
`281d579de0d08e907194b8b790a0597b07d16b7b` with no actionable findings.
No Ponytail review is present under the authorized missing-review
policy.
- These checks do not claim a full local repository suite, live Copilot
or Daytona qualification, deployed host/database suspension, or measured
cost savings.

## Risks

- Missing a supported producer could strand cleanup. Tests exercise real
finalizer, heartbeat, environment and process writers. Process-local
signals cover in-process writers; no multi-replica or external SQL
notification transport is added.
- A timeout can leave an original callback active. Cleanup and shutdown
must keep waiting for it. The existing global maintenance drain is
conservative across roots.
- A retained live process still has a scoped 30-second absence probe. A
saved lease keeps its actual deadline. Operational errors retain retry
work. Immutable proof refusals and operator-required histories do not
gain automatic retry authority.
- Cleanup keeps all existing artifact, identity, claim, no-launch and
quarantine checks. Terminal status alone does not authorize physical
cleanup.
- This PR does not expand Cloud alarm coverage or relax host sleep
eligibility. It proves worker behavior, not deployed app/database
suspension.
- The Copilot source identity has changed; these checks do not claim new
live provider qualification.
- The parent has merged. This PR is merged only after its current-head
protected CI and review gates pass under the existing campaign
authorization.

## Model Used

OpenAI Codex, GPT-6 family, with code execution and repository 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>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 04:24:57 -05:00
Nicky LeachandPaperclip aa75ec9d56 Replay Claude native options on ACP reconnect (#18135)
## Thinking Path

> - Paperclip manages agents and their task execution.
> - Runner uses ACPX to connect to Claude sessions.
> - Claude receives native options when ACPX creates a session.
> - ACPX omits those options when it loads or resumes the same session.
> - A reconnect can lose allowed tools, instructions, and settings
sources.
> - This pull request replays the existing options through the existing
Claude metadata contract.
> - Resumed tasks keep the configuration admitted for their session.

## Linked Issues or Issue Description

**What happened?**
A Claude task can complete its first turn and then fail on a warm
follow-up. The provider refuses an internal completion tool because
`session/load` omits the `allowedTools` options sent with `session/new`.
The same omission exists on `session/resume`.

**Expected behavior**
Creation, load, and resume must supply the same caller-selected native
session options. The existing policy for native user settings must stay
unchanged.

**Steps to reproduce**
Create a persistent Claude ACP session with an explicit allowed-tool
list and appended instructions. Complete a turn, close its connection,
and reconnect to the saved session. Inspect the ACP request. Before this
change, the reconnect has no `_meta` field.

**Paperclip version or commit**
Reproduced on Runner source `e8b78cce5bb557b086bee9ca930eeaab1d09b244`.
The offline protocol regression also fails on the current base
`80a2b9284bf189e93ca4313085814548f48b8dc8`.

Related: #18089 added prepared harness storage. #11798 concerns the
separate legacy adapter and does not fix Runner reconnect metadata.

## Upstream status and backport scope

ACPX [0.21.1](https://github.com/openclaw/acpx/releases/tag/v0.21.1)
already replays session metadata on load and resume in its [released
client
implementation](https://github.com/openclaw/acpx/blob/v0.21.1/src/acp/client.ts).
This PR backports that behavior to the currently qualified 0.13.1
integration.

The released 0.21.1 runtime does not expose equivalents for all hooks
used by Runner's existing patch: verified executable spawning,
synchronous protocol admission guards, provider extension dispatch, and
response-delivery receipts. Upgrading requires a compatibility pass that
preserves these guarantees and removes local changes already covered
upstream. This backport does not add a new Paperclip-specific dependency
contract.

## What Changed

- Replay existing Claude native options on `session/load` and
`session/resume` through the same metadata builder used at creation.
Other providers keep their existing reconnect requests.
- Test both reconnect methods against the installed ACPX manager and a
local ACP wire fixture. Cover allowed tools, model, turn limit,
instructions, and both existing settings-source modes.
- Update exact source attestations and generated profile declarations
required by the shared ACPX patch. Keep historical fixtures unchanged.
- Document the reconnect contract. No new home mode, plugin policy, or
provider permission rule is added.

## Verification

- Confirmed the new load and resume tests fail before the patch because
metadata is absent.
- Applied the canonical patch to pristine package bytes and confirmed it
matches the tested runtime.
- Targeted installed-package model-selection and reconnect suite plus
changed Grok identity tests: 22 passed.
- Rechecked the four new reconnect cases against the cleanly applied
patch, with explicit expected values for all supplied options.
- Three targeted current-profile and revision-boundary assertions pass
locally. Updated the native Pi test digest; native compilation and
execution remain in CI.
- Maintained profile generators pass their consistency checks.
- GitHub CI is green, including typecheck, native Runner checks, package
contracts, packaged installation, build, and server/browser suites. One
unrelated server database-cleanup timeout passed on the bounded
failed-job rerun. No comprehensive local suite was run. Live
post-deployment acceptance remains pending.

## Risks

Claude reconnects now receive the same native settings sources and
options as creation. This corrects configuration loss without changing
caller policy. The shared dependency patch requires new source
identities for other attested profiles; their reconnect behavior is
unchanged. No database migration is required.

## Model Used

OpenAI Codex, GPT-6 family, with code and tool use. Exact deployment 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 01:45:18 -07:00
Nicky LeachandPaperclip 80a2b9284b Define durable runtime activity events (#18129)
## Thinking Path

> - Paperclip manages agents and tasks.
> - Runner reports durable run events through PRP.
> - Runtime clients need a typed record of reported activity.
> - The event must keep the normal run authority and read boundaries.
> - This pull request adds the generic runtime activity event contract.
> - Later PRs can publish and consume this contract without private
plugin coupling.

## Linked Issues or Issue Description

First feature prerequisite extracted from #18050. Runner publishing is
#18050; the dependent consumer is #18131. Related independent test
stability work: #18128. The parent search and review history is
preserved in [the verification
archive](https://github.com/paperclipai/paperclip/pull/18050#issuecomment-6489369676).

**Subsystem affected**

Runner event protocol, server run-event persistence and redaction, and
UI event taxonomy.

**Problem or motivation**

Core needs a durable, typed activity record tied to the authenticated
run. A text marker is not an event contract.

**Proposed solution**

Add `runtime.activity.recorded` as a P1 event with a closed `{
namespace, activityKey }` payload. Runner knows no plugin or panel
identity. Run/session identity, sequence and emission time stay in the
outer envelope; Core resolves company, task and agent through the
authorized run binding. Use the existing authenticated persistence,
acknowledgement, replay and redaction paths.

## What Changed

- Define and validate the event in PRP v1, v2 and v3. Update the
generated protocol artifacts and event catalog.
- Preserve saved and live event redaction. Test persistence, replay
deduplication and the existing run-read boundary.
- Register the event in the UI taxonomy without changing panel display
behavior.
- Advance the source-bound Copilot identity to 78. Retain all published
historical identity fixtures without changing their bytes.

## Verification

- Root `pnpm typecheck` and `pnpm build`: passed for the revised
activity contract.
- Node protocol checks: 14 passed. Provider identity and registry tests:
185 passed. Server tests: 103 passed. UI event registry: five passed.
- Maintained Grok and Copilot identity generator checks and `git diff
--check`: passed.
- The first activity-contract review scored 4/5 because the dependent
producer and readers still used the earlier contract. Both dependent PRs
are now updated and restacked; the finding is resolved and review is
running again.
- Initial extraction retained a consumer-only import in one server
suite. That suite failed to load. The consumer case and import were
moved out; the final three server files passed all 103 cases.
- Earlier panel-specific head `6137c50bc` had green CI and standard/Apex
5/5. Those scores do not qualify this revised activity contract. Fresh
CI and reviews are pending. Earlier combined results in the archive
apply only to their recorded source revisions.

## Risks

This change is additive. It adds no route, publisher, filesystem
transport, provider sandbox grant, or panel display behavior. Activation
hints grant no permission to read a plugin view. Provider identities
bind the changed protocol source; historical identities remain
decode-only. No schema migration or dependency change is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools and code
execution. The exact serving snapshot is not exposed.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 00:32:12 -07:00
Nicky LeachandPaperclip c57af3c564 Reuse prepared Runner storage and installed skill selections (#18089)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/207/changes/paperclip/207
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages AI agents and their work.
> - The native Runner prepares selected skills, instructions, and
provider storage.
> - Repeated preparation imports the company skill inventory and
rebuilds Claude storage.
> - Execution environments can already maintain prepared resources.
> - This pull request lets them reuse account storage while Core keeps
execution policy.
> - New retry runs resolve current skills and keep the failed attempt's
history.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Native Runner preparation and retry skill selection.

**Current behavior**

Explicit installed selections still trigger company inventory
reconciliation. Plugin preparation receives account identity only on
warm transitions. Claude's isolated mode requires a session-specific
configuration directory.

**Proposed behavior**

Skip inventory imports when explicit selections are installed, while
retaining current authorization and version resolution. Send account
identity on initial preparation. Allow an execution environment to
provide persistent Claude storage without enabling preconfigured
permission behavior. A new retry resolves current skill assignments.

**Reason and benefit**

Remove repeated preparation work without adding environment-specific
policy to Core. Related: #13984 describes a similar storage-lifetime
problem in the separate claude_local adapter; this PR does not change
that adapter.

## What Changed

- Derive Claude’s configuration path from the single authoritative
prepared-storage input; separately supplied CLAUDE_CONFIG_DIR values are
overridden.
- Add an explicit prepared Claude storage binding, forward it to the
sidecar, and retain recovery and provider lifetime fencing.
- Refresh Core-owned Claude settings after acquiring the lifetime lease.
Reuse environment-prepared skills.
- Reuse installed explicit skill selections and preserve
missing-selection initialization and current access checks.
- Reserve the prepared-home marker for environment provisioning; task
overrides are rejected and configured bindings are stripped before
native launch.
- Clear inherited skill selection snapshots on new retries. Keep
admitted execution recovery and failed attempt metadata.

## Verification

- Current single-input follow-up `8dbc2f6ec`: 154 focused Runner checks
pass with one existing skip; four Grok identity checks and four Pi
packaged-probe checks pass. Shared immutable source identities advance
to Grok10/Pi32/Copilot74. All56 current-head CI checks pass (four
intentionally skipped); standard and enhanced reviews are both5/5 with
no unresolved threads.
- Focused Runner sandbox tests: 29 passed. Focused environment tests: 16
passed.
- company-skills-empty-runtime: 10 passed.
- Plugin Runner and runtime selection database tests were attempted.
Local execution is blocked because embedded PostgreSQL cannot load
libzstd.1.dylib; these checks remain for CI.
- New database regressions cover installed-selection reuse, initial
account preparation, and retry snapshot removal.
- Prepared-home trust-boundary regressions: 4 targeted checks passed
(task schema, all env binding scopes, native executor).
- Focused Pi public-install probe checks: 4 passed. The build smoke
probe now asserts the current Pi 32 profile and exact digest.
- CI found and fixed retry-context TypeScript inference, stale Pi
identity fixtures, Docker source identity inputs, and the
skill-observability test’s old assumption that every selection imports
inventory. Cold and reused selection coverage remain.
- CI chat shard 2 initially failed three GitHub/Discord idle-database
assertions. An unchanged-head rerun passed; the original cause remains
unexplained.
- Runtime head `f5b53679a` passes all 56 current CI checks (four jobs
intentionally skipped), including the full build/public-install probe,
TypeScript, Rust, Runner and server matrices. Greptile is 5/5 with no
unresolved review threads.
- The requested enhanced review scored 5/5 on `f5b53679a`, with one
nonblocking documentation request. Documentation follow-up `1ac5d26a8`
adds only the documented existing ownership/0700 requirement; the thread
is resolved and all 56 current-head checks pass (four intentionally
skipped). The subsequent single-input runtime follow-up8dbc2f6ec
repeated the complete CI → standard5/5 → enhanced5/5 cycle successfully.
- Broader verification is delegated to GitHub CI as requested. The
initial policy check rejected a generated lockfile repair; that change
was removed because Core CI already resolves stale importer entries.

## Risks

Prepared storage must be provisioned by the execution environment before
launch. It is not credential isolation. Core replaces managed Claude
settings under the existing provider lease. No new per-run harness homes
are created by this option. New retries may select a newer skill
version; recovery of an already admitted provider execution keeps its
saved input.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and tool use. The exact model
revision 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
related context above
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change
- [x] I have run focused local tests; database and full verification
remain for CI as explained above
- [x] I have added or updated tests where applicable
- [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 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 17:09:24 -07:00
DottaandPaperclip 356c7de9b7 fix(runner): bind Grok packs to current admission source (#17972)
## Thinking Path

> - Paperclip manages agents and their work.
> - Native agents use verified Runner and provider-pack artifacts.
> - A protected installed pack can be reused when its selected provider
profile matches.
> - Grok kept profile 1 when its sidecar gained effort, search, and
startup diagnostics.
> - An older Grok sidecar can therefore pass compatibility and reject
the new session fields before provider startup.
> - This PR binds the current Grok profile to its admission source so a
fresh run selects the current verified pack.

## Linked Issues or Issue Description

Refs: #17922, #17942, #17962. Related installation contract: #14024. No
duplicate repair was found.

**What happened?**

The selected Grok profile digest stayed unchanged across native session
contract changes. The installed-pack verifier correctly compared that
digest, but the unchanged value let a pre-effort sidecar satisfy a
current controller. That old parser rejects `grokEffort` and
`grokDisableWebSearch` before the new startup diagnostics run.

**Expected behavior**

A fresh Grok run must use a pack that supports its current session
contract. Source-only app changes must still permit warm reuse when the
selected Grok profile matches. Reattachment must keep its exact admitted
artifact authority.

**Steps to reproduce**

1. Retain a protected pack with published Grok profile 1 and ACPX
interface 1.
2. Upgrade the controller to the native effort and search contract.
3. Start Grok 4.7 with High effort and disabled web search.
4. The old profile passes installed-pack compatibility, but its sidecar
rejects the new fields.

**Paperclip version or commit**

Reproduced from master at `09ad9adce2cf4742944353a3707a2f908e9bb35e`.

## What Changed

- Advance Grok to profile 7. Keep historical versions 1–6 decodable and
keep the Grok 1.0.13 runtime pin.
- Stamp the Grok admission source identity into a generated launcher
comment. Keep the existing physical command-byte digest check unchanged.
Bind effort/search/credential handling, sidecar admission, and Rust
backend/session/diagnostic source.
- Check the source attestation in the existing TypeScript/Rust profile
build gate. Keep its required fixture in the Docker context. Refuse to
overwrite a versioned identity after source changes.
- Add regression coverage for rejecting the old pack, current-profile
warm reuse, exact historical recovery authority, and actual sidecar
dispatch of Grok 4.7 High with both search policies.
- Re-attest Copilot as profile 71 because its bound shared recovery
decoder now retains Grok 6. Preserve Copilot 70 and all earlier
identities. Keep the compatibility algorithm, other provider identities,
dependencies, lockfile, and workflows unchanged.

## Verification

- The production installed-pack regression failed before the profile
update: the old Grok pack was accepted. It now passes.
- 105 server manifest, artifact, archive, and authority tests passed.
- 246 Runner profile, physical launcher integrity, Grok
effort/search/credential, and actual sidecar process tests passed; six
existing platform cases were skipped.
- 31 Node packaging and identity tests passed, including an actual
generator CLI regression that preserves all authority files when a
versioned identity would change.
- 55 Rust ACPX unit tests and 17 real sidecar pipe tests passed. After
the final profile declaration, all 55 unit checks passed again.
- Final `pnpm -r typecheck` and `pnpm build` passed at the final source.
- CI on the preceding head caught Copilot’s stale attestation for the
shared recovery decoder. The same current-source test failed locally,
then passed after profile 71 was generated with version 70 retained. All
106 affected Copilot/profile checks pass. Final head
`78e6d76fc52f492371e15574482b3641735a6d89` passed the full CI workflow;
the failed prior job log is retained.
- Review follow-up: mutating the Rust backend’s actual Grok descriptor
field left the prior identity unchanged. This regression failed before
binding `acpx_provider_backend.rs` and passes afterward. Profile 7
retains the prior versioned fixture and recovery decoder. All 179
affected Runner checks and 75 focused server pack/manifest checks passed
after this change.
- `pnpm test:run` hit the recorded embedded PostgreSQL bootstrap failure
after five attempts. The full run also exposed a current-release fixture
with the historical Grok digest; it now reads the current profile. Its
11 focused manifest tests now pass. The failed local run log is
retained; final exact-head CI passed.
- The same filtered-context Docker build that failed CI now passes
locally after adding its required source fixture.
- A separate probe used the built sidecar in a private HOME with no
credentials. It admitted the current profile and the new Grok fields,
then returned the closed working-directory rejection before provider
launch or inference.
- A historical parser probe reproduced the pre-effort sidecar rejection.
These probes establish the contract boundary; they do not establish
native subscription task acceptance.
- Initial restricted local ownership tests failed because loopback
listeners were denied. The same tests passed with loopback access. One
new dispatcher fixture first lacked required instructions; the completed
request passed. These setup failures are retained in local evidence.
- Live native task acceptance remains pending deployment. Earlier
deployed attempts failed before tool output. No successful native shell
proof is claimed.

- Final exact-head merge gate: all 62 contexts are clean (57 success,
four intentional skips, one informational neutral formal review).
Greptile and Paperclip reviews are both 5/5, with no unresolved
actionable threads. The formal review uses the existing report-only
neutral policy.

## Risks

- The first fresh Grok run after upgrade may need to stage the current
provider pack. Matching current profiles keep their existing reuse path.
- Fresh admission rejects older Grok profile identities. Historical
decoding and exact reattachment authority remain separate; this change
does not reinterpret an old identity or replace an active session's
pack.
- Future changes to bound source require a new Grok profile attestation.
The build gate fails if the checked-in identity is stale.
- Model, effort, search, credential, approval, and retry policy are
unchanged.

## Model Used

- OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact deployment 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 (focused checks; full-suite
database failure is retained above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 07:15:13 -05:00
DottaandPaperclip 38d08847b8 fix(runner): keep OpenRouter upstream keys in the parent proxy (#17949)
## Thinking Path

> - Paperclip manages agents and their work.
> - Paperclip Runner starts OpenCode with the selected provider and
model.
> - The native OpenRouter route passed the reusable upstream key into
the child environment.
> - A persisted-state scan found that key in an OpenCode database WAL.
The exact write operation is not known.
> - This pull request reuses the existing parent-held provider proxy for
that route.
> - The child receives a temporary loopback credential instead of the
upstream key.

## Linked Issues or Issue Description

**What happened?**

The native OpenRouter path passed `OPENROUTER_API_KEY` into the OpenCode
child. A real Product E2E persisted-state scan detected the key in the
child database WAL. The scan does not establish which operation wrote
it.

**Expected behavior**

The runner keeps the reusable upstream key in its own process. OpenCode
can call only the selected model through the session proxy.

**Steps to reproduce**

1. Start the OpenCode driver with an explicit or ambient synthetic
OpenRouter key.
2. Inspect the fake child configuration, environment, and persisted
provider values.
3. Send a request through the real loopback proxy and verify the
upstream authorization and exact model.

**Paperclip version or commit**

The regression is present on merged master
`813e808af462b6a6f9db38b6791e3bfe8465b51e`. This PR is rebased onto
merged master `d40f9ac377`.

**Deployment mode**

Built from source. The finding came from an AWS Product E2E job. The
regression tests use local synthetic servers and a fake child, with no
provider calls.

Related issue search found #16643 about general inherited environment
scope. This change addresses the narrower native OpenRouter path. No
duplicate custody PR was found. This PR must remain unmerged until
separately approved; it does not change the eval baseline or qualify a
new live result.

## What Changed

- Reuse the existing parent-held proxy for native `openrouter/` models.
- Remove the upstream key from the child environment and retain it in
diagnostic redaction.
- Keep the selected provider and exact model. Reject alternate-routing
fields before the upstream request. Use a session-lived loopback token.
- Preserve the effective explicit or ambient proxy bypass list when
adding loopback entries.
- Add explicit and ambient key regressions, upstream routing checks, and
child persistence checks.
- Document the boundary and its limits.

## Verification

- Final rebased head: full OpenCode driver suite, 64 synthetic tests
passed, and runner source TypeScript check passed. Original author run
had 61 passing tests before the new master tests.
- The two new explicit and ambient regressions fail on the old
implementation.
- Independent source review passed. The two new synthetic regressions
also passed independently. A separately filtered legacy pair hit fixture
selection/chmod ordering and is not claimed as a passing run.
- Tests use the real driver and proxy with a fake OpenCode child and
synthetic upstream transport. They check key exclusion, exact
URL/model/authentication, wrong-model and alternate-routing rejection,
proxy bypass preservation, redirect rejection, and proxy shutdown.
- The two advisory regressions failed before the correction: fallback
routing reached upstream, and ambient NO_PROXY was lost. The full
64-test driver suite and source TypeScript check pass after the
correction.
- No real OpenCode SDK/provider qualification was run. The original WAL
write mechanism remains unknown.
- Repo-wide typecheck, test:run, and build were not run locally because
local native/DB/model execution is excluded. Normal PR CI passed on head
`3e1903272ce65b92055ea70f8dc586d9aa5e0205`: typecheck/release registry,
general and serialized suites, runner static/Rust/Vitest checks, E2E
shards, build, and canary dry run. Greptile is 5/5 on that head.
Paperclip Review is neutral with no blocking findings; its two earlier
findings are fixed and resolved.

## Risks

The native OpenRouter route now uses the existing OpenAI-compatible
proxy transport. Synthetic tests do not prove every live SDK response
shape. The loopback token remains a credential, is redacted, and expires
with the session. This change does not claim isolation of every child
secret or persisted value.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) assisted source investigation,
implementation, synthetic tests, and review with tool use. No provider
model call was used for verification.

## Checklist

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

> - Paperclip runs agents through a controlled execution boundary.
> - Native Runner starts ACPX providers through a TypeScript sidecar and
a Rust transport.
> - That transport hides arbitrary provider messages because they can
contain credentials.
> - Grok admission failures currently have no stable code. Other startup
failures can also lose their owning stage.
> - A real native startup failure therefore reports only
`classification=unclassified`, even when the ordinary subscription hello
test succeeds.
> - This pull request preserves fixed failure categories without
forwarding provider text or changing admission policy.
> - The benefit is a useful next diagnostic result before another
functional repair or retry.

## Linked Issues or Issue Description

Refs #17922 and #17942.

**What happened?**

A native Grok session failed before its first tool. Runner assets passed
verification. The Rust rejection discarded the cause because only closed
error codes may cross that boundary. The existing admission guard used
plain errors. Startup errors outside that guard could also lose their
stage.

**Expected behavior**

Report a fixed Grok admission reason, or a fixed startup stage when no
known error code exists. Keep credentials, provider messages, session
IDs, and paths out of the classification. Keep the failure and cleanup
effective.

**Steps to reproduce**

1. Have a Grok ACP fixture return a session without its native effort
acknowledgement.
2. Start it through the real ACPX client and pass the failure through
the sidecar classifier.
3. Before this change, the result is `acpx_sidecar_command_failed`. Rust
reduces that to `unclassified`.
4. The same loss occurs for injected sandbox, credential, and runtime
admission failures.

## What Changed

- Give Grok effort admission errors fixed codes for missing
acknowledgement, model or effort mismatch, session mismatch, conflicting
configuration, drift, and invalid protocol use.
- Record closed host startup stages in a private weak map. Preserve the
original error object, cancellation, and resource cleanup.
- Prefer existing known error codes over a fallback stage. Ignore
arbitrary provider-supplied stage properties and messages.
- Map only exact new codes to Rust diagnostic categories. Add real
ACPX-client and sidecar-pipe regressions with secret canaries and
unknown-code controls.
- Bind the changed shared source and new diagnostic modules in Copilot
profile 70. Preserve profile 69 and earlier history.
- Document the diagnostic contract. There are no dependency, lockfile,
workflow, auth, model, permission, or retry-policy changes.

## Verification

- Red before the production change: four TypeScript cases lost the
native reason or host stage. A Rust case returned `unclassified` for the
new closed categories.
- Final focused checks: 320 tests passed: 241 across sidecar
classification, Grok admission, the real ACPX client, recovery, runtime
adapter, and Copilot installation; all 79 host integration tests also
passed in isolation. These include nine startup-stage cases, translated
errors, actual missing Pi skill materialization, missing Copilot/Cursor
credentials, and a missing workspace binding.
- Review follow-up: a translated Copilot rejection lost its stage, and a
real Pi skill-loading failure reported configuration. Both regressions
failed before the two-line repair and pass afterward. Stage recording
now follows provider translation and starts before Pi skill acquisition.
The current unpublished Copilot 70 identity was regenerated.
- Formal review follow-up: missing Copilot and Cursor credentials
reported configuration. Both cases failed before the two-line stage
repair and pass afterward. A missing-workspace case also verifies the
separate binding catch.
- Seven Rust unit checks and 17 sidecar transport integration checks
passed. The pipe checks preserve known categories and reject unknown
suffixes without disclosing the provider message.
- `pnpm -r typecheck` and `pnpm build` passed. Rust formatting and the
generated profile/source identity checks passed.
- Host integration history is retained: one complete 73-case host run
passed. Other batches hit credential-port ownership errors in different
existing cases; the four new stage regressions passed. The final 79-case
host run passed after the last review fix. The prior intermittent lease
failures remain recorded and are not claimed fixed here.
- `pnpm test:run` was attempted and stopped after repeated embedded
Postgres bootstrap failures. The same local database failure predates
this change. Full CI must pass before merge.
- A metadata-only probe with pinned Grok 1.0.13, private HOME, synthetic
credentials, a local catalog, and no inference passed fresh Grok
4.7/High admission and cold restore. This is supporting ABI evidence. It
does not prove live subscription execution.
- Initial CI history is retained: server shard 1 failed its unchanged
final rate-limit slot test (two requests allowed instead of one). No
server policy code changed here. The review follow-up requires fresh
full CI; this is not claimed fixed.
- Second CI history is retained: chat shard 2 failed the unchanged Slack
session-sync quiet-queue test (three selects during the quiet window).
The first rate-limit failure did not recur there. No chat or server
policy code changed in this PR. Final head
654bc5aa21 passed all 61 contexts (56
success, four intentional skips, one informational neutral review). Both
final-head reviews are 5/5 with no new findings; the Paperclip app
publishes its completed review as an informational neutral check.
- Live native acceptance is still pending. After deployment, retry the
original bounded task and inspect its actual shell output, exit status,
run result, and saved task state. This PR fixes the evidence gap; it
does not claim the startup incident is resolved.

## Risks

- Shared startup failures can now receive a stage category. The private
weak map cannot import provider-defined fields. Known error codes keep
priority.
- A category could point at the wrong stage. Tests inject failures at
the installation, sandbox, credential, and runtime boundaries. Existing
cancellation and cleanup tests remain in place.
- The Copilot profile identity changes because shared source changes.
Historical identities remain decodable and cannot authorize a current
launch.
- The next live failure may require another functional repair. Admission
remains closed until the requested configuration is verified.

## Model Used

- OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact deployment 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 (focused checks; full-suite
environment failures 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-27 20:53:02 -05:00
DottaandPaperclip 7a8df30953 fix(runner): admit Grok effort through native session metadata (#17942)
## Thinking Path

> - Paperclip lets people manage AI agents for work.
> - Paperclip Runner must preserve each agent's model and thinking
effort.
> - The Grok migration in #17922 passes explicit effort to native
Runner.
> - The pinned Grok 1.0.13 CLI reports native session metadata instead
of standard ACP config options.
> - The standard effort guard rejects that valid session before the
first prompt.
> - This pull request binds model and effort on Grok session open and
verifies the native reply.
> - Restored sessions keep the selected effort instead of reverting to
Grok's default.

## Linked Issues or Issue Description

Related: https://github.com/paperclipai/paperclip/pull/17922

**What happened?**
A migrated Grok 4.7 agent with High effort fails at native session.open
before it can run a tool. Grok 1.0.13 has no standard configOptions
response and rejects session/set_config_option. Its native session
metadata supports the requested model and effort. A cold load also
resets effort to High unless the request supplies it again. The upgrade
banner also calls Grok “Codex”.

**Expected behavior**
The native session must acknowledge the selected model and effort before
a prompt. A cold restore must preserve both values. The upgrade banner
must describe the selected harness accurately.

**Steps to reproduce**
1. Upgrade a Grok agent to Paperclip Runner with explicit High effort.
2. Assign a bounded shell task. The pre-fix native session fails during
admission.
3. For the restore case, create a Low native session, close the process,
and load it without effort metadata. The pinned CLI reports High.

**Paperclip version or commit**
Observed at f60ac29cf1 with Grok 1.0.13.

**Deployment mode**
Cloud, with the board operator interface.

## What Changed

- Project the bound model and effort into native Grok session/new,
session/load, and session/resume metadata before transport writes and
observation.
- Require a correlated native acknowledgement with the exact model,
effort, and session identity. Reject conflicting metadata, selection
drift, stale connections, and prompts before admission.
- Connect lazy restored handles through read-only native session
inspection. Keep the existing process ownership and launch snapshot
checks.
- Replace Grok's unsupported standard config setter. Keep the existing
Claude effort path.
- Add behavioral guard cases and a real ACPX client fixture for fresh
and cold Low/High sessions. The fixture resets effort on restore if
metadata is absent, as the pinned CLI does.
- Publish Copilot profile v69 because its source identity includes the
shared runtime adapter. Preserve published v66/v67/v68 bytes and the
reviewed Grok v67 candidate as history. Keep old profiles closed for
launch.
- Explain the native protocol in the Grok Runner guide and use
provider-independent upgrade banner text.

## Verification

- Three native create/load/resume cases failed before the repair. The
pre-fix guard rejected the native metadata reply.
- Seven affected Runner test files: 234 tests passed after the master
merge. These include native Grok admission, the real ACPX transport
fixture, runtime ownership, Claude effort, and profile history.
- The review follow-up extends the same Low/High fixture through a
complete first turn after cold restore. It checks the repeated native
load, original session id, actual response event, and completed turn.
All 127 tests in the three affected Grok/adapter files passed again;
Runner typecheck and source identity checks also passed.
- All 167 existing agent form tests passed. Token gates and diff checks
passed.
- Workspace typecheck passed. Final Runner typecheck and generated
profile checks passed.
- Production `pnpm build` passed, including after the master conflict
resolution. Runner typecheck, profile history checks, and the 234
affected tests passed on the merged source. All 55 Rust ACPX library
tests also passed on the merged source.
- Real pinned Grok 1.0.13 metadata probes reproduced the unsupported
standard setter and native create/load/resume behavior. No model prompt
was sent. An earlier actual ACPX runtime probe passed fresh and cold
Low/High metadata checks. A repeat with an explicitly isolated HOME
failed authentication before session creation, so it does not count as
final live acceptance. The deterministic transport fixture is green; a
deployed shell task remains required.
- `pnpm test:run` did not complete locally. Embedded Postgres failed
during bootstrap after five attempts. This is the same local fixture
limitation recorded for #17922. Fresh PR CI must pass before merge.
- After deployment, retry the original bounded shell task with the saved
Grok 4.7/High configuration. Verify actual tool output, a successful
run, and Done state after reload.

- Final commit `810d84fd19728e7d798989582f26b05f69166db2`: all CI gates
passed. Greptile and the formal Paperclip review both reached 5/5. No
unresolved review threads remain.

## Risks

- This depends on the pinned Grok 1.0.13 native metadata format. Missing
or conflicting replies stop admission instead of silently changing
effort.
- Cold restores must make one read-only native inspection call before
admission. The existing handshake timeout and process ownership checks
still apply.
- The shared adapter changes Copilot's source identity. The new current
profile includes the final source hashes; the prior profile remains
decodable but cannot launch.
- This does not change the Grok CLI version, account selection, search
policy, dependency patch, or lockfile.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 17:53:58 -05:00
DottaandPaperclip 0a08d37aa0 feat(runner): recover controller authority without interrupting execution (#17097)
## Thinking Path

> - Paperclip manages agents and owns their business authority.
> - Runner owns execution transport, acknowledgements and replay.
> - A replacement controller must recover that transport without
starting another provider turn.
> - An external store can retain the required control records without
copying streamed text.
> - A duplicate local journal adds synchronous disk work without
providing the replacement server's authority.
> - This PR adds the optional recovery contract and its standalone
proof. Server adoption and browser delivery have separate owners.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

A surviving runner can reconnect to a replacement controller with its
admitted process, session and active turn.

**Current behavior**

Local controller files do not provide recovery on empty replacement
storage. Rewriting those files after an external checkpoint is installed
also blocks normal controller work.

**Proposed behavior**

An optional callback stores opaque checkpoints. The replacement restores
that checkpoint before it constructs the controller. Installing the
callback makes the external store authoritative. Local storage holds a
marker that requires restoration. Consumers without the callback retain
their file journal.

PR 1 of four: #17097 → #17439 → #17455 → #17456. Related work: #17390
and #17361. The pre-split reference remains
`codex/hot-upgrades-reference-2026-10-24`.

## What Changed

- Add opaque checkpoint encoding, restoration, incremental persistence
and authenticated sparse recovery cursors.
- Keep authentication, commands, semantic inputs and lifecycle events
behind their commit barriers. Share semantic-call ownership between live
dispatch and recovery.
- Keep streamed text out of recovery checkpoints. Preserve bounded
retention, original deadlines and admitted process identity.
- Stop normal local journal writes after external persistence is
installed. Fail closed on a local marker until external restoration
occurs. Preserve current master's staged file writes for standalone
consumers.
- Keep provider-native admission and authorization behind adapters.
Preserve historical Copilot attestations and bind the merged launch and
transport sources in v68; preserve published v66 and prior development
identities.
- Add the one-process scripted executor fixture and deterministic
outage, replay, failure and backpressure tests. Add no production test
endpoint or auxiliary process.

## Verification

The completion-recovery correction passes three restart regressions that
fail before its respective transport/driver fixes. All 230
controller/attestation cases, all 302 Codex transport cases in the full
repeat, and all three one-process fixture cases pass. The broader
Codex/Dot/Muse run passes 326 cases and times out one existing mid-goal
case; its isolated retry and complete Codex repeat pass on unchanged
source and binaries. The initial timeout remains recorded. Conformance
and replay parity pass.

Historical v65/v66 attestation bytes remain frozen; v67 binds the
changed transport. The local runner-only API-authority lane passes 2,027
cases but its 47 HTTP cases cannot initialize embedded Postgres on this
Mac. The integrated owned-database HTTP path is verified in PR 2. At
preceding head `0d8d1b8250`, the Actions workflow passes after one retry
of runner-service shutdowns. Greptile is 5/5 with no unresolved threads.
The interrupted attempt is retained. All checks on that preceding head
are terminal and green/neutral/skipped.

Run `pnpm --filter @paperclipai/paperclip-runner exec vitest run
src/control-plane/durable-prp-control-plane.test.ts
src/live/runnerd-codex-transport.test.ts --maxWorkers=1` and `node
packages/paperclip-runner/scripts/copilot-profile-identity.mjs --check`.

The [qualification
record](https://github.com/paperclipai/paperclip/blob/codex/hot-upgrades-qualification/doc/plans/2026-10-22-hot-upgrade-qualification.md)
retains exact revisions, failed attempts and qualification limits. The
local cost campaign observes zero hot-path local journal fsync calls. It
does not qualify a native harness or hosted deployment.

Master reconciliation `d5fc443626` preserves the published v66 and prior
development identity bytes and binds the combined transport in v68. All
290 focused runner/profile cases and runner typecheck pass. The first
sandboxed invocation cannot open loopback listeners; the permitted
repeat passes. Fresh CI and Greptile are pending for this updated head.

Current merge candidate `4fb3d1835b` also fixes public-reader
publication before external commit. New held/rejected-write cases fail
before correction and pass afterward. The full controller repeat passes
168 cases. The combined lane passes 390 other
recovery/transport/profile/fixture cases; its first two overlap fixture
failures are retained and corrected to observe callback entry instead of
provisional state. Runner TypeScript build and typecheck pass.
Current-head GitHub Actions is green and Greptile is 5/5 with all
threads resolved. The superseded master-reconciliation CI shutdown
remains recorded.

## Risks

The persistence callback is an acknowledgement barrier. Failure must
stop delivery. A consumer that installs external persistence must
restore its committed checkpoint before restarting; the marker is not a
recovery snapshot. Sparse display recovery does not reconstruct
acknowledged text or repeat execution. This slice has no Postgres
schema, application authorization or browser behavior.

## 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
- [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:10:32 -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
3cd3af5d75 Trace native preparation and OpenCode execution phases (#17918)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Each native run prepares its workspace and skills, then starts its
provider.
> - A long preparation span does not show whether inventory refresh, a
cache lock, repository reads, or file checks caused the delay.
> - One hosted run spent 81 seconds in this phase. The same deployed
service and pinned files took 2.55 seconds in a separate diagnostic
process.
> - Another hosted turn spent 69 seconds before its first output. A
matched public-workspace local model replay took 7.64 seconds.
> - We need skill preparation and provider-internal measurements before
choosing another fix.
> - This pull request adds skill spans, a real-service benchmark, and
opt-in filtered provider timing.
> - The benefit is a faster and more precise diagnosis loop.

## Linked Issues or Issue Description

Refs #17620. That PR owns the batched read optimization. This PR adds
diagnostics and does not change its read policy.
Refs #17907. That PR protects long cache lock transactions from the
database idle timeout.

**What happened?**

Native skill configuration can take much longer than matched standalone
resolution. Provider execution also has long gaps with no internal
timings. Existing spans cannot separate inventory refresh, cache
acquisition, repository reads, context loading, Git snapshots, or model
streaming.

**Expected behavior**

An operator-configured trace shows these phases under the existing run
context. Without an OTLP endpoint, the new spans stay off. A local
benchmark can reproduce the service path with real PostgreSQL, files, an
agent actor, and a responsible user.

**Steps to reproduce**

1. Run `pnpm --filter @paperclipai/server exec tsx
scripts/benchmark-native-skill-preparation.ts --actor=agent
--staging-shape=true`.
2. Inspect cold and warm phase timings, SQL counts, and file
verification results.
3. Set the existing operator OTLP configuration and add
`--export-otlp=true` to inspect the same hierarchy in the collector.

## What Changed

- Add bounded skill inventory, refresh wait, cache acquisition, row,
version, repository, file check, and consumer spans.
- Keep the existing endpoint gate, attribute allowlist, cache locks,
authorization, file validation, and durable pin boundary.
- Add a standalone benchmark with a full repository fixture, immutable
snapshot input, calibrated local transport delay, and optional OTLP
export.
- Verify every delivered file and executable bit outside the timed
section. Create its fixture agent through the lifecycle API.
- Add an opt-in authenticated loopback sink for OpenCode. Discard raw
attributes, logs and content. Retain only closed phase names and
timestamps.
- Carry one bounded diagnostic batch through the real proxy, Rust
normalization, durable journal and server trace projection. Group
provider phases under their execution parent.
- Freeze the Date clock in an existing delegated Slack rate-limit test.
This fixes a CI failure when consecutive requests cross a rate-window
boundary. It does not change rate-limit behavior.
- Document phase boundaries and the difference between SDK startup and
confirmed ingestion.

## Verification

- Skill service, runtime selection, concurrency, cache and timing
suites: 122 tests passed with real PostgreSQL and migrations.
Enabled-span integration tests also passed. They verify parent
relationships and a real advisory-lock timeout.
- A captured 208-file repository produced 209 verified runtime files.
The benchmark uses real agent and responsible-user authorization. The
lifecycle fixture correction passed with the staging-shaped inventory.
- Affected OpenCode driver, collector and transport tests: 72 passed.
The tests cover authentication, content removal, size/count bounds,
disabled behavior and the rebuilt native Runner boundary. One Rust
projection test and 18 server trace tests also passed. A held run-log
sink proves that a full 128-span diagnostic batch adds no duplicate
database writes before terminal consumption.
- The two CI-failing delegated Slack rate-limit cases passed against
real PostgreSQL with only the Date clock frozen.
- Runner TypeScript and server TypeScript checks passed. Rust formatting
and module-boundary checks passed.
- Real Honeycomb readback confirmed the 14-span skill waterfall and a
40-span provider waterfall. Provider phases have the correct execution
parent. The provider export uses synthetic model replies and is
instrumentation proof only.
- Earlier full local checks failed on missing package-local executables,
then on the default Node heap and a missing generated service worker.
The dependency links were repaired. The server check passed with a
larger heap. The full local test attempt could not start embedded
PostgreSQL on this host and was stopped after retaining its failures;
real database coverage uses an isolated database on an existing local
server. These attempts do not count as a full local pass.
- CI on the prior revision passed typecheck, build, Runner and all E2E
shards. It failed the benchmark lifecycle boundary and one existing
rate-window test. Those fixes passed CI. A later Runner assertion
exposed the Copilot source identity pin on the shared transport file.
The diagnostic flag now uses the existing configured-environment
projection, preserving that file byte-for-byte. All 66 selected
installation and native transport tests passed. New-head CI and review
remain required.
- The under-15-second hosted response target remains unmet. This PR adds
diagnostics and does not claim a hosted latency fix.

## Risks

- Skill spans and Honeycomb export retain the operator endpoint gate.
OpenCode phase collection requires a separate explicit diagnostic flag.
Without an endpoint, its closed measurements stay in the instance run
log.
- Raw OpenCode OTLP can contain prompts and authorization attributes.
The new sink rejects unauthenticated requests and discards all
attributes before any measurement reaches PRP or the operator collector.
Request, event and per-phase limits bound memory and journal growth.
- Collection does not wait for a provider flush. Late or oversized
exports can be absent; these measurements are not a complete profiling
guarantee.
- The benchmark's inventory contents and transport delay are explicit
fixtures. They do not reproduce server contention or prove hosted
response time.
- The one durable diagnostic batch remains the local evidence. Its child
span export does not add per-phase run-log rows.
- No database migration, authorization policy, model selection or
inference transport changes. The Rust Runner and OpenCode proxy must be
shipped together for the new opt-in diagnostic.

## Model Used

OpenAI GPT-6 through Codex, with repository inspection, shell execution,
browser tools, and Honeycomb queries. The session does not expose a
verifiable backend 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
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Paperclip <paperclip@paperclip.ing>
2026-10-27 14:53:32 -05:00
DottaandPaperclip db70c5acd9 fix(runner): retain startup Stop and exhaust reconnect recovery (#17812)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators must be able to stop a remote runner while it starts.
> - Remote artifact staging can finish after the transport's bounded
cleanup wait.
> - The launcher discarded an early Stop request and could dispatch
after staging.
> - A separate path missed the runner's plain-text reconnect expiry
receipt.
> - This change retains startup cancellation and ends an exhausted
reconnect incident.
> - Public package imports and a source-bound profile keep the
regressions buildable and admission checks intact.

## Linked Issues or Issue Description

Related work: Refs #16835, Refs #16843, Refs #16855.

**What happened?**

The HTTP Stop route returned 200 and recorded a cancelled run. After
bounded bootstrap cleanup, releasing artifact staging still dispatched
one launch RPC. A separate reconnect test accepted a replacement after
the runner reported that its grace period had expired.

The first PR head also failed CI. The HTTP regression imported Runner
source across the server TypeScript boundary. Its event receipt mock
read a field that is not present on both event forms. The changed
transport also invalidated the pinned Copilot source identity.

**Expected behavior**

A cancelled launch must remain cancelled after staging. An exhausted
reconnect receipt must end that incident. Regression tests must use
public package contracts. The source identity must cover the changed
transport without replacing historical profile bytes.

**Steps to reproduce**

1. Hold the remote launcher's artifact staging promise.
2. Call the board Stop route and let bootstrap cleanup reach its
preparation deadline.
3. Release staging and count launch RPCs.
4. For reconnect expiry, end an owned runner with its coded or
plain-text expiry message.
5. Run the server typecheck and the Copilot profile identity check.

## What Changed

- Retain cancellation through staging, trace publication and an
in-flight launch RPC.
- Apply a deferred signal through the existing identity checks when the
launch identity arrives.
- Preserve an earlier KILL request when a later TERM request arrives.
- Recognize both coded and plain-text reconnect expiry receipts.
- Test the real board Stop route and heartbeat cancellation with
PostgreSQL. Use public Runner exports and handle both event receipt
forms.
- Generate source-bound Copilot profile v65 after integrating current
master. Preserve exact published v62, v63 and v64 fixtures, retain the
earlier v63 reconnect candidate as historical evidence, and reject
historical profiles for a current launch.
- Document process evidence, retained uncertainty and the limits of
cleanup and continuation evidence.

## Verification

- At current integration head
`2b96ee3adcb3be642c538436113e1159d92f843d`, launcher and HTTP Stop
regressions: 21 passed. This includes the existing process-generation
and exact-exit safety cases on the integrated base. The HTTP case
includes bootstrap expiry; it is not isolated Stop-only settlement
proof.
- At current integration head, reconnect expiry regressions: 2 passed,
for coded and plain-text receipts.
- At current integration head
`2b96ee3adcb3be642c538436113e1159d92f843d`, the Copilot installation and
identity suite passed all 63 tests and the canonical generator check
passed. Before regeneration, the merged-tree admission test failed with
a transport source hash mismatch and the generator reported a stale
identity. Published v62, v63 and v64 bytes remain unchanged; the prior
reconnect candidate is preserved separately. The v62 fixture SHA-256
remains
`faa4d1b35267b54e134a8e0c84586fe1196d8fad5525cb53aa195aae53ca6e83`.
- Current integration head passed all 86 focused tests, the full
recursive repository typecheck and the root repository build. The normal
server typecheck also passed, including its full Runner release rebuild.
- Historical full recursive repository typecheck and the root repository
build passed at `187bb85b4fa1fbd2ffaec992650a1c8557df9ebe`. Server
typecheck also passed through the normal package script and a direct
full server TypeScript check. The prerequisite full Runner release build
passed.
- The historical HTTP baseline returned 200 and dispatched one late
launch RPC. The repair returned 200 and dispatched zero in the bounded
fixture.
- Earlier failures remain part of the evidence: the first head failed
TypeScript package boundaries and source identity. One local HTTP run
failed before migrations; it passed after the disposable test database
received normal migrations. Earlier sandbox-wide checks ran out of
memory or lacked Cargo. Those runs did not pass.
- Historical head `187bb85b4fa1fbd2ffaec992650a1c8557df9ebe` received
Greptile 5/5 with no actionable findings and all hosted gates passed in
run `40412261957`: 53 successful check runs, four expected skips and a
successful legacy Snyk status. Those results predate the master
integration and do not establish current-head readiness.
- Current integration head `2b96ee3adcb3be642c538436113e1159d92f843d`
includes master `bd382eee536f4ada680072b1cc19100163c3d04a`. All
current-head hosted gates passed in run `40512885858`: 53 successful
check runs, four expected skips and a successful legacy Snyk status,
with zero pending or failed checks. Build passed at 13:42:36 UTC and the
final `ci / verify` aggregate (job `122224566238`) passed at 13:43:00
UTC on 2026-10-27. Greptile reviewed exact head
`2b96ee3adcb3be642c538436113e1159d92f843d` at 5/5 (updated 2026-10-27
13:36:41 UTC), with no actionable findings and no open inline threads.
The hosted partitions passed full-suite verification, including browser
and release gates. The wider qualification limits below remain in force.
- Local setup on current master initially failed frozen install with
`ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` because `patchedDependencies`
differs from the lockfile. Pinned pnpm 9.15.4 hydrated dependencies with
`--no-frozen-lockfile --ignore-scripts`; its generated lockfile change
was restored. This PR changes no lockfile or workflow.
- Reproduce the Stop tests from `server`: `pnpm exec vitest run
src/services/native-runtime/native-session-executor.test.ts -t 'remote
runner process supervision|HTTP Stop during remote runner staging'`. The
test accepts a guarded disposable `_test` database through
`PAPERCLIP_TEST_DATABASE_URL`, or starts its normal embedded database.
- Reproduce reconnect tests from `packages/paperclip-runner`: `pnpm exec
vitest run src/live/runnerd-codex-transport.test.ts -t 'does not restart
an exhausted reconnect'`. Build the normal test runner first.
- Reproduce profile checks from `packages/paperclip-runner`: `node
scripts/copilot-profile-identity.mjs --check` and `pnpm exec vitest run
src/drivers/acpx/copilot-installation.test.ts`.

## Risks

- The wider qualification is incomplete. Verified-stopped replacement
and concurrent recovery plus Stop each entered two physical provider
processes. Both fail the original requirement of at most one physical
provider entry. Passing fixture assertions do not make all incident
scenarios accepted.
- HTTP concurrent recovery, shared provider-attempt accounting,
server-admitted restored continuation, live-provider behavior and
product cleanup settlement remain unrun or unproved.
- Accepting a deferred signal is not proof that a dispatched process
stopped. The existing monitor remains authoritative.
- The HTTP test uses the real route, heartbeat cancellation and
PostgreSQL state. Execution lease and event ports, plus the launch RPC,
are controlled fixtures. Bootstrap expiry participates in this case.
- The local incident matrix uses an installed runner binary and a
scripted provider. It does not qualify a live provider. Local fixture
teardown does not certify product cleanup settlement.
- This change does not authorize historical turn replay. It does not
change ownership, pause, approval or provider-attempt gates.

## Model Used

OpenAI Codex, GPT-6 family. The runtime does not expose the exact
serving model ID or context-window size. The agent used reasoning,
repository inspection, shell execution and connected GitHub tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:45:00 -05:00
DottaandPaperclip 13709b4c7a feat(connections): let agents configure connections within delegated authority (#17737)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections provide governed tools, chat channels, model accounts,
and gateways.
> - Several management routes require a human board actor even when an
agent has the required grant.
> - Default agents must configure these resources within the responsible
user's authority.
> - This pull request adds a shared authorization path to the existing
REST and native API surface.
> - Human authentication, execution approvals, and local host boundaries
remain enforced.
> - The benefit is that a standard agent can complete authorized setup
with a bounded human handoff.

## Linked Issues or Issue Description

**Subsystem affected**

Server authorization, connection services, shared contracts, native API
discovery, database schema.

**Problem or motivation**

Connection administration is available in the web app but often
unavailable to agents. Agent grants, responsible-user authority,
credential ownership, and actor attribution need separate checks.
Opening gateway-token creation also requires preserving the issuing
agent's delegated authority during token use.

**Proposed solution**

Use the existing authorization evaluator for every connection family.
Enforce current responsible-user authority, effective trust, grant
scope, resource visibility, and target-agent access. Keep existing agent
grants unchanged. Expose authorized configuration through default
`search_api` and `call_api`. Save human authentication steps and let
agents continue after completion.

**Roadmap alignment**

This change completes the API access path for the existing Connected
Apps, Personal & Shared AI Accounts, and governed MCP Gateway
capabilities in `ROADMAP.md`. It follows the maintainer's requested
design. Related work: #11899 enforces connection execution access and
creator/manager rules; this PR extends agent management across
connection families. It does not replace that execution-policy work.

## What Changed

- Add shared connection management context and mandatory
responsible-user, trust, scope, and target checks.
- Allow authorized agents to configure tool, chat/email, GitHub/Slack,
AI, profile, and gateway resources through existing routes.
- Preserve human credential ownership and record the actual agent,
responsible user, and run or key in audit data.
- Preserve saved browser authentication handoffs and callback session
checks.
- Bind agent-issued durable gateway tokens to their responsible user and
recheck delegated authority at use.
- Add explicit REST transport and management capability metadata,
built-in guidance, and sensitive-response handling.
- Intersect caller and endpoint-agent Slack test/invitation policies,
including independent and shared rates. Require the addressed human’s
current endpoint identity link before completing identity handoffs.
- Add production-authenticated integration scenarios. Companion #17739
contains the saved setup UI (including the required human
import/rotation step), product and permission documentation,
catalog/Vercel credential and callback ownership, and operation maps to
keep each review below 100 files. Both PRs must ship together; merge
this implementation first, then its companion.

## Verification

- Current implementation head:
`2ecd6451d0d0c8d82121a4e3fa4ce94c5befbbd6`, including master
`ea727dc3c2`, 99 files. The latest follow-up fixes the two valid
findings from the preceding f9 review. Exact-head Greptile has completed
at5/5 with no findings and Superagent passed. Full exact-head Linux CI
workflow40446606056 completed SUCCESS; only the queued external
Paperclip Review remains pending; earlier Linux passes do not qualify
this successor.
- Latest preserved-stack verification passed **2,165 tests** in fresh
PostgreSQL: **70 actual-auth scenarios**, 27 OpenAPI contracts, 2,022
native API tests and 46 saved GitHub wizard cases. **141 existing
gateway/policy acceptance tests** also passed. Workspace
typecheck/build, maps and token gates passed. The first workspace
typecheck was blocked by sandbox tsx IPC permissions; its authorized
rerun passed. This is focused local evidence; the full Linux CI matrix
is still required.
- Issuer/target gateway policy regressions were red before the fix. Both
decisions now intersect, including Block/Ask first/rates, same
credential identity and current token/user/agent authority after
approval. Invocations retain their token and actual requesting agent;
deleted tokens fail closed. Thirteen actual-auth cases cover revocation,
narrowed scope, approvals, shared rates and board compatibility.
Intermediate missing-token attribution, review-context and
implicit-session actor failures remain in the qualification record; all
final cases pass.
- Activity pagination now retains a bounded cursor across private-only
windows. The actual-JWT regression reaches three older readable events
after 27 private ones without exposing private details. A native
device-login regression was red for plaintext receipts; local check and
test-call results now use existing protected-response handling. The
passing actual-auth case proves encrypted persistence, exact replay,
redacted history and no response asset.

- Previous-head `5b55195593` Linux CI initially failed e2e shard 4/8 in
the existing connection-intent continuation test: periodic recovery
queued a repair at 01:21:47, the scripted journey completed the task at
01:21:48, and the extra queued run was cancelled at 01:21:49 because the
task was terminal. The assertion selected that latest cancelled run.
GitHub refused the first attempt while the workflow was nonterminal.
After completion, the single evidence-supported failed-job rerun was
accepted as **attempt 2** on the same head (workflow 40431202466). The
failed shard and final E2E aggregate passed on attempt 2, and the
complete Linux workflow for that head is successful. The original
failure remains part of qualification. No additional unchanged-code
rerun will be used for this failure.

- Companion CI also has an unchanged login-cleanup idleness timeout,
retained in its qualification record. That same 16-case suite passed in
this parent Linux run and a fresh local database. Both preceding
workflows passed after their single failed-job reruns as attempt 2; the
original failures remain recorded. No additional unchanged-code rerun
was used.

- Migration `0380_broken_aqueduct.sql` was regenerated through the
repository workflow after master took 0379 for project Git
authorization. It adds the responsible-user column with `IF NOT EXISTS`,
preserves upstream migrations, and satisfies snapshot retention and
migration safety checks.
- Upstream published Copilot v62 and v63 identities remain byte-for-byte
unchanged. The combined guidance is now v64, digest
`sha256:22e31f95ef972bcead98a4a707c9f33433558fd111e390e027a2bbb4346e112a`.
The normal shared TypeScript/Rust identity check and **61 Copilot
installation tests passed**. The old source-identity assertion first
failed against unchanged published v63; regenerating a new v64 preserves
the published release.
- Workspace `pnpm -r typecheck` and `pnpm build`, map validation, and UI
token gates passed on the final combined stack after the upstream merge.
Node 24.22.1 / pnpm 9.15.4 were used.
- **Earlier 82 API/OpenAPI tests passed** in fresh PostgreSQL 18: 55
assembled-server scenarios and 27 contracts. They use real persistent
agent keys, run JWTs, human sessions, production defaults, and
deterministic provider fixtures. No actor injection establishes access.
- The new email regression was red before per-account scope filtering.
The Arcade regression was red before human ownership and inventory-key
fixes; it also verifies actual-agent audit identity and a human-session
inventory read. The activity regression measured **200 authorization
checks before the fix and one afterward** for the same one-item page.
- **82 GitHub UI tests passed**, including all three new
failed-replacement regressions that were red before their fix. The UI
preserves an earlier copy only after confirming its committed
generation. Changed or unreadable results block copying and reconnecting
until reconciled. Human-only secret responses now include their
nonsecret committed generation.
- Private test status now rechecks the originating principal and linked
task, including mandatory agent/responsible-user privacy. Cross-agent
tests require the full caller tool access decision and the same
credential identity, regardless of auth label; caller and target
policies/approvals and rate limits apply before execution and after
human approval. A profile-only precondition was found to reject valid
allow-policy and scoped-grant access and has been removed. Both
permitted-access cases and a no-auth-label identity regression were red
before the correction; caller-specific Block still prevents provider
execution. The private-status regression was also red before its fix.
- The tool-activity regression measured 100 capability decisions and 102
run captures on a 100-event page before the fix. It now uses two task
decisions and at most two captures while retaining the same 50 visible
events, private-event filtering, and 403 after audit-grant revocation.
The regression was red before request-context reuse and task-decision
sharing; final server typecheck/build also pass.
- Generic chat configure/reconnect now hands agent-supplied verification
credentials to the addressed human before provider work or vault
changes. Actual key/JWT regressions were red for Slack signing-key
replacement and generic channel secret-reference rebinding. They now
prove unchanged refs and vaulted signing value, human setup, permitted
agent bot-token repair, and governed test messages. All 82 API/OpenAPI
cases pass in fresh PostgreSQL. Eight native receipt protections and
final server typecheck/build also pass.
- The preceding review found that old healthy state could retire a
credential-entry card before a human changed anything. The actual-JWT
regression was red. Saved field generations now change only with
protected values and commit with refs plus a verification fence; retries
retain the baseline. Old health, bot-token repair and unchanged entry
stay pending. New signing verification and current authority permit
continuation. A separate red race proved that user revocation during
provider authentication could return 403 after refs changed; authority
is now checked before persistence and inside the credential transaction.
The final 82 API/OpenAPI cases, four neighboring real-database
Slack/GitHub lifecycle cases, and final server typecheck/build pass.
- A preceding full run crossed a rate-window boundary. Database rows
prove one consumed slot at 23:35 and another at 23:36 for the same
policy/bucket. Only Date is frozen in the rate test cases; transport and
asynchronous timers remain real. Production rate behavior is unchanged,
and the final full run passes. An intermediate fixture failure that
overwrote hidden generation metadata with an API projection is retained
in the qualification record.
- Linux CI on an earlier head found two rate-admission assertions that
omitted the newly persisted bucket key. The failures were reproduced
locally; both assertions now verify the exact actor/tool bucket and all
49 policy-service tests pass. The companion qualification record retains
the initial and intermediate failures. Catalog creator attribution is
preserved in the companion to keep this implementation review at 99
files.
- The latest review reproduced three regressions before repair: complete
human replacements failed on unavailable old signing secrets, fresh
GitHub links incorrectly selected reconnect, and different
credential-entry requests shared an idempotency key. Each old protected
ref now has a narrow known-unavailable fallback; unexpected resolver
failures and company/scope violations still abort. Fresh imports keep
their credential form, configured endpoints keep reconnect, and
canonical field sets/completion modes distinguish handoffs while
matching retries retain their baseline. All 55 actual-auth scenarios and
27 separately run OpenAPI contracts pass, as do server typecheck/build.
Companion #17739 also passes all 41 wizard tests including actual
fresh-form submission, UI typecheck, maps and token gates. Earlier red
results and a mistyped OpenAPI filename are retained in qualification.
- The configured GitHub handoff regression was red in the
browser-component tests and actual-auth link/persistence tests. Saved
links now name requested fields and all/any completion mode; the
companion form submits those supplied fields through reconnect and
retains other saved credentials. Webhook/client-secret reconnect remains
human-only; first-setup secret restrictions remain. All 46 wizard tests
pass, including combined modes and legacy links. A duplicate review
referenced the older companion bf760912; the current form is already
fixed, linked in the reply, and its thread is resolved.
- Linux CI on bf760912 failed automatic Slack provisioning because vault
persistence cleared an already verified manifest-update challenge. The
same regression was reproduced locally. The provider-owned helper now
preserves proof only for the current signing fingerprint and callback
URL. Eight existing compatibility cases pass, including this case and
initial GitHub secret rejection. The first uncommitted GitHub-field
variant also failed that initial boundary and was narrowed to reconnect;
both failures remain in qualification.
- The upstream merge conflicted only in generated migration metadata.
Upstream 0379 is preserved, normal generation/pruning produced 0380, and
two repeated applications of the idempotent additive SQL passed. The
final combined stack passed **128 tests** (55 actual-auth, 27 OpenAPI
and 46 wizard cases) in fresh PostgreSQL. Eight Google UI cases also
pass; the two protocol cases could not initialize embedded PostgreSQL in
this fresh local attempt. Their earlier passing evidence remains
historical; fresh Linux CI must execute them. Vercel personal credential
attribution is preserved in companion #17739 with its other
ownership/consent follow-ups, keeping this PR at 99 files.
- The suite covers fresh defaults, restricted users/agents, scopes,
personal isolation, token revocation, human handoffs, callback replay,
execution approvals, authorized self-targeted policy changes,
self-approval denial, and current authority before commit. Reproduce API
checks with `pnpm exec vitest run
server/src/__tests__/connection-management.integration.test.ts
server/src/__tests__/openapi-routes.test.ts`, using a fresh database
through `PAPERCLIP_CONNECTION_MANAGEMENT_TEST_DATABASE_URL` or the
default embedded test database.
- Companion #17739 also records consent separately from token refresh so
saved Google choices survive refresh. Its eight service-picker and two
local-HTTP OAuth tests pass; both new UI cases were red before the fix.
Normal migration generation confirms no SQL change is needed for the
additive JSON metadata.
- The integration module shares one assembled server, authentication
factory, and provider lifecycle to preserve the
HTTP-to-vault-to-task-continuation proof. A reused external database
caused a Slack fixture identity conflict; the fresh final run passed.
Earlier fixture/transport and contract-update failures remain in the
companion qualification record.
- The broad local `pnpm test:run` attempt remains blocked by macOS
embedded PostgreSQL's host semaphore limit. It is not a clean pass. The
fresh Linux CI matrix must complete. Provider fixtures do not prove live
setup or an empirical LLM success rate.
- A current-head completed Paperclip assessment is not yet recorded. Its
earlier external recovery boundary has not been bypassed, and no
incomplete assessment is reported as passing. The user authorized both
merges when checks pass; merge this implementation first, then replay,
retarget, and requalify companion #17739 against the squash-merged
master.

- After the master refresh, local workspace typecheck/build, **97
actual-auth/OpenAPI cases** and **141 gateway/policy cases** pass. The
original fixed database port was occupied; Docker assigned a free
localhost port. The first neighbor setup command could not resolve root
`tsx`, leaving its schema uninitialized; the built database package
migrated the separate fixture and all unchanged cases passed. Both setup
failures are retained in qualification. Fresh Linux CI remains required;
no full local test-sweep pass is claimed.

- The f9 Greptile review scored **2/5** for two reproduced findings:
Slack test sends skipped the caller’s tool policy, and healthy App
credentials completed an unconfirmed identity handoff. Both are fixed in
this head and have resolved evidence threads
([Slack](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927765),
[identity](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927895)).
Actual key/JWT cases cover twelve Slack caller/target/recipient
combinations; the human-session GitHub OAuth callback alone remains
pending until explicit confirmation. All **99 API/OpenAPI tests** (72
actual-auth + 27 contracts), workspace typecheck and build pass. On the
combined companion, all four focused cases (including the twelve Slack
combinations), typecheck/build and maps also pass. The continuation
suite’s 50 embedded-PG cases were skipped because its database could not
start locally; fresh Linux CI must run them. Initial fixture
credential-collision and audit-projection assertion failures are
retained with the red reproductions in the companion qualification
record. No full local sweep or live consent is claimed.

## Risks

- The maintainer explicitly confirmed authorized policy administration,
including self-targeted changes that loosen controls. These writes
require management grants and the responsible user’s current authority.
Agents cannot approve their own governed action requests or edit their
own principal permission grants. The actual-auth regression exercises
both permitted administration and those denials.
- This is a broad authorization change. Incorrect scope or owner
resolution could deny permitted setup or expose another user's
resources. Integration cases cover both permitted and denied requests
with actual authentication.
- The additive nullable gateway-token column does not infer identities
for legacy clients or backfill agent grants. Legacy agent tokens without
a responsible user fail closed.
- Provider fixtures test supported setup and callback contracts. They do
not prove live provider availability.

## 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 suites above;
full local sweep remains blocked as documented
- [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 — exact `2ecd6451d0` Linux CI
completed SUCCESS; external Paperclip Review is still queued
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
exact `2ecd6451d0` review completed; both f9 findings have resolved
evidence replies
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:20:24 -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
Nicky Leach e61ee4b005 fix(runner): preserve Claude user settings trust in HOME (#17826) 2026-10-26 18:02:15 -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 125ddcabe5 perf(runner): keep event journal writes off the HTTP thread (#17745)
## Thinking Path

> - Paperclip lets people manage AI agents and their work.
> - The HTTP server also owns durable Runner state.
> - Each committed event rewrites and flushes that state on the HTTP
thread.
> - Large journals and slow writes delay unrelated navigation and saves.
> - Event acknowledgements must still wait for durable storage.
> - This PR stages output writes asynchronously and joins them before
writer replacement.
> - The board can serve requests while Runner output waits for storage.

## Linked Issues or Issue Description

Refs: #17507. Related: #17514 reduces writes per event burst. This PR
moves individual output writes and file flushes outside the HTTP thread.

**What happened?**
A live CPU profile spent about three seconds of a 13-second sample
serializing and synchronously writing Runner state. Representative
journals were about 9 MB. Unrelated task requests had multi-second
delays.

**Expected behavior**
A slow output-journal write must leave unrelated HTTP requests
responsive. An event must not be acknowledged before it is durable.

**Steps to reproduce**
Hold an authenticated output event's file flush in the durable protocol
test. Send an unrelated HTTP request during that flush. Also save a
command, reconnect, or retire the controller during the write.

## What Changed

- Stage `item.delta` snapshots with asynchronous file writes and file
flushes. Keep lifecycle, control, authentication, and tool events
synchronous so transport readers observe durable boundaries.
- Fence publication by saved revision. An older snapshot cannot replace
newer commands or connection state. A failed write fences the writer.
- Write compact JSON and share private-file checks. Existing journals
remain readable.
- Stop external ingress before joining admitted writes. Checkpoint only
after retirement succeeds. Close reports a failed detach consistently
and releases notification consumers.
- Add real HTTP and Rust transport cases for held writes, reconnects,
commands, failure, restart, close, and timeout.
- Add immutable Copilot source identity v61 for the changed shared
transport. Preserve v60, historical decoding, exact-current launch
checks, and qualification flags. No new live Copilot qualification is
claimed.

## Verification

- Head `6f5c92e778`: workspace `pnpm -r typecheck` and `pnpm build`
passed. All CI gates passed in [run
40356159484](https://github.com/paperclipai/paperclip/actions/runs/40356159484),
including both full Runner shards. Fresh Greptile review is 5/5; all
findings are resolved.
- Current-base focused verification passed 300 cases across protocol,
real Rust restart/continuation, permission, backend, and
immutable-profile suites. The complete transport suite also passed 286
cases before the base refresh.
- Earlier iterations exposed lifecycle visibility, late writer
publication, and close-order failures. Controlled regressions reproduced
each before repair. CI also found missing test-peer drain methods and a
stale source fingerprint; both are corrected. An older broad local test
run was stopped after its source was superseded. No full local-suite
pass is claimed; full coverage passed in isolated CI.
- A synthetic 9 MB journal comparison used 20 writes per sample and
concurrent HTTP probes, with alternating baseline/treatment order. HTTP
median changed from 31 ms to 2–3 ms; p95 changed from 51–85 ms to 12–21
ms. Parsed output was equal. The asynchronous loop served 125–153 probes
versus 19–20, and took longer overall (992–1069 ms versus 675–678 ms).
This proves local I/O responsiveness, not deployed application latency.
- Deployment and live save/archive acceptance remain pending.

## Risks

Persistence interleavings affect restart authority. The tests cover
concurrent commands, replacement, failed storage, and reopening the
journal. JSON serialization, atomic rename, directory flush, and
control-event writes remain synchronous. This change still rewrites
whole journals. Incomplete retirement retains recovery evidence and
fails the close. A new exact-current Copilot source identity can reject
an older launch identity; historical decoding remains available. No
migration is required.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, tool use, SSH and browser
diagnostics, code editing, and test execution. The exact serving model
suffix and context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 11:19:36 -05:00
DottaandPaperclip 5823e9a664 fix(runner): preserve disabled Codex web search (#17744)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native Codex agents use the saved agent settings to prepare each
provider launch.
> - Onboarding saves web search as off, but native configuration
conversion removes that setting.
> - Codex 0.160.0 includes a hosted web-search tool by default, even in
an authentication probe that asks it not to use tools.
> - A gateway that permits only priced function tools can reject that
request before budget admission.
> - This change preserves the explicit restriction through native
execution and disables web search for authentication probes.

## Linked Issues or Issue Description

**What happened?**

A native Codex authentication probe can include hosted web search.
Normal task execution also loses a saved `search: false` setting. A
restricted Responses gateway can reject these requests before it makes a
model call. Related repairs: Refs #17445, Refs #17529. The roadmap and
related PRs were checked; no duplicate repair was found.

**Expected behavior**

Authentication probes check the selected account and model without
hosted web search. A saved search-off setting remains effective in
native task launches, prepared launches, and session recovery. Existing
behavior for an absent setting remains unchanged.

**Steps to reproduce**

1. Create a Codex agent with search off and choose Paperclip Runner.
2. Use a Responses gateway that rejects hosted tools.
3. Inspect the request from the native authentication probe or task
launch. Before this fix, the pinned Codex SDK includes `web_search`
despite the saved setting.

## What Changed

- Preserve an explicit search-off setting when native agent
configuration is built and converted.
- Carry the restriction in the durable native input and provider launch
requirements.
- Apply the restriction to authentication probes and normal launch
paths, including custom arguments and recovery.
- Reject prepared launches that discard the required restriction. Keep
gateway billing rules unchanged.
- Admit only the restrictive literal value in the strict plugin task
API. Exercise the real plugin setup path.
- Add regression coverage and document the policy.
- Add the immutable Copilot v60 source identity required by the changed
shared files. Preserve v59 and all original live evidence. Copilot
authentication probes keep their prior launch requirements.

## Verification

- Regression cases were run against the unfixed source and failed at the
configuration and launch boundaries.
- An isolated capture using the real Codex 0.160.0 app-server reproduced
hosted-tool rejection. Disabling web search reached a mocked budget
reservation. The helper and child processes permitted only loopback
network access and used synthetic credentials. It made zero upstream
calls.
- Focused checks passed: 284 server cases, 61 native form cases, 198
backend/security/launch/parser cases, and 36 authentication/launch
cases. A separate complete transport/launch/parser run passed 393 cases.
These groups overlap.
- Head `617b98f` passed workspace typecheck/build and 28/28 plugin
contract and actual Runner probe tests with no skips. Final rebased head
`20ff0c1` passed all current-head CI checks, including full isolated
test lanes, and fresh Greptile and Paperclip reviews at 5/5.
- The additive Copilot identity update passed 134
compatibility/policy/protocol checks and nine authentication probe
checks. The real pinned Codex SDK capture was repeated after the final
policy change: all five cases passed with zero upstream calls.
- Two local full-suite attempts stopped after native PostgreSQL loader
failures. Seven local dependency aliases were restored, and an isolated
cluster initialized successfully. A third run later encountered host
PostgreSQL semaphore exhaustion and was interrupted before
source-profile regeneration. Its zero exit code after SIGINT is
explicitly not a full-suite pass. Final full-suite verification runs in
isolated CI; the local attempts remain recorded.
- The first CI run exposed a missing strict plugin API field. Its five
failures were reproduced locally, then passed after repair. The next run
passed every underlying job except the source-identity guard. That guard
now binds an additive identity with v59 retained. Final-head CI and both
fresh reviews passed; addressed review threads are resolved.
- The offline capture runs on Darwin ARM64. It does not prove the
contents of a prior unretained Linux request or complete Cloud
onboarding acceptance.

## Risks

- The restriction must survive prepared launches and resumed sessions.
Regression tests cover those boundaries.
- Existing absent settings retain their prior behavior. This change does
not add native search-on support or loosen gateway admission.
- Older durable inputs without the optional restriction must remain
valid.
- Copilot now uses profile v60 for exact launch admission. Historical
v59 inputs remain readable. The new declaration adds no live Copilot
qualification and does not change its executable or admission flags.
- A deployed Cloud acceptance run is still required after this source
repair.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code execution, and
delegated review. The exact backend 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 10:29:51 -05:00
DottaandPaperclip aec86c794b fix(runner): preserve native work through controller outages (#17594)
Keep remote native work under its authenticated connection lease through controller outages. Hold durable ACPX tools through reconnection, align the native Claude HTTP MCP client budget, and wait for the recovered handler before dispatch. Preserve Stop, cancellation, exact identity and artifact checks.

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 09:01:24 -05:00
Nicky Leach 2cd6eb27c7 fix(runner): record the plugin-prepared working directory (#17243) 2026-10-22 20:42:26 -07:00
Nicky LeachandPaperclip 0081863463 Fix isolated ACPX admission for assigned PRP tools (#17149)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

Reproduced against `92cfd701c39bb1ea394a796023481a21decb2532`.

**Deployment mode**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 16:00:14 -07:00
DottaandPaperclip 734c265339 Default new Pi agents to Paperclip Runner (#17142)
## Thinking Path

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

## Linked Issues or Issue Description

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

**Current behavior**

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

**Proposed behavior**

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

**Reason and benefit**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 17:10:00 -05:00
DottaandPaperclip 0a5f1546ee feat(cases): add reusable prompt workflows (#17114)
## Thinking Path

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

## Linked Issues or Issue Description

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

**Problem or motivation**

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

**Proposed solution**

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

**Alternatives considered**

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

**Roadmap alignment**

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

## What Changed

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

## Verification

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

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

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

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 07:17:50 -05:00
Nicky LeachandPaperclip e5351b240a Verify native Runner setup through plugin tasks (#17029)
## Thinking Path

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

## Linked Issues or Issue Description

**Subsystem affected**

Runner, plugin SDK, and agent environment tests.

**Problem or motivation**

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

**Proposed solution**

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

**Alternatives considered**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 18:13:09 -07:00
Nicky LeachandPaperclip 2a5a323e57 Add execution-owned Runner launch preparation (#16997)
## Thinking Path

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

## Linked Issues or Issue Description

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

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

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

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 14:24:13 -07:00
Nicky LeachandPaperclip 05f7079ecb Extract Runner provider launch preparation (#16977)
## Thinking Path

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

## Linked Issues or Issue Description

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

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

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

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 11:20:49 -07:00
DottaandPaperclip 505e1a5582 feat(cases): add persistent workflows with same-task agent handoffs (#16959)
## Thinking Path

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

## Linked Issues or Issue Description

**Problem or motivation**

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

**Proposed solution**

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

**Alternatives considered**

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

**Roadmap alignment**

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

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

## What Changed

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

## Verification

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

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

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

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

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

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

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

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

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

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

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

Preserved CI failures and retries:

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


## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 12:46:14 -05:00
DottaandPaperclip df80616d98 Preserve Copilot historical runtime attestations (#15703)
## Thinking Path

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

## Linked Issues or Issue Description

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

## What Changed

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

## Verification

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

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

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

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

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

## What Changed

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

## Verification

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

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

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

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

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

**Subsystem affected**

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

**Problem or motivation**

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

**Proposed solution**

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

**Alternatives considered**

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

**Roadmap alignment**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 15:36:04 -05:00
DottaandPaperclip 06d4fe3121 perf(runner): preload essential Claude task tools (#16885)
## Thinking Path

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

## Linked Issues or Issue Description

Refs #15993, #15994, #15997.

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

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

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 14:29:22 -05:00
DottaandPaperclip 95672307f4 feat(runner): carry acknowledged Claude effort through native resume (#15994)
## Thinking Path

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

## Linked Issues or Issue Description

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

## What Changed

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

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

## Verification

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 13:31:09 -05:00
DottaandPaperclip 3858d2341d fix(recovery): default saved-monitor waits and keep task recovery quiet (#16686)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

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

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

## What Changed

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

## Verification

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

## Risks

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

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

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

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

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-18 21:43:15 -05:00
Dotta cfa9dce295 refactor(runner): remove unreferenced Paperclip Runner test fixtures (#16543)
## Thinking Path

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

## Linked Issues or Issue Description

**What existing behavior does this improve?**

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

**Subsystem affected**

`packages/paperclip-runner` test fixtures.

**Current behavior**

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

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

**Proposed behavior**

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

**Reason and benefit**

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

**Breaking changes**

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

**Additional context**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

Refs #16444.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 13:46:50 -05:00
Nicky LeachandPaperclip ec3eb1968b feat(runner): expose credential updates through PRP (#16463)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner uses PRP to send harness events to the host.
> - A harness can replace its stored OAuth tokens during a run.
> - The host has no PRP signal that tells it to read the updated
credential.
> - This pull request adds a durable credential update event and
observers for supported stores.
> - The host can react before it acknowledges the event. Token values
stay outside PRP.

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner`: native provider execution, PRP schemas, and
host event delivery.

**Problem or motivation**

A Paperclip host that consumes PRP needs to react when a harness changes
its refresh-token credential. Existing credential copy-back paths do not
provide a common event during a warm session.

**Proposed solution**

Add `auth.credentials.updated` as a P0 runner event. Include only the
provider, binding ID, revision, and detection method. Observe native
Codex and Codex/Grok ACPX credential files. Retain each pending event
across runner restart until the durable outbox accepts it. Raw PRP
consumers opt in with `observeCredentials: true` before session open.
The bundled transport opts in for fresh sessions.

**Alternatives considered**

`harness.diagnostic` would mix a runner observation with harness
diagnostics. Sending token values through PRP would expose credentials
to event logs. Both approaches are unnecessary.

**Roadmap alignment**

I checked `ROADMAP.md`. This change extends the existing Runner protocol
and does not duplicate a planned core feature.

**Additional context**

Refs: #11094, #14056, #12696. These describe credential copy-back and
staging work. This PR adds the notification contract. It does not
replace those private credential channels or claim to fix their full
scope.

## What Changed

- Add strict credential update payload validation to PRP v1, v2, and v3.
Regenerate validators, the manifest, and the event catalog.
- Watch supported credential directories with `notify`. Add a periodic
read as a fallback and check at terminal and close boundaries.
- Persist a private baseline and pending event together. Notify on
account identity changes and retain the new baseline for later
refreshes. Ignore incomplete files, unsafe files, and metadata changes.
- Forward the event through the host transport. Test commit-before-ACK
delivery and replay.
- Commit pending runner observations before suspend and shutdown
commands complete. Preserve the provider event backlog.
- Create the private ACPX runtime directory before configuring
observation. Cover fresh session startup with observation enabled.
- Fence asynchronous PRP commits to the current authenticated connection
and run authority. Ignore replaced callbacks while preserving the
maintenance drain of admitted work.
- Deliver observations found during final provider cleanup before
clearing terminal recovery state. Retain the outbox and recovery state
when the host ACK is lost.
- Advance the pending Copilot candidate profile to v19 for the changed
shared PRP source hashes. Preserve its v18 history and pending
qualification status. Include the current fixture in the Docker build
context.
- Commit credential updates through an awaited host callback before PRP
ACK, including during idle and close. Persist them in a separate run-log
source namespace with company, agent, session, and runner checks.
- Preserve public event metadata through server redaction. Register the
event in task run details.
- Document opt-in behavior, supported stores, event semantics, and the
local run-log path.

## Verification

- All 45 durable runner control tests and 24 native executor integration
tests pass.
- Ten Rust credential observer tests pass. They cover atomic
replacement, polling, recovery, account-only changes and later refreshes
for Codex and Grok, unsafe files, fresh runtime creation, and the Grok
close handoff. Account identity stays private.
- The full Runner TypeScript suite passes: 3,565 tests in 221 files. An
additional 12 tests are skipped by the suite.
- All 214 focused tests pass for the contract, Codex event routing,
catalog, and durable host delivery.
- All 13 Node protocol contract tests pass.
- The exact Docker context integrity command passes: `docker buildx
build --file .github/docker-context-checks.Dockerfile .`.
- Rust formatting and generated protocol checks pass.
- `pnpm -r typecheck` and `pnpm build` pass. The full local `pnpm
test:run` was attempted with CI-compatible `init.defaultBranch=master`,
then stopped after a reproducible failure outside this change:
`git-workspace-expiration.test.ts` expects one re-expired workspace but
gets zero. The same case fails in isolation on this macOS checkout. Full
repository validation is provided by CI; the focused Runner and host
tests pass locally.
- All 253 native transport and restart tests pass against the final
release binary.
- All 3 durable recovery tests and 139 candidate profile and native
admission tests pass.
- All 41 host redaction and task protocol surface tests pass. `pnpm
check:token-gates` passes.
- All 467 CI policy tests pass, including the 15 CI profiling tests. The
upstream secret-reference test fix is retained from master. No workflow
changes are included.

- The Apex host-delivery fix passes 381 targeted Runner tests, six host
database tests, repository typecheck, and the production build. The
Runner tests cover commit-before-ACK, retry after a rejected host
commit, warm attachment, and close after the turn queue ends.
- Prior head `2f125cfcb` passed CI, standard Greptile 5/5, and Apex 5/5.
One CI shard was interrupted by GitHub runner shutdown; its single rerun
passed. Both Apex findings are addressed: idle/cleanup host delivery and
late callback reconnect fencing. Current head `5db78f082` passes CI (56
successful statuses and four optional skips) and standard Greptile 5/5.
Apex review of the account-change update is 5/5 on this exact head, with
no actionable issues.
- All 121 durable control-plane and credential callback tests pass,
including account-only change delivery, subsequent refresh on the new
account during close, host commit retry, late success/failure races,
forward cursor delivery on a replacement connection, and the existing
maintenance retirement contract. All 27 native provider and durable
recovery integration tests pass after the account-change update.

## Risks

- File changes signal a stored credential update. They do not prove that
an OAuth refresh succeeded. Changes between reads can be combined.
- Unix Codex and Codex/Grok ACPX stores are supported. Other harnesses
and credentials held only in memory need their own integration.
- Hosts must update their event schemas before opting in. Older hosts
omit the flag and receive no new event. Older runners ignore the flag.
- The host must use its existing private credential channel and account
checks to read or copy the token. Account switches trigger notification
but do not authorize accepting the new account. The event grants no
credential access.
- Tests use synthetic credentials. No live OAuth refresh has been
forced.

## Model Used

OpenAI Codex, exact model ID `gpt-6.1-sol`, with high reasoning effort,
repository inspection, tool use, and code execution. The session does
not expose its 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-15 14:49:00 -07:00
DottaandPaperclip 8843887c24 fix(runner): preserve managed GitHub access in OpenCode (#16488)
## Thinking Path

> - Paperclip manages AI agents and their authorized connections.
> - Native OpenCode agents use managed Git and GitHub launchers for
shell work.
> - Each operation must obtain credentials from the active run's broker.
> - Two OpenCode environment filters dropped that broker binding before
the shell started.
> - The shell therefore ran anonymously even when connector tools had
authorized access.
> - This pull request preserves the explicit broker environment through
both filters.
> - The benefit is working GitHub shell access with current identity and
revocation checks.

## Linked Issues or Issue Description

**What happened?**

Native OpenCode shell commands reported `GitHub capability_missing`
despite an authorized GitHub connection. Both runner startup and
provider startup dropped the controller's broker settings. Connector MCP
calls used a separate path and could still succeed.

**Expected behavior**

A managed shell operation obtains credentials for the current run. A
later operation uses the new identity after rotation and loses access
after revocation. Ambient host credentials do not supply authority.

**Steps to reproduce**

1. Start the native GitHub broker with an active run binding.
2. Pass its environment through native OpenCode startup.
3. Run `gh api user` from the provider shell.
4. Observe anonymous access before this fix.

**Paperclip version or commit**

Reproduced on master `6943904bad` before this change.

**Deployment mode**

Native Paperclip Runner with OpenCode, including remote execution.

Related: #16401 fixes the separate oversized OpenCode SSE failure and is
already merged. The same live-driver regression was verified locally
against its exact pre-fix source and current source. This PR does not
duplicate that fix. Searches found no open PR for this native broker
propagation defect; #15309 concerns the legacy OpenCode adapter.

## What Changed

- Use the existing GitHub credential environment projection at both
OpenCode launch boundaries.
- Preserve explicit controller authority while excluding an ambient host
broker.
- Exercise the real launcher and broker from an OpenCode child process,
directly and through runner projection.
- Check operation-time identity rotation, revocation, and exclusion of
controller API credentials and persistent GitHub tokens.
- Document the managed OpenCode shell contract.

## Verification

- Red: both new `native-github-access.test.ts` cases returned
`anonymous` instead of `fixture-a` before production changes.
- Green: both cases pass after the fix, including `fixture-a` to
`fixture-b` rotation and anonymous operation after revocation.
- Full native GitHub broker suite: 18 tests pass.
- OpenCode, provider-event, and configured-environment suites: 141 tests
pass across eight files.
- Separate SSE red/green verification: the existing live-driver
regression times out on `fd057f6ac4^` and passes with merged #16401. The
full OpenCode group also passes after restoration.
- Full repository build and typecheck pass locally. All CI jobs pass for
`23d734293f6a5c6d6128cae0c8773661816daf9a`. Final GitHub rollup: 55
successful checks/statuses, two skipped checks, and one neutral check;
none pending or failing. Greptile gave that commit 5/5 with no findings
or unresolved threads.
- Paperclip Review spent over 23 minutes preparing its runtime without a
provider assessment. Its run was cancelled for recovery and ended
neutral (review execution did not complete). This neutral result is not
a code assessment. No check policy or branch protection was changed.
- The full local Vitest attempt first hit embedded PostgreSQL startup
failures. Running the unchanged `initdb --version` and `postgres
--version` independently showed missing native library symlinks. The
dependency had been installed with scripts disabled. Running its bundled
`hydrate-symlinks.js` restored startup; all 15 affected native-session
cases and all 112 AI connection tests then passed without application
code changes. The original full-suite attempt was stopped after the
setup failure and its log is retained. A complete local suite pass is
not claimed.
- The broker and executable are local fixtures. No live GitHub account,
credential change, or test PR is required by these regressions.

## Risks

The change affects credential delivery into OpenCode processes. It
reuses the existing bounded GitHub projection and accepts broker
authority only from explicit input. Each shell operation still uses the
normal broker, scope, identity, and revocation rules. Unrelated
controller secrets remain excluded. There are no database or
permission-policy changes.

## Model Used

OpenAI `gpt-6.1-sol`, through Codex, with xhigh reasoning and repository
tools/code execution. The session does not report its 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 the focused regression and affected suites locally and
they pass; the full local attempt and setup failure are disclosed above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green (Paperclip Review is
neutral/incomplete, as disclosed above)
- [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-15 16:15:38 -05:00
DottaandPaperclip b8ffeb973a feat(runner): add experimental Grok Bot agent participation (#16219)
## Thinking Path

> - Paperclip manages AI agents that perform work for a company.
> - The shared Runner owns task admission, authority, receipts and
finalization.
> - An existing Grok Bot needs to receive assignments and return results
through that Runner.
> - The Bot also needs governed access when it starts work from its own
conversation.
> - This PR adds agent-purpose MCP access and routine webhook dispatch.
> - It reuses the external-agent Rust Runner and keeps Grok capabilities
explicit.
> - The provider stays experimental until the real-client managed
journeys pass.

## Linked Issues or Issue Description

**Agent or provider**
Grok Bot, distinct from the Grok Build coding runtime in #13882.

**Why this adapter is useful**
Users can assign work to an existing Bot, receive progress, questions,
documents and files in Paperclip, and let the Bot initiate work under
its agent permissions.

**How the agent is invoked**
A webhook-only routine delivers bounded references. Dedicated
named-agent OAuth and MCP provide inbound calls. Setup follows [Grok
routines](https://cursor.com/help/grok-bot/routines) and [custom
plugins](https://cursor.com/help/grok-bot/connect-plugins). The current
desktop app needs its Bot-generated Webhook URL navigation link when
routine-row clicks fail.

The GitHub search found related Grok Build runtime work, but no existing
Grok Bot agent provider. This extends the roadmap’s existing agent,
Runner, governance and artifact foundations.

## What Changed

- Add default-off Grok Bot participation through the shared real Rust
external backend, preserving native provider identity guarantees and
distinguishing session closure from remote termination.
- Bind agent OAuth to company, agent, client, gateway and authorizer;
recheck permissions and task-bound execution authority without
manufacturing a native identity.
- Persist routine configuration, dispatch intents, authenticated
acknowledgement and recovery holds. Store URL/key together in encrypted
secret storage, use guarded public egress, and never automatically
replay ambiguous HTTP delivery.
- Reuse native tools, durable waiting, completion assessment and review.
Add task-bound file grants through existing artifact storage; suppress
proactive echo dispatch and synchronous result wake loops.
- Enforce the current native deliverable work-mode policy at file-ticket
issuance and use. Add operator retries for confirmed rejected wakes,
with retained receipts, stable retry intent and current-authority
checks. Recovery locks bindings before routine rows. Thread Stop
resolves the selected run and its agent.
- Cancel queued and preparing Stop targets before assignment creation,
restore saved setup after a failed request and successful retry, and
publish the Grok provider descriptor schema. Advance the versioned
Copilot source declaration for the shared schema change; its
qualification remains pending.
- Filter task summaries with the shared privacy policy, preserve
feedback admission when wake delivery is blocked, reconcile settled
delivery receipts without restoring work authority, and bind every Stop
control to its displayed run. Recovery records distinguish dispatch
uncertainty from a revoked session.
- Add resumable guided setup, credential replacement, consent,
management, observed work status and stop/recovery controls, plus an
interactive Storybook journey using the production task thread, question
form and report card. Grok’s own apps remain available; Paperclip
workspace and third-party tools are deferred.

## Verification

- Five focused protocol, authorization, person MCP and Runner files: 192
tests pass. The Grok assigned-work case executes the actual Rust Runner,
saves a document, uploads/deduplicates a file and reaches ordinary
finalization.
- Proactive intake/deduplication and renewed-session recovery pass.
These use scripted clients and synthetic storage; they are not
real-provider acceptance.
- Repository typecheck, production build, token gates, map checks and
Storybook build/catalog checks pass. The local full-suite campaign was
stopped after macOS shared-memory exhaustion repeatedly prevented
embedded PostgreSQL startup. No local aggregate pass is claimed. The
first clean-worker CI run identified avatar fixture/configuration, flag
defaults, feature-card ordering and OpenAPI route-coverage gaps; all
four focused regressions pass after correction. Those regressions pass.
The latest clean-worker CI run also found a Copilot source-hash
declaration mismatch after the shared descriptor update; the corrected
declaration passes all 28 integrity tests. The next review corrections
pass 144 rendered UI tests, 21 OpenAPI tests and 82 Runner
contract/integrity/history tests. The latest database fixtures were
blocked at startup by host shared-memory exhaustion; clean-worker CI
must execute their new regressions. Full current-head CI now passes: 54
successful checks and four intentional skips. The database regression
uses the PostgreSQL driver result shape; file-policy, rejected-feedback
and lock-order cases pass on clean workers. Current-head Greptile is 5/5
with no unresolved findings.
- Rendered setup steps and outbound-only verification were walked
through in Storybook. Simulation cannot enable Done without an
authenticated-reply state.
- Actual client OAuth, continued access, reconnect and one routine wake
with an exact chat acknowledgement were observed separately. This
candidate’s live authenticated challenge, assigned/proactive workflows,
Linux managed artifact, restart and cleanup are not yet qualified. The
provider stays disabled by default.
- The separate Cloud ingress change forwards only exact task-bound
upload/download paths and preserves host identity and header stripping.
- Current Cloud policy reserves Test for pre-merge app/harness
experiments; Staging accepts only master-derived revisions. Real-client
qualification needs a supported, authorized deployment target and
remains outstanding.

## Risks

One append-only migration adds routine/dispatch state and extends shared
bindings and file tickets. The unshipped migrations were regenerated
after upstream consumed their original numbers. Rolling back code
retains the durable rows; revoke grants and inspect unknown remote
activity before resuming dispatch. Grok cannot confirm remote
termination, stream its complete transcript or report spending. Plugins
are account-wide and do not isolate credentials between Bots.
Real-client managed acceptance remains required before enabling the
experimental provider.

## Model Used

OpenAI Codex based on GPT-6, with reasoning, code execution and
browser/native UI tools. The exact deployment model ID and
context-window size are not exposed by this runtime.

## 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-13 20:57:42 -05:00
DottaandPaperclip d6e6d1c78a Stream OpenCode immediately, scope reasoning to turns, and deduplicate instructions (#15708)
## Thinking Path

> - Paperclip helps people manage AI agents and observe their work.
> - The native runner carries provider output into the task transcript.
> - OpenCode sends incremental text in `message.part.delta` events.
> - The driver ignored those events and waited for a full part snapshot.
Accepted chats also waited after lifecycle verification was complete.
> - This pull request forwards each valid chunk as it arrives and
removes unnecessary isolated startup work.
> - Valid chunks reach Paperclip sooner without changing completion or
permission rules. The matched browser experiment below does not
establish a reliable end-to-end latency improvement.

## Linked Issues or Issue Description

**What happened?**

The native OpenCode driver withheld text until OpenCode sent a full
snapshot. A local delayed-provider probe with the pinned OpenCode
1.18.34 runtime showed a 1,496 ms gap between the first native text
delta and the first Paperclip text delta (1,510 ms from provider text).

**Expected behavior**

Forward valid assistant text and reasoning deltas immediately. Preserve
repeated identical tokens, message roles, turn ownership, and final
response selection.

**Steps to reproduce**

Send an empty text part, then text deltas, and withhold the final full
snapshot. The new fixture requires the consumer to acknowledge its first
text delta before releasing the snapshot. The previous driver cannot
pass this handshake.

**Paperclip version or commit**

Baseline: `011e5669bad61c435a4745fb10812bef70376841`. The patch is
rebased onto current master.

**Deployment mode**

Local native OpenCode 1.18.34 on macOS arm64. Live diagnostics use
`openrouter/deepseek/deepseek-v4-flash-0731`. These are narrow
diagnostics, not full Product E2E qualification.

## What Changed

- Keep the macOS verified OpenCode launch pathname until child exit,
with guarded reuse and cleanup on failed launches. This fixes a
reproduced asynchronous executable-lifetime failure.
- Dispatch accepted queued chats immediately after lifecycle readiness
commits, through normal scheduler admission. Preserve ready state if
dispatch fails.
- Validate native OpenCode model access with the real hello probe
without a redundant catalog scan. Keep legacy adapter discovery
unchanged and isolate unspecified native probe directories.
- Map incremental text and reasoning to the existing canonical event
path, using observed part and message identities.
- Keep additive chunks without IDs distinct. Preserve ID-based event
deduplication.
- Clear current streaming part metadata when a new turn starts. Reject
mismatched session/message identities and unknown parts or fields.
- Disable automatic updates, remote model refreshes, and default plugins
in each isolated OpenCode process. Keep assigned MCP tools and default
model reasoning intact.
- Retain the latest cumulative text/reasoning part while its message
role is unknown, including completion metadata after more than 100
chunks.
- Expose `startTurn({ message, reasoningMode: "disabled" })` for one
OpenCode/OpenRouter turn. Carry the selection in the durable command
through Rust and the proxy. An omitted/default option restores provider
defaults on the next turn, including warm and recovered sessions. There
is no environment-level setting or automatic selection policy.
- Group optional Rust turn inputs in `CodexTurnOptions` and dispatch
through `start_turn_with_options`; retain `start_turn` for defaults.
Future turn settings can be added without another feature-specific
method.
- Expose a native-session capability for per-turn reasoning and reject
explicit unsupported selections before dispatch, including direct ACPX
and Codex backends. Runnerd checks the durable selected model as well as
the provider.
- Remove duplicate agent instructions from the shared OpenCode proxy
task envelope for all users. Send one system copy on every turn,
including prepared and resumed turns, because OpenCode reads the latest
user message’s system field. Preserve task constraints and completion
contracts.
- Document startup and streaming behavior. Add regression coverage for
role ordering, repeated chunks, final snapshot deduplication, and stale
turns.

## Verification

### Lower-load browser retry — 2026-10-10

**All 8/8 trials succeeded. In this batch, median Send → first visible
reply fell from 30.586 s to 12.476 s (59.2% lower).** Four fresh-agent
trials per variant, phase order before/after/after/before with two
trials per phase. Every adjacent-phase pair favored the candidate,
although one difference was only 0.301 s. This is evidence for the
readiness/probe changes on this host, not a production percentile or a
guarantee across providers.

| Phase/trial | Variant | Send → reply (s) | Observed ready → run (s) |
Session open → turn start (s) | Model requests |
|---|---|---:|---:|---:|---:|
| 0/0 | before | 45.042 | 25.337 | 3.629 | 2 |
| 0/1 | before | 13.689 | 0.000 | 2.443 | 2 |
| 1/0 | after | 14.696 | 0.000 | 2.526 | 1 |
| 1/1 | after | 13.389 | 0.000 | 2.470 | 2 |
| 2/0 | after | 10.871 | 0.000 | 2.706 | 2 |
| 2/1 | after | 11.564 | 0.004 | 2.443 | 2 |
| 3/0 | before | 41.582 | 21.518 | 2.376 | 2 |
| 3/1 | before | 19.589 | 9.753 | 2.707 | 1 |

Observed ready-to-run median: **15.636 s → 0 s**; zero means execution
began by the first ready observation, not literally zero latency.
Polling interval is nominally 250 ms plus HTTP time.
Session-open-to-turn-start includes controller handling, not just child
startup. All eight ran within the existing startup timeouts; no timeout
or reasoning policy was changed. Host load at fixture creation stayed
**5.47–8.73 on 18 CPUs**, versus 68.9–100.8 in the prior campaign. No
builds/tests ran concurrently with measurement.

Same merged source **b0a0158729a7913882a0e756fe7e27228d72bf53**, release
runner, rebuilt static UI, OpenCode **1.18.34**, model
**openrouter/deepseek/deepseek-v4-flash-0731**, provider-default
reasoning, and empty isolated workspaces in both variants. Only the
readiness worker and explicit-model verification source were toggled;
the launch-lifetime fix and all proxy streaming changes were held
constant. Thus this does not separately measure the original streaming
changes. One browser per phase, two fresh companies/agents/chats per
phase. Measurement begins at capture-phase Send click and ends on
visible Hi text plus two animation frames. Status/thinking is excluded;
emoji can arrive just after the first text. Successful screenshots
inspected. Each variant had three two-request turns using
`paperclip_finish` and one one-request turn; no status lookup was
observed. Reported usage includes settlement after the first visible
reply.

Runner SHA-256
`57f658c220eecd2370ffd3333cd7e5d06d16bb2798af0cf43c84e01c8207c1c3`;
proxy
`bcc02fda2bf35b38a116cd880841aa6c534f6e0b497a96d97369a1e06dcc72ac`;
rebuilt UI tree
`eee238f2eda628c4e8c3660707986da4f8dd9100c814e26938fce3756df2eae4`
(sorted relative path, NUL, binary per-file SHA-256). Worker/probe
variant source hashes are unchanged from the preserved comparison below.
Measured turn cost **$0.00612574**, plus verification probes not
included in that figure. All eight attempts retained; all source/proxy
files restored and test supervisors exited.

Current commit validation: **53 successful CI checks, 4 skipped, zero
failing; Greptile 5/5 on b0a0158729 with no actionable findings.** The
previous 20 targeted post-merge tests passed. No source edit was made
for this rerun. Earlier failed and inconclusive cohorts below remain
historical evidence and are not pooled with this batch.


### Master update and failure diagnosis — 2026-10-09

Merged `origin/master` at `417db14e7d` into this branch without
conflicts; pushed merge commit
`b0a0158729a7913882a0e756fe7e27228d72bf53`. The incoming changes do not
alter OpenCode process startup or its timeout budgets. Historical
measurements below remain attributed to their original commits.

The four last-campaign failures never issued `turn.start`, so these were
**cold-session admission failures, not model replies failing**. Two
retained `session.open` commands eventually completed after controller
timeout/cleanup had begun. The other two ended with the inner
`thread/start` response timeout, and their diagnostics recorded OpenCode
startup retries. Startup event timestamps are buffered publication times
and must not be interpreted as exact process-spawn times.

On the merged source, two credential-free startup-only checks used the
real pinned OpenCode 1.18.34, empty temporary workspaces, a placeholder
key, and **no model turns**:

- Existing pinned executable: spawn at 1.083 s; failed health
attempt/retry at 11.311 s and 21.914 s; third process healthy at 32.210
s; session opened at **35.168 s**.
- Verified private executable path: snapshot preparation took **0.497
s**; process spawned at 1.588 s; healthy at 9.967 s; session opened at
**11.120 s**.

These are sequential diagnostic samples, not evidence that one
executable path is faster. Host load was **56.5–64.5 on 18 logical
CPUs**. The local health wait permits 10 s per attempt and the driver
retries up to three times; the outer controller's cold admission budget
is 30 s, and the Rust facade also waits 30 s for a response. Thus
retries plus setup/session creation can outlast the caller's budget. The
isolated 35.168 s success demonstrates that a session can eventually
open yet fail the app's admission deadline. Heavy load aggravates the
timing; its exact contribution is not isolated. No timeout was increased
and no new model-latency claim is made.

Merge validation: **20/20 targeted lifecycle-policy and heartbeat
run-completion tests passed**, including temporary PostgreSQL cases. The
first sandbox invocation skipped database cases; the authorized local-DB
rerun executed all 20. The package-manager launcher could not verify its
version via the unreachable registry, so validation used the
already-installed Vitest binary. Full CI/review subsequently passed on
this merge commit; see the October 10 retry above. Older results below
apply to their named commits.


### Follow-up: reproduced macOS launch failure — 2026-10-09

The retry exposed a startup bug rather than only host-load noise. The
macOS proxy deleted the private verified executable path immediately
after asynchronous spawn. A credential-free test of the actual pinned
OpenCode `--version` reproduced a fast SIGKILL and a 15-second timeout
in three immediate-cleanup attempts; three deferred-cleanup controls
succeeded. The timeout was killed by the diagnostic's own deadline. This
experiment does not establish the OS-internal reason for the fast
SIGKILL.

Commit `c30451e0ebf3f74e9ef70d37bbe4d9fe7fb56359` retains the private
launch path until child exit, cleans failed spawns, and waits for forced
shutdown before reuse. Source descriptor authentication, ownership,
mode, inode checks, and the prohibition on ambient executable fallback
remain. Overlapping reuse fails closed. The existing synchronous shell
test was changed to exercise the actual asynchronous boundary.

**Verification:** 59 focused proxy/driver tests passed; runner
TypeScript check passed. All six subsequent real OpenCode version
launches succeeded without timeout (4.11, 4.33, 5.73, 6.91, 4.95, 6.70
seconds). The native Rust binary is unchanged from the retry; no model
calls were made by these diagnostics.

Retained interrupted retry: before 42.56/18.69 seconds; after one
180-second timeout (`provider_process_exited` / health SIGKILL) and one
37.33-second success. The latter overlapped the credential-free
diagnostic and is not a clean matched timing. The next phase was stopped
before Send to diagnose the reproduced bug. Reported measured-turn cost:
$0.0016874, verification probes additional. These attempts are not
pooled with other campaigns.

<!-- launch-fixed-proof:start -->
**Completed retry, stopped by the declared failure rule after 6 of 8
planned trials. No reliable end-to-end speedup demonstrated.** At commit
`c30451e0ebf3f74e9ef70d37bbe4d9fe7fb56359`, the launch fix above was
held constant in both variants; only the readiness handoff and
explicit-model verification path changed. Planned phase order:
before/after/after/before, two fresh agents/chats per phase, one new
browser per phase. The second after phase had two consecutive failures,
so the final before phase was not run.

| Phase/trial | Variant | Send → first visible reply | Observed ready →
run | Outcome |
|---|---|---|---|---|
| 0/0 | before | No reply within 180 s | 2.777 s | session.open timeout
|
| 0/1 | before | 47.654 s | 9.383 s | Succeeded |
| 1/0 | after | 50.051 s | 0.087 s | Succeeded |
| 1/1 | after | No reply within 180 s | 0.151 s | session.open timeout |
| 2/0 | after | No reply within 180 s | 3.337 s | session.open timeout |
| 2/1 | after | No reply within 180 s | 1.434 s | session.open timeout |

Both successful screenshots show “Hi 👋”. Timing starts at the browser's
capture-phase Send click and ends at the first visible answer text plus
two animation frames; the first fragment can be “Hi” before the emoji
arrives. Thinking/status text is not counted. All four failures were
`runner_local_connect_failed: PRP command session.open timed out`
(`native_session_interrupted`), before a reply; none reported the
earlier health-stage SIGKILL. They are retained, not discarded as
outliers. One success per variant does not support a speedup estimate or
median comparison. Observed ready-to-run median was **6.080 s before
(n=2) vs 0.793 s after (n=4)**; this is sampled every nominal 250 ms
plus HTTP latency and is a lower bound, not precise tracing. Host load
at fixture creation ranged **68.9–100.8 on 18 logical CPUs**, a
substantial confound that worsened over the campaign. No local
build/test was run concurrently with this campaign.

Provenance: pinned OpenCode **1.18.34**, model
**openrouter/deepseek/deepseek-v4-flash-0731**, default reasoning in
both variants, empty synthetic workspaces and isolated probe homes.
Release runner SHA-256
`57f658c220eecd2370ffd3333cd7e5d06d16bb2798af0cf43c84e01c8207c1c3`;
current proxy SHA-256
`bcc02fda2bf35b38a116cd880841aa6c534f6e0b497a96d97369a1e06dcc72ac`;
built UI tree SHA-256
`7f0c2b7f586cb753408351574b2239e22311944add99af4f6f3562cd6d47bbcb`. This
holds the rebuilt runner and static UI constant. Provider-reported
measured turn cost **$0.00120649**; verification probes are additional.
Including the earlier interrupted retry, this follow-up reports
**$0.00289389** in measured turn usage; missing usage is not assumed
free. Prior cohorts remain separate below.

Validation on `c30451e0e`: **59 focused tests passed**, runner
TypeScript check passed, **6/6 real credential-free pinned OpenCode
launches passed**, fresh Greptile **5/5 with zero unresolved threads**.
CI: **51 success, 4 skipped, 1 failed**. The failed native compilation
job never reached compilation: Docker's auth endpoint timed out during
Buildx setup, then failed the same way on one retry
([job](https://github.com/paperclipai/paperclip/actions/runs/37994181674/job/114039737503)).
Full local checks were not rerun while measuring. The PR remains draft:
the launch defect is reproduced and fixed, but cold session startup
still exceeds the controller's admission budget on this host. Raising
that budget would not establish a faster first response.
<!-- launch-fixed-proof:end -->

### Readiness investigation and live rerun — 2026-10-09

**Measured queue fix; no reliable end-to-end speedup claim. Keep this PR
in draft.** Accepted chats could wait for the periodic queue sweep after
verification had already committed `ready`. The lifecycle worker now
dispatches through the existing scheduler immediately after that commit.
The normal company, pause, budget, concurrency, and task-ownership
checks still apply. Dispatch failure preserves readiness and leaves
recovery to the queue sweep.

Native OpenCode verification also avoids enumerating the full model
catalog before running its real hello request. Identifier validation
remains. Authentication failures, unavailable models, and timeouts still
prevent readiness. An unspecified local probe directory uses an empty
temporary directory.

**Queue-only experiment:** four before and four after attempts, in
before/after/after/before server phases, two fresh agents per phase.
Median observed ready-to-start delay fell from **19.429 s to 0.058 s**.
State polling was nominally 250 ms plus HTTP time, so the latter means
within observation resolution; it is not a precise 58 ms latency claim.
After timings were 100.20, 65.29, 63.78, and 76.97 seconds. Before had
one 59.65-second success and three 120-second response timeouts (one
provider health SIGKILL, one late success, one still running after
settlement and canceled). These censored results do not support a
success-only median speedup comparison. Focused tests overlapped the
last baseline phase, which further limits total-time interpretation.
Reported measured-turn cost: $0.0055383; verification probes and
incomplete/canceled usage are additional.

**Final matched experiment:** built static UI in both variants to avoid
pre-Send Vite compilation; current proxy, release runner, selected
model, default reasoning, and explicitly isolated empty probe
cwd/HOME/XDG held constant. Both worker handoff and model-probe changes
vary. Fresh browser/company/agent/chat per attempt. ABBA order, two
attempts per variant, 180-second response limit declared before the
batch, four-turn bound. Same Send-to-rendered-Hi metric as the earlier
experiment.

| Order | Variant | Send → visible Hi | Created → execution | Observed
ready → execution | Outcome |
| --- | --- | ---: | ---: | ---: | --- |
| 1 | Before | 62.66 s | 23.467 s | 2.830 s | Succeeded |
| 2 | After | >180 s | 14.200 s | Within polling resolution | Provider
health SIGKILL |
| 3 | After | >180 s | 13.877 s | Within polling resolution | Provider
initialization timeout |
| 4 | Before | >180 s | 144.256 s | 14.067 s | Still running after
settlement; canceled |

Only one of four attempts produced a timed reply. **There is no valid
overall speedup estimate from this batch.** The dispatch delay is
removed, but provider startup failures and heavy shared-host load
remain. A recorded host sample was load 93.55 on 18 logical CPUs. This
is a confound, not proof that every failure was caused by host load.
Provider-reported measured-turn cost was $0.00032752, with no reported
usage for the other three attempts; verification probes are additional.

Retained earlier setup attempts: one shared-memory startup failure
before model calls, and a separate development-UI batch with a
60.06-second baseline followed by a navigation timeout before Send.
These attempts are retained separately, not counted as successful
response timings. No live attempts were silently dropped.

Provenance: source base `53580f8fbd40b963f3fb7ba5172ff3ede2e9ef1f`,
measured patch committed as `40b54eafb`, then rebased as
`c590770dcc2bb1debce14037935a7031e5c3c1ac`. **These live timings predate
the rebase.** Source and binary hashes are retained below. The inner
harness label `after` selects the identical current proxy in every
attempt; the outer campaign handoff label is the actual before/after
variant. Owned benchmark processes stopped and original proxy restored.

<!-- readiness-check-status:start -->
Post-rebase validation at `c590770dcc2bb1debce14037935a7031e5c3c1ac`:

- Full local `pnpm -r typecheck`: **passed**, including the native
release build (1,098.6 seconds on the loaded host).
- Focused lifecycle and adapter tests: **26 passed**. The 14 database
integration tests did not run locally because their hard-coded 20-second
database setup hook timed out. A retry with a CLI timeout override
encountered the same explicit hook limit. The earlier pre-rebase focused
batch passed 77 tests; these results are not substituted for post-rebase
execution.
- Local `pnpm test:run` was started, then stopped to avoid duplicating
CI on the saturated host. Local `pnpm build` was not run separately.
**Current-head CI passed Typecheck + Release Registry, Build, all
general and serialized test groups, Rust checks, both runner Vitest
groups, and all eight browser E2E shards.** The last general shard
passed 1,179 tests (72 files).
- Fresh [Greptile
review](https://github.com/paperclipai/paperclip/pull/15708#issuecomment-6085742217):
**5/5**, reviewed this exact head, no actionable defect.
- Final CI rollup: **49 success, 4 skipped, 4 failure**. The failures
are [Compile isolated native
Runner](https://github.com/paperclipai/paperclip/actions/runs/37990274515/job/114024329242),
[Docker context
integrity](https://github.com/paperclipai/paperclip/actions/runs/37990274623/job/114024196511),
[Canary Dry
Run](https://github.com/paperclipai/paperclip/actions/runs/37990274623/job/114024196424),
and the dependent `ci / verify` aggregate. All three root failures are
Docker Hub HTTP 429 / unauthenticated pull-rate limits while fetching
Node base images. The native-image job was retried once and hit the same
limit. No source compiler/test failure was reported by those gates. CI
maintainers need authenticated pulls or to rerun after the registry
limit clears.
- Owned benchmark servers stopped. Local validation commands completed
or were stopped. The PR remains a draft: user-visible speed/reliability
is not qualified, and the Docker-dependent CI gates are not green.
<!-- readiness-check-status:end -->

<details><summary>Sanitized readiness evidence with all attempts and
source hashes</summary>

```json
{"campaign":{"order":["before","after","after","before"],"trialsPerPhase":1,"maxMeasuredTurns":4,"maxCampaignUsd":1,"sourceHead":"53580f8fbd40b963f3fb7ba5172ff3ede2e9ef1f","reasoning":"provider default, no override","proxySha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","purpose":"Final matched comparison of both optimizations; distinct from earlier queue-only campaign.","responseTimeoutMs":180000,"timeoutRationale":"Declared before this final campaign because earlier unchanged baselines sometimes exceeded 120 seconds; earlier timeouts remain retained.","ui":{"mode":"built static UI","treeSha256":"7f0c2b7f586cb753408351574b2239e22311944add99af4f6f3562cd6d47bbcb"},"priorCampaign":"combined-proof stopped after a development-UI navigation timeout before Send; no failed attempts erased."},"complete":true,"statistics":{"before":{"attempted":2,"successfulMeasurements":1,"medianTtfrMs":62657.2000002861,"rangeTtfrMs":[62657.2000002861,62657.2000002861],"medianObservedReadyToRunMs":8448.5,"medianRunStartToVisibleMs":37290.199951171875},"after":{"attempted":2,"successfulMeasurements":0,"medianTtfrMs":null,"rangeTtfrMs":null,"medianObservedReadyToRunMs":0.0,"medianRunStartToVisibleMs":null}},"measuredTurnCostUsd":0.00032752,"costCoverage":"Provider-reported measured chat turns only; harness verification probes are additional and not included.","readinessMetricLimit":"First observed ready state sampled every 250 ms plus HTTP duration; clamped to zero if execution started before the observation. This is a lower bound on ready-to-start delay, not a precise sub-millisecond metric.","results":[{"phase":0,"trial":0,"handoff":"before","ttfrMs":62657.2000002861,"answer":"Hi","statuses":["succeeded"],"error":null,"runErrorCode":null,"providerHealthKilled":false,"queueMs":23467.0,"queuedBeforeObservedReady":true,"observedVerificationMsAfterFixture":26390.0,"observedReadyToRunMs":2830.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":37290.199951171875,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00032752,"costUsdExact":"0.000327520","inputTokens":26864,"outputTokens":46,"cachedInputTokens":0,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"},{"phase":1,"trial":0,"handoff":"after","ttfrMs":null,"answer":null,"statuses":["failed"],"error":"TimeoutError: page.waitForFunction: Timeout 180000ms exceeded.","runErrorCode":"provider_process_exited","providerHealthKilled":true,"queueMs":14200.0,"queuedBeforeObservedReady":true,"observedVerificationMsAfterFixture":24028.0,"observedReadyToRunMs":0,"readyAndStartedInSameSample":true,"runStartToVisibleMs":null,"usage":[{}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":2,"trial":0,"handoff":"after","ttfrMs":null,"answer":null,"statuses":["failed"],"error":"TimeoutError: page.waitForFunction: Timeout 180000ms exceeded.","runErrorCode":"provider_initialize_timeout","providerHealthKilled":false,"queueMs":13877.0,"queuedBeforeObservedReady":true,"observedVerificationMsAfterFixture":18107.0,"observedReadyToRunMs":0,"readyAndStartedInSameSample":true,"runStartToVisibleMs":null,"usage":[{}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":3,"trial":0,"handoff":"before","ttfrMs":null,"answer":null,"statuses":["running"],"error":"TimeoutError: page.waitForFunction: Timeout 180000ms exceeded.","runErrorCode":null,"providerHealthKilled":false,"queueMs":144256.0,"queuedBeforeObservedReady":true,"observedVerificationMsAfterFixture":136901.0,"observedReadyToRunMs":14067.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":null,"usage":[{}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"}],"hostLoadSample":{"at":"2026-10-09T20:48:40.031Z","parallelism":18,"load":[93.546875,82.68017578125,75.9091796875]},"measuredChangesCommit":"40b54eafb","postRebaseCommit":"c590770dcc2bb1debce14037935a7031e5c3c1ac","postRebaseLimit":"Live benchmark predates the rebase. No post-rebase live result is claimed.","variantSourceHashes":{"before":{"server/src/modules/agent-lifecycle/application/worker.ts":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326","packages/adapters/opencode-local/src/server/test.ts":"4c10bacb55f2c7589e7b5c79d74781206ae075db8955f5b998065d6db3c0335a","server/src/adapters/registry.ts":"4a858763f69947d5745c7b8cb251a62fa404bc9683ade0ffb76282ed12761394"},"after":{"server/src/modules/agent-lifecycle/application/worker.ts":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7","packages/adapters/opencode-local/src/server/test.ts":"cd2ea3d51c3f1b4fb42261be701fb7f6b85704ad8e641e6db73d7c58e47364d3","server/src/adapters/registry.ts":"4a858763f69947d5745c7b8cb251a62fa404bc9683ade0ffb76282ed12761394"}},"model":"openrouter/deepseek/deepseek-v4-flash-0731","prompt":"Reply with Hi and an emoji and nothing else.","runnerBinary":{"profile":"release","sha256":"6134c17debda14a76da69ac9631a2d10dad482ebd58dbc9a4e4480ed652211c4"},"probeIsolation":"Explicit empty cwd and HOME/XDG folders under the synthetic fixture workspace in BOTH variants. No server checkout or ambient provider home is used for the hello request.","comparisonLabelNote":"Inner run.mts variant after selects the identical current proxy in every trial; outer campaign readinessHandoff controls before/after source changes."}
```

Queue-only campaign:

```json
{"campaign":{"order":["before","after","after","before"],"trialsPerPhase":2,"maxMeasuredTurns":8,"maxCampaignUsd":1,"sourceHead":"53580f8fbd40b963f3fb7ba5172ff3ede2e9ef1f","reasoning":"provider default, no override","proxySha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04"},"complete":true,"statistics":{"before":{"attempted":4,"successfulMeasurements":1,"medianTtfrMs":59654.5,"rangeTtfrMs":[59654.5,59654.5],"medianObservedReadyToRunMs":19429.0,"medianRunStartToVisibleMs":8843.5},"after":{"attempted":4,"successfulMeasurements":4,"medianTtfrMs":71128.7000002861,"rangeTtfrMs":[63778.90000009537,100195.59999990463],"medianObservedReadyToRunMs":58.0,"medianRunStartToVisibleMs":26542.849975585938}},"measuredTurnCostUsd":0.0055383,"costCoverage":"Provider-reported measured chat turns only; harness verification probes are additional and not included.","readinessMetricLimit":"First observed ready state sampled every 250 ms plus HTTP duration; clamped to zero if execution started before the observation. This is a lower bound on ready-to-start delay, not a precise sub-millisecond metric.","results":[{"phase":0,"trial":0,"handoff":"before","ttfrMs":59654.5,"answer":"Hi 👋","statuses":["succeeded"],"error":null,"queueMs":50590.0,"observedReadyToRunMs":25709.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":8843.5,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00087852,"costUsdExact":"0.000878520","inputTokens":25644,"outputTokens":264,"cachedInputTokens":28416,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"},{"phase":0,"trial":1,"handoff":"before","ttfrMs":null,"answer":null,"statuses":["failed"],"error":"TimeoutError: page.waitForFunction: Timeout 120000ms exceeded.","queueMs":41651.0,"observedReadyToRunMs":14656.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":null,"usage":[{}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"},{"phase":1,"trial":0,"handoff":"after","ttfrMs":100195.59999990463,"answer":"Hi 🙂","statuses":["succeeded"],"error":null,"queueMs":65893.0,"observedReadyToRunMs":116.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":33243.60009765625,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00075782,"costUsdExact":"0.000757820","inputTokens":27014,"outputTokens":175,"cachedInputTokens":26368,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":1,"trial":1,"handoff":"after","ttfrMs":65288.60000038147,"answer":"Hi 👋","statuses":["succeeded"],"error":null,"queueMs":43511.0,"observedReadyToRunMs":0,"readyAndStartedInSameSample":true,"runStartToVisibleMs":21227.60009765625,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00085326,"costUsdExact":"0.000853260","inputTokens":25166,"outputTokens":250,"cachedInputTokens":28160,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":2,"trial":0,"handoff":"after","ttfrMs":63778.90000009537,"answer":"Hi 👋","statuses":["succeeded"],"error":null,"queueMs":39218.0,"observedReadyToRunMs":0,"readyAndStartedInSameSample":true,"runStartToVisibleMs":23479.89990234375,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.000839,"costUsdExact":"0.000839000","inputTokens":27068,"outputTokens":238,"cachedInputTokens":26368,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":2,"trial":1,"handoff":"after","ttfrMs":76968.80000019073,"answer":"Hi 👋","statuses":["succeeded"],"error":null,"queueMs":46257.0,"observedReadyToRunMs":185.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":29605.800048828125,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00030582,"costUsdExact":"0.000305820","inputTokens":24694,"outputTokens":32,"cachedInputTokens":1792,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"ceffb90a6bc97ffaaf8ec7d0267c7bfa7738d321aaf2a618b5efb9b114bc88e7"},{"phase":3,"trial":0,"handoff":"before","ttfrMs":null,"answer":null,"statuses":["succeeded"],"error":"TimeoutError: page.waitForFunction: Timeout 120000ms exceeded.","queueMs":100979.0,"observedReadyToRunMs":3872.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":null,"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00190388,"costUsdExact":"0.001903880","inputTokens":25524,"outputTokens":852,"cachedInputTokens":55808,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"},{"phase":3,"trial":1,"handoff":"before","ttfrMs":null,"answer":null,"statuses":["running"],"error":"TimeoutError: page.waitForFunction: Timeout 120000ms exceeded.","queueMs":129391.0,"observedReadyToRunMs":24202.0,"readyAndStartedInSameSample":false,"runStartToVisibleMs":null,"usage":[{}],"workerSha256":"02adc7e1162fb60439869cec62b75d8fb22fec71155f80535c8e00211cde8326"}]}
```
</details>

### Matched live browser latency evidence — 2026-10-09

**Conclusion: the overall first-response speedup is not established.**
Twelve successful real browser runs produced a lower after median, but
the updated path won only 3 of 6 adjacent pairs. Median paired
improvement was -0.17 seconds (effectively tied). Do not treat the
deterministic streaming-forwarding improvement as proof that this PR
fixes end-to-end first-response latency.

- **Actual path:** local Paperclip browser → real server/database →
current optimized Rust runner → pinned OpenCode 1.18.34 → OpenRouter
`deepseek/deepseek-v4-flash-0731`. Default reasoning in both variants;
no disabled-reasoning override.
- **Prompt:** `Reply with Hi and an emoji and nothing else.` Fresh
company, agent, chat, and per-turn native provider process for each
trial; same QA fixture instructions and selected model.
- **Comparison:** current product/runner at
`53580f8fbd40b963f3fb7ba5172ff3ede2e9ef1f` held constant. The baseline
substitutes the exact `opencode-app-server-proxy.ts`,
`opencode-proxy-task-envelope.ts`, and `opencode-server-driver.ts`
contents from pre-PR `41fec8c8921f9fb19c13fe11e2c9b71bf1017317`. This
isolates those changed modules; it is not an entire old-checkout
comparison.
- **Metric:** browser capture-phase Send click to a rendered `Hi`
markdown answer plus two animation frames, with a screenshot of the
answer. Thinking, tool labels, and status indicators do not count. This
is a DOM/render measurement, not instrumented compositor pixel timing.
- **Order/bound:** predeclared `before, after, after, before` repeated
three times; six trials per variant; 120-second response timeout; $1
campaign guard. All 12 measured trials returned `Hi` and an emoji and
finished successfully; none omitted.
- **Result:** before median **48.08 s** (37.42–66.40); after median
**42.50 s** (27.68–63.32). The 11.6% lower median alone is not
persuasive evidence of a reliable improvement given the mixed paired
results and broad overlap.
- **Remaining delay:** retained queue timestamps for 10/12 trials show
**9.76–41.65 seconds from run creation to execution start**. This is
before the OpenCode path changed here. Its cause is not established by
this benchmark. The final two queue reads were unavailable after
automatic server shutdown; all twelve primary browser timings were
retained.
- **Cost:** $0.010517369 provider-reported across the 12 measured turns;
$0.011371499 including the successful setup pilot. This is separate from
the older diagnostics listed below.
- **Retained setup attempts:** two failures before Send (composer
locator and transpiler helper); one baseline startup failure before any
observed model request (`SIGKILL` while probing OpenCode health); one
successful current-code pilot whose selector missed the visible reply.
These are retained separately, not silently included/excluded as valid
timings. The measured batch used the corrected selector and the same
release binary for both variants.
- **Limits:** local development server and headless Chromium on macOS
arm64, small sample, variable queue timing/provider routing/cache. This
does not qualify production/cloud performance or isolate the
contributions of each changed module. Server, browser, and owned runs
were stopped; original proxy build artifact restored; no product source
files changed for this experiment.

| Pair | Before: Send → visible Hi | After: Send → visible Hi | Faster
variant |
| --- | ---: | ---: | --- |
| 1 | 66.40 s | 27.68 s | After |
| 2 | 37.42 s | 28.00 s | After |
| 3 | 39.75 s | 55.22 s | Before |
| 4 | 47.32 s | 63.32 s | Before |
| 5 | 48.85 s | 29.79 s | After |
| 6 | 51.31 s | 61.07 s | Before |

<details>
<summary>Sanitized measurement records, source/binary hashes, usage, and
retained attempt classification</summary>

```json
{"manifest":{"candidate":"53580f8fbd40b963f3fb7ba5172ff3ede2e9ef1f","baseline":"41fec8c8921f9fb19c13fe11e2c9b71bf1017317","comparison":"Same current product and runner; replace the three OpenCode proxy/driver source modules with exact pre-PR contents for baseline. Reasoning uses defaults in both.","model":"openrouter/deepseek/deepseek-v4-flash-0731","prompt":"Reply with Hi and an emoji and nothing else.","samplesPerVariant":6,"order":["before","after","after","before","before","after","after","before","before","after","after","before"],"maxTurnMs":120000,"maxCostUsd":1,"variants":{"before":{"sources":{"src/cli/opencode-app-server-proxy.ts":"e9b46c937d7ce3b51dc44181a2a3ad82befda9ebe184adf80c0a6b30da140fd6","src/cli/opencode-proxy-task-envelope.ts":"fc23f8a515c2c4d1551f6b95e5b38e6254849dec23f7396e76b646e170a6e006","src/drivers/opencode/opencode-server-driver.ts":"99de415e8fc3bb5fb6f8d7512d751c4c37d2aa77a18b0546b9fb232f1a6fb6c5"},"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b"},"after":{"sources":{"src/cli/opencode-app-server-proxy.ts":"fa800e9bccce02f05f1af83e225d3b5a1300d0a7d4c35ac548f400d6c0a83f79","src/cli/opencode-proxy-task-envelope.ts":"5c387614fc9832322686326b8482eb00d88699d491b05cf59cadcd94a41194ea","src/drivers/opencode/opencode-server-driver.ts":"a944f3bf7f1bf897daec3a5dc2aa34ee9d1a2133efcb3cf150b002095a0ec586"},"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04"}},"runnerBinary":{"profile":"release","sha256":"6134c17debda14a76da69ac9631a2d10dad482ebd58dbc9a4e4480ed652211c4"},"metric":"Browser Send capture-phase click to visible Hi answer, sampled on animation frames, plus two paint opportunities. Excludes reasoning/tool/status text.","setupAttempts":["setup-failure-1","setup-failure-2","startup-failure-3","pilot-selector-failure"]},"summary":{"before":{"attempts":6,"measured":6,"medianMs":48083.050000190735,"minMs":37420.5,"maxMs":66397.69999980927,"totalCostUsd":0.004945229,"toolCalls":[4,1,0,0,0,1]},"after":{"attempts":6,"measured":6,"medianMs":42504.049999952316,"minMs":27680.099999904633,"maxMs":63320.90000009537,"totalCostUsd":0.00557214,"toolCalls":[0,1,0,4,0,1]},"medianReductionPercent":11.602841334350234,"medianPairedImprovementMs":-168.59999990463257,"reportedCampaignCostUsdIncludingPilot":0.011371498999999998},"pairs":[{"indices":[0,1],"beforeMs":66397.69999980927,"afterMs":27680.099999904633,"improvementMs":38717.59999990463},{"indices":[2,3],"beforeMs":37420.5,"afterMs":27997,"improvementMs":9423.5},{"indices":[4,5],"beforeMs":39751.60000038147,"afterMs":55217.199999809265,"improvementMs":-15465.599999427795},{"indices":[6,7],"beforeMs":47318.90000009537,"afterMs":63320.90000009537,"improvementMs":-16002.0},{"indices":[8,9],"beforeMs":48847.2000002861,"afterMs":29790.900000095367,"improvementMs":19056.300000190735},{"indices":[10,11],"beforeMs":51311.7000002861,"afterMs":61072.40000009537,"improvementMs":-9760.699999809265}],"trials":[{"index":0,"variant":"before","startedAt":"2026-10-09T19:15:23.172Z","measurementError":null,"ttfrMs":66397.69999980927,"domMs":66390.59999990463,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.002612595,"costUsdExact":"0.002612595","inputTokens":55962,"outputTokens":1344,"cachedInputTokens":83456,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":["paperclip_get_task_context","paperclip_comment_on_task","paperclip_finish","paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":4,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:15:58.194Z","turn.submitted":"2026-10-09T19:15:58.311Z","turn.started":"2026-10-09T19:15:59.063Z","firstTextDelta":"2026-10-09T19:16:36.039Z","turn.completed":"2026-10-09T19:16:36.118Z"},"completedRunDurationsMs":[42915.0]},{"index":1,"variant":"after","startedAt":"2026-10-09T19:16:36.598Z","measurementError":null,"ttfrMs":27680.099999904633,"domMs":27636.599999904633,"answer":"Hi","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00030429,"costUsdExact":"0.000304290","inputTokens":26845,"outputTokens":28,"cachedInputTokens":0,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":3,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:17:00.717Z","turn.submitted":"2026-10-09T19:17:00.841Z","turn.started":"2026-10-09T19:17:01.508Z","firstTextDelta":"2026-10-09T19:17:05.934Z","turn.completed":"2026-10-09T19:17:06.205Z"},"completedRunDurationsMs":[14435.0]},{"index":2,"variant":"after","startedAt":"2026-10-09T19:17:08.762Z","measurementError":null,"ttfrMs":27997,"domMs":27984.599999904633,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00101016,"costUsdExact":"0.001010160","inputTokens":27544,"outputTokens":366,"cachedInputTokens":26624,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":["paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:17:26.192Z","turn.submitted":"2026-10-09T19:17:26.305Z","turn.started":"2026-10-09T19:17:26.936Z","firstTextDelta":"2026-10-09T19:17:40.688Z","turn.completed":"2026-10-09T19:17:40.826Z"},"completedRunDurationsMs":[17763.0]},{"index":3,"variant":"before","startedAt":"2026-10-09T19:17:41.376Z","measurementError":null,"ttfrMs":37420.5,"domMs":37364.40000009537,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.000693018,"costUsdExact":"0.000693018","inputTokens":24236,"outputTokens":282,"cachedInputTokens":27648,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":["paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:18:12.381Z","turn.submitted":"2026-10-09T19:18:12.616Z","turn.started":"2026-10-09T19:18:13.441Z","firstTextDelta":"2026-10-09T19:18:21.746Z","turn.completed":"2026-10-09T19:18:22.262Z"},"completedRunDurationsMs":[29216.0]},{"index":4,"variant":"before","startedAt":"2026-10-09T19:18:23.000Z","measurementError":null,"ttfrMs":39751.60000038147,"domMs":39705.7000002861,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.000265747,"costUsdExact":"0.000265747","inputTokens":26123,"outputTokens":77,"cachedInputTokens":0,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:19:01.000Z","turn.submitted":"2026-10-09T19:19:01.163Z","turn.started":"2026-10-09T19:19:01.893Z","firstTextDelta":"2026-10-09T19:19:07.169Z","turn.completed":"2026-10-09T19:19:07.384Z"},"completedRunDurationsMs":[15843.0]},{"index":5,"variant":"after","startedAt":"2026-10-09T19:19:10.050Z","measurementError":null,"ttfrMs":55217.199999809265,"domMs":55204.89999961853,"answer":"Hi 🙂","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00030421,"costUsdExact":"0.000304210","inputTokens":4294,"outputTokens":28,"cachedInputTokens":22543,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:19:59.877Z","turn.submitted":"2026-10-09T19:19:59.990Z","turn.started":"2026-10-09T19:20:00.713Z","firstTextDelta":"2026-10-09T19:20:07.290Z","turn.completed":"2026-10-09T19:20:07.658Z"},"completedRunDurationsMs":[15104.0]},{"index":6,"variant":"after","startedAt":"2026-10-09T19:20:09.550Z","measurementError":null,"ttfrMs":63320.90000009537,"domMs":63313.09999990463,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00260723,"costUsdExact":"0.002607230","inputTokens":137971,"outputTokens":951,"cachedInputTokens":1024,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":["paperclip_comment_on_task","paperclip_get_task_context","paperclip_comment_on_task","paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":4,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:20:59.730Z","turn.submitted":"2026-10-09T19:20:59.859Z","turn.started":"2026-10-09T19:21:00.501Z","firstTextDelta":"2026-10-09T19:21:19.416Z","turn.completed":"2026-10-09T19:21:19.608Z"},"completedRunDurationsMs":[26519.0]},{"index":7,"variant":"before","startedAt":"2026-10-09T19:21:20.519Z","measurementError":null,"ttfrMs":47318.90000009537,"domMs":47246.800000190735,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.000257965,"costUsdExact":"0.000257965","inputTokens":4700,"outputTokens":71,"cachedInputTokens":21407,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:22:03.924Z","turn.submitted":"2026-10-09T19:22:04.439Z","turn.started":"2026-10-09T19:22:04.772Z","firstTextDelta":"2026-10-09T19:22:09.915Z","turn.completed":"2026-10-09T19:22:10.343Z"},"completedRunDurationsMs":[16702.0]},{"index":8,"variant":"before","startedAt":"2026-10-09T19:22:11.124Z","measurementError":null,"ttfrMs":48847.2000002861,"domMs":48802.59999990463,"answer":"Hi 🎉","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.000327654,"costUsdExact":"0.000327654","inputTokens":44796,"outputTokens":32,"cachedInputTokens":0,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:22:57.182Z","turn.submitted":"2026-10-09T19:22:57.281Z","turn.started":"2026-10-09T19:22:57.988Z","firstTextDelta":"2026-10-09T19:23:02.915Z","turn.completed":"2026-10-09T19:23:03.035Z"},"completedRunDurationsMs":[9541.0]},{"index":9,"variant":"after","startedAt":"2026-10-09T19:23:03.579Z","measurementError":null,"ttfrMs":29790.900000095367,"domMs":29748.800000190735,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00034054,"costUsdExact":"0.000340540","inputTokens":24710,"outputTokens":59,"cachedInputTokens":1792,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":[],"eventCounts":{"turn.started":1,"item.delta":2,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:23:28.840Z","turn.submitted":"2026-10-09T19:23:28.954Z","turn.started":"2026-10-09T19:23:29.666Z","firstTextDelta":"2026-10-09T19:23:35.306Z","turn.completed":"2026-10-09T19:23:35.531Z"},"completedRunDurationsMs":[12732.0]},{"index":10,"variant":"after","startedAt":"2026-10-09T19:23:37.247Z","measurementError":null,"ttfrMs":61072.40000009537,"domMs":61061.300000190735,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00100571,"costUsdExact":"0.001005710","inputTokens":25307,"outputTokens":368,"cachedInputTokens":28160,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6691475ed55f10179ec6ee0023a1f6462982f763848da7cd5b1d0baf38633b04","toolCalls":["paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:24:33.721Z","turn.submitted":"2026-10-09T19:24:33.832Z","turn.started":"2026-10-09T19:24:34.601Z","firstTextDelta":"2026-10-09T19:24:43.135Z","turn.completed":"2026-10-09T19:24:43.278Z"},"completedRunDurationsMs":[17387.0]},{"index":11,"variant":"before","startedAt":"2026-10-09T19:24:44.710Z","measurementError":null,"ttfrMs":51311.7000002861,"domMs":51300.5,"answer":"Hi 👋","runCount":1,"statuses":["succeeded"],"usage":[{"model":"openrouter/deepseek/deepseek-v4-flash-0731","costUsd":0.00078825,"costUsdExact":"0.000788250","inputTokens":24316,"outputTokens":356,"cachedInputTokens":27648,"cacheWriteTokens":0,"usageSource":"per_run","costStatus":"reported"}],"bundleSha256":"6dd8726e72545341f6772e54ec5aeb6264dec74db67290df44930d87135efb6b","toolCalls":["paperclip_finish"],"eventCounts":{"turn.started":1,"tool.execution.started":1,"item.delta":1,"turn.completed":1},"eventTimes":{"session.started":"2026-10-09T19:25:31.347Z","turn.submitted":"2026-10-09T19:25:31.463Z","turn.started":"2026-10-09T19:25:32.208Z","firstTextDelta":"2026-10-09T19:25:39.405Z","turn.completed":"2026-10-09T19:25:39.563Z"},"completedRunDurationsMs":[15446.0]}],"additionalAttempts":[{"attempt":"setup-1","stage":"before_send","result":"non-editable composer locator","modelRequestObserved":false},{"attempt":"setup-2","stage":"before_send","result":"transpiler helper absent in browser","modelRequestObserved":false},{"attempt":"startup-pilot-before","runnerProfile":"debug","result":"no visible reply within 120s; OpenCode health startup SIGKILL; retained infrastructure failure","modelRequestObserved":false},{"attempt":"selector-pilot-after","runnerProfile":"debug","result":"Hi reply succeeded; browser selector missed it; no valid TTFR","providerReportedCostUsd":0.00085413}],"queueTimingCoverage":{"measuredTrials":10,"totalTrials":12,"records":[{"index":0,"runs":[{"createdAt":"2026-10-09T19:15:28.998Z","startedAt":"2026-10-09T19:15:53.558Z","queuedMs":24560.0}]},{"index":1,"runs":[{"createdAt":"2026-10-09T19:16:38.520Z","startedAt":"2026-10-09T19:16:54.157Z","queuedMs":15637.0}]},{"index":2,"runs":[{"createdAt":"2026-10-09T19:17:10.587Z","startedAt":"2026-10-09T19:17:23.561Z","queuedMs":12974.0}]},{"index":3,"runs":[{"createdAt":"2026-10-09T19:17:43.807Z","startedAt":"2026-10-09T19:17:53.564Z","queuedMs":9757.0}]},{"index":4,"runs":[{"createdAt":"2026-10-09T19:18:28.113Z","startedAt":"2026-10-09T19:18:54.011Z","queuedMs":25898.0}]},{"index":5,"runs":[{"createdAt":"2026-10-09T19:19:12.343Z","startedAt":"2026-10-09T19:19:53.993Z","queuedMs":41650.0}]},{"index":6,"runs":[{"createdAt":"2026-10-09T19:20:14.258Z","startedAt":"2026-10-09T19:20:53.866Z","queuedMs":39608.0}]},{"index":7,"runs":[{"createdAt":"2026-10-09T19:21:23.019Z","startedAt":"2026-10-09T19:21:54.298Z","queuedMs":31279.0}]},{"index":8,"runs":[{"createdAt":"2026-10-09T19:22:14.671Z","startedAt":"2026-10-09T19:22:53.933Z","queuedMs":39262.0}]},{"index":9,"runs":[{"createdAt":"2026-10-09T19:23:06.155Z","startedAt":"2026-10-09T19:23:23.941Z","queuedMs":17786.0}]}],"limitation":"The server shut down before a final API read; queue timing is retained for the first ten trials only."},"conclusion":"No reliable end-to-end speedup established. The after median is lower, but only three of six adjacent matched pairs were faster; median paired improvement is approximately zero. The deterministic streaming-forwarding fix remains separately supported.","limitations":["Local dev server and headless Chromium on macOS arm64; six fresh chats per variant; not a production/cloud latency guarantee.","Current product and current release runner held constant; only three OpenCode modules replaced by their exact pre-PR contents for baseline.","Default model reasoning unchanged; no no-reasoning override or decision policy.","Upstream routing/cache and queue time vary; trials run serially in predeclared counterbalanced ABBA order.","Render proxy: capture-phase Send click to visible nonempty Hi markdown, then two animation frames; screenshot verifies the rendered answer. This is not instrumented compositor pixel timing.","Two setup-only failures, one startup failure, and one invalid-measurement successful pilot are retained separately, not silently treated as successful timings."],"reproducibility":{"harnessSha256":"f93996b306c7d31c19bfcb9cc197653f867944ffb900d81a23a34f831e17c0c5","variantBuilderSha256":"4e88a7bbdc0de5d72601194ebe3b96d9c6f6eda5a33d8e0f00cf2d5d14db34c2","analyzerSha256":"2d129177a1b8033f768aad3c82dc8fff70ba0ba76e7270b2d8612ee760d4aaf4"}}
```

</details>

- Latest options-struct refactor: 33 provider tests and 86 backend tests
passed. Four port-dependent fixtures initially failed inside the sandbox
and passed with loopback access. Latest check snapshot: 51 successes, 4
skips, and 2 failures (`ci / e2e` and `ci / e2e shard (5/8)`). This
latency experiment does not make the PR merge-ready.

- Focused TypeScript suites passed: OpenCode driver, per-turn reasoning,
prepared-context recovery, proxy envelope, live sessions, Codex context
control, and native instruction measurements. The real runnerd/proxy
integration test confirms disabled followed by default in the same
session. A stale staged binary initially hid the new parameter;
rebuilding the release runner resolved it.
- Capability-guard regression suites passed all 53 tests; the real
runner/proxy boundary still accepts the per-turn selection. Both
OpenRouter and non-OpenRouter real runner/proxy cases passed, along with
62 existing OpenCode fixture tests. Runner TypeScript build passed after
the final correction.
- Affected Rust modules passed: 33 provider tests and 86 durable backend
tests. Malformed or unsupported reasoning selections do not dispatch a
provider turn or poison admission state.
- Pinned OpenCode 1.18.34 with a local OpenRouter-compatible fixture
sent three successive provider requests with reasoning omitted,
`enabled: false`, then omitted. Each request contained one copy of the
agent instructions. No paid provider call was needed.
- The reconstructed first-turn task envelope shrank from 4,356 to 460
characters. This is a payload-size measurement, not a claimed token or
latency reduction. Existing stored conversation history is not
rewritten.
- Prior head `8c07fe2e70267a7c8a3118f1071eca73ecdc6c8a`: all 53 checks
passed, with four intentional skips. Greptile is 5/5 with no open
findings. One bounded retry cleared first-test timeouts, a legacy
signoff lease failure, and CI runner shutdowns. The timed-out suites
also passed locally (14 auth-signal tests, 40 device-login tests, and
the runner resume case).
- Known reported diagnostic usage totals about $0.0029. Two prematurely
closed baseline warm-turn attempts are excluded from latency comparisons
and their usage is not fully captured; background provider usage is also
not fully accounted. No further paid runs are active.
- `pnpm -r typecheck`: passed. Runner TypeScript typechecks and build
also passed after the review correction.
- `pnpm test:run`: attempted and stopped after a reproducible failure in
the untouched Codex recovery test `archives a damaged prior epoch before
completing guarded same-task replacement with real runnerd`
(`server/src/services/native-runtime/native-session-resume.test.ts:1072`).
It returns `needs_review` / failed instead of done / succeeded,
including when rerun alone. The broad local suite is not green. The two
initial collection failures disappeared after building; their isolated
rerun passed all 1,565 tests.
- `pnpm build`: passed.
- Pinned real OpenCode plus a delayed local provider: first native delta
to Paperclip delta fell from 1,496 ms to less than 1 ms at millisecond
measurement resolution. This isolates forwarding delay, not
network/model inference.
- Two live driver samples after the patch reached first text in
2.28–2.62 seconds including session startup. Baseline first responses
took 12.37–13.43 seconds. Small unmatched samples had different
reasoning/cache outcomes, so these are observations, not an attributed
speedup ratio.
- Full compiled runnerd protocol diagnostic: completed with `Hi 👋`;
first assistant delta at 9.19 seconds and cleanup complete at 9.44
seconds. The seeded mock-control-plane harness used 27,512 input tokens
across two provider requests, split into 13,521 and 13,991. The extra
`answer_status_question` call posted `Hi 👋` to the mock task in 12 ms,
then caused another model request. A reconstruction contains 25 tools
(35.3k JSON characters), 12.8k system characters, and a 4.4k task
envelope; 3.9k instruction characters appear in both system and task
context. Provider-reported cost was $0.00073976; the pricing-table
estimate was $0.00395332. This is one integration diagnostic, not a
production latency claim.
- A separate full-runner sample with existing lazy tool discovery also
completed, but took 14.64 seconds through cleanup and called
`paperclip_finish`. Its usage ledger recorded 12,888 input and 11,776
cached-input tokens, with $0.00096344 provider-reported cost. This did
not establish a latency improvement, so the default tool exposure was
not changed.
- Four direct OpenRouter requests separately measured default reasoning
at 2.45/3.90 seconds to first text and disabled reasoning at 0.66/0.53
seconds. Default reasoning remains unchanged; disabling it requires the
explicit per-turn option.

## Risks

- Immediate readiness dispatch changes scheduling timing. It uses
existing admission checks and preserves the periodic sweep as recovery.
- Native model verification relies on the real request rather than
catalog enumeration. The final live batch had provider startup failures;
overall speed and reliability are not qualified.
- Incremental chunks without IDs cannot safely be deduplicated by
content. Repeated identical chunks are valid. Known-ID duplicates remain
suppressed.
- OpenCode uses its bundled model catalog plus the explicit
selected-model entry. New remote catalog metadata will not refresh
during isolated startup.
- Default provider plugins are disabled. This runner supplies
credentials and assigned MCP tools through its own controlled
configuration.
- Disabled reasoning is supported only on the OpenCode/OpenRouter path
and requires a compatible model. It applies to one turn and is not an
automatic latency policy.
- The matched live browser sample is small and does not establish a
reliable end-to-end improvement. It includes local queueing/startup and
browser rendering, but does not qualify production or remote sandbox
latency.

## Model Used

OpenAI GPT-6 (Codex). Tool use, code editing, and command execution were
used. The session does not expose a more specific model ID or
context-window size. Live diagnostic target: DeepSeek
`deepseek/deepseek-v4-flash-0731` through OpenRouter and OpenCode
1.18.34.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-10 07:15:41 -05:00
DottaandPaperclip 57e977be72 feat: integrate Pi 1.0 into the experimental Runner (#14921)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The experimental Runner owns provider processes and durable
sessions.
> - Pi needs working task execution and human controls.
> - The five-PR stack must preserve changes already on master.
> - Each layer now carries the complete integrated source for a safe
sequential fallback.
> - This PR belongs to native GitHub stack #15602, ending at #14956.

## Linked Issues or Issue Description

Refs #14436, #14631, #14743 and #14956.

Ship Pi 1.0 through the experimental Paperclip Runner. The five PRs are
#14921, #14922, #14923, #14924 and #14956. The user authorized the
complete merge after checks pass. Existing `pi_local` execution is
unchanged. Accounting and wider provider/platform qualification remain
deferred.

## What Changed

- Recover missing final replies after workspace finalization changes
owners, using accepted-turn evidence without rerunning work or granting
external-chat publication.
- Preserve the admitted Pi instruction root across warm runs, while
retaining changed-root rejection.
- Give Pi a bounded 15-second default shutdown grace so stop, drain
acknowledgement and durable suspension can complete. Explicit deadlines
and other providers retain their existing behavior.
- Integrate the Pi 1.0 runtime and master contracts.
- Use Pi profile 22. Preserve explicit caller-selected models and exact
native thinking levels. Keep Pi's wrapper, helper, extension and
question/control behavior unchanged from the qualified profile-19
runtime.
- Preserve master's Dot lifecycle and consent fields, configured task
environment, status guards and current Codex/Claude dependency versions.
Cursor stays qualified. Copilot stays pending; profile 17 binds the
changed shared protocol validation sources.
- Exclude general AWS IAM credentials from Pi static/custom provider
bindings and selected task projections; preserve the provider-scoped
Bedrock bearer key. Profile 21 is retained as historical provenance.
Rust and cloud install probes use the current declaration.
- Patch bundled brace-expansion 5.0.9 to the exact official 5.0.12
payload. Pin the patch and complete runtime closures. Include the patch
in normal installed setup tooling. Keep the upstream Pi shrinkwrap as
provenance and permit only this exact security correction.
- Include current attestation files in the Docker build context. Keep
the repository lockfile unchanged from master. CI and private image
builds resolve manifest changes before their frozen installation.

## Verification

- Full local `pnpm -r typecheck` passes, including Runner Rust, server
and UI. Focused integration checks pass: 194 Runner
admission/environment tests, 63 profile/credential tests with one
expected skip, 152 Dot/UI configuration tests, and Pi transcript/notice
tests.
- Full local `pnpm build` passes on the final source.
- Fresh final-source checks pass: all 698 Rust workspace tests (32
binaries), 156 credential/profile/controller tests with one expected
skip, Runner TypeScript typecheck, and 20 package/setup/sandbox tests.
- The profile-21 Pi materializer passes on the native host with the
official pinned Node 24.21.0 and its npm. It verifies all 150 locked
packages, the patched dependency and the exact closure. Setup/package
bundle tests and UI token gates pass.
- The old hashes were reproduced for all three supported targets before
calculating the patched graph. New closure hashes are darwin-arm64
`282022db10150c6632b3444df421342e7d534bdf5d5fb1097a2e79d0625a2bcf`,
darwin-x64
`64e251e19009f755c0b04f73ce2138246faab71a961b0f13d75ebfcc34bef12e`, and
linux-x64
`713b1fdff42fb56a1518bdc084f181d70bee8ebadc3e4b1d76321ed9108c8410`.
Independent native platform execution is separate from graph identity
reproduction.
- Historical cloud qualification remains unchanged: all seven core cases
pass on shipping source `10dc43c9ec65d88c2f782d62afb296d09494f215`,
harness `1a4408a48cfb5a1f094a311141c257c92cd7a893`, image
`sha256:5b3a775b383591bda1b0c1889e509acc70ce7f37c53f09733c81d59037f02280`,
and accepted Sonnet 4.6/low fixture. All 215 canonical files and all
seven cleanup checks pass independent verification. These are profile-19
results and are not relabeled as fresh profile-22 runs.
- Current Pi digest:
`sha256:e92078bee3c23bec4100aa589013a44613d054cd686826534025d8019e9f39a9`.
[The readiness
plan](https://github.com/paperclipai/paperclip/blob/codex/pi-production-readiness/doc/plans/2026-10-02-pi-production-readiness.md)
preserves campaign and failed-attempt provenance.
- Merge only after every PR's current-head CI and fresh review pass.
Linux CI covers the full suites, build and browser tests. The local
embedded Postgres API-authority suite cannot start on this macOS/Node 26
host, so Linux CI must confirm that suite.

### Fresh profile-22 core qualification — 2026-10-08

All seven accepted core cases pass canonically on Pi profile 22, with
`openrouter/anthropic/claude-sonnet-4.6` and native-confirmed low
thinking. This model is a fixture; production accepts the caller's
explicit Pi provider/model.

Runtime/install source: `3241a992f2a7703e59e97ed0fd3e5d6405de4401`.
Frozen accepted harness: `1a4408a48cfb5a1f094a311141c257c92cd7a893`.
Immutable cloud image:
`ghcr.io/paperclipai/paperclip-daytona-runner@sha256:506f22db7edd78f37c0c40bec1cc084af1850455026dbf467194bfbb8fcef141`.
Pi digest:
`sha256:e92078bee3c23bec4100aa589013a44613d054cd686826534025d8019e9f39a9`.

[Hosted Linux image and clean-install
verification](https://github.com/paperclipai/paperclip/actions/runs/37868328023)
passes, including all 20 source-bound archives, normal CLI/Pi setup,
companion import and the production pack reader. This exact installation
source includes the latest master integration and the corrected Pi warm
instruction-root fence. Full local typecheck/build and current-head
hosted CI verify the final stack. All 13 focused real-root regressions
pass. The full local executor suite passed 662 tests; 15 database tests
could not start the Mac embedded PostgreSQL service. Hosted Linux CI
passes the full required verification and E2E checks. These fresh
results keep their own source identity; profile-19 results remain
historical.

| Core path | Canonical campaign | Retained archive SHA-256 |
| --- | --- | --- |
| File edit, validation, download and Done |
`pi-core22-replyfix-0-1791511228` | 23 files;
`a473e8603a3dd4737863291f8d3d1e392391f0b16d433c3e0e0e9d8baf7a97b0` |
| Pending question and controller restart |
`pi-core22-replyfix-1-1791511376` | 33 files;
`6b829c4eb74e1f32a89c692a4ae7130dbfc1c6d3cf13915effe2103d9e242c8e` |
| Three-turn session/process/workspace continuity |
`pi-core22-replyfix-2-1791511587` | 23 files;
`7a87021f8f9a3fdd3c58bb4467f8d82c635e3ea4795d6e75f144d9aa14818df8` |
| Four typed questions and browser reconnects |
`pi-core22-replyfix-3-1791511881` | 42 files;
`9e31755252be1f4f9cb0626c984c142d4d1ae5f5bee3a7af08444db8d12c280a` |
| Plan approval and completion | `pi-core22-replyfix-4-1791512031` | 22
files;
`a0383ce1aab38e7b5a25ce0e9dd3bebea5c037ebd96ae6b29dae19015da2ae2c` |
| Same-turn steering and permission denial |
`pi-core22-replyfix-5-1791512261` | 39 files;
`c929b8c7070f0b66aedc17e65ca46e6beab1e363926ac9f7e2a75fb250f05949` |
| Stop during pending permission | `pi-core22-replyfix-6-1791512390` |
33 files;
`7f0a58ae0f4d5bfc76149435f4e322537089c5bd16e7ffe9b5ad71f10a621a07` |

All 215 canonical files (28714587 bytes) are independently
hash-verified. All seven cleanup grades pass, with no owned runtime
process or temporary root after each case. Automatic retries are zero.
The owned cloud host stopped normally after retention. The prior
profile-22 warm attempt remains failed and separately retained: archive
SHA-256
`1e54eba5ec72b50cee1534b23d1d1d4f21a090006b8a64501ba70db972abfde5`. Its
original canonical classification is preserved. Diagnosis reproduced a
product bug comparing an agent-files root against an unset
checkpoint-only field. The fix stores the admitted physical root
separately from the adopted per-run collection capability. The real-root
regression fails before the fix and passes afterward, including
rejection of a changed physical root. Fixture, grader, model and all
seven accepted case IDs are unchanged; this fresh campaign tests
final-reply publication after file registration first. The intermediate
restart attempt also remains failed and retained: archive SHA-256
`5dcaefdf1d17cf4cd54fd4cf810f45e736667392339b8ce7caf08bb4e225277f`. Its
original canonical classification is preserved. Pi resumed, wrote the
verified answer and completed its task; exact runner suspension was
proven, but idle stop consumed about 5.2s and left under 3s for the
drain acknowledgement. The Pi-only default shutdown grace is now 15s,
preserving a full 5s drain round trip and a finite suspension reserve.
Explicit caller deadlines, other provider defaults, literal drain
receipts and exact suspension identity checks remain unchanged. The
timing regression fails before this correction and passes afterward; all
18 focused settlement tests and Runner typecheck pass. The final-source
file attempt is also preserved as failed (`candidate_failure`), archive
SHA-256
`db6767b6773ea618997927ac77bdb005a5ac81492c7b9c0ffbc900449f829bc9`.
Native edit, validation, exact downloadable artifact and Done/succeeded
all passed, and the exact final reply was durably recorded. A workspace
recovery owner completed before the live heartbeat reached presentation,
leaving that reply absent from task chat. Recovery now materializes only
a completed final reply from the accepted turn of an ordinary internal
Done task, preserving issue/run/contract binding, suppression,
external-chat authorization and same-run deduplication. The database
regression covers the generated file-preparation receipt, suppression,
unapproved external continuation and replay. Server typecheck and all 49
response-selection tests pass; hosted Linux verifies the database
regression because embedded PostgreSQL cannot start on this Mac.

The delayed-final-answer database regression passes on [the final
root-source Linux server
shard](https://github.com/paperclipai/paperclip/actions/runs/37868262553/job/113628594152),
alongside 1,108 passing tests. The first root Runner shard had one
unchanged durable-resume test exceed its 5-second timeout; the identical
top-source shard and the isolated exact test passed. One rerun of that
failed job and its required aggregate passed without source or test
changes. The original failed job log and the single-rerun receipt remain
retained.

### October 9 merge verification

Current merge head: `5a8fe63512a7166aaef5cf50065a25008aa8b44b`. All
current-head checks pass, including `ci / verify` and `ci / e2e`;
exact-head Greptile review is 5/5 with no unresolved threads. Current
master conflicts are resolved. The user authorized the maintainer
override of the code-owner review gate after these checks. The seven
retained live core cases remain bound to source
`3241a992f2a7703e59e97ed0fd3e5d6405de4401` and its recorded cloud image.

## Risks

- The security correction changes the dependency closure and profile
identity. Old sessions must reopen on the new profile. Exact identities
and credential bindings fail closed.
- The runner remains experimental and requires explicit selection.
Legacy Pi Local is unchanged. Caller model IDs pass through; the E2E
model is a fixture.
- Accounting and the broad platform/provider matrix remain deferred.
This merge does not publish a release or deploy a service.

## Model Used

OpenAI GPT-6 through Codex assisted with reasoning, repository
inspection, editing and tool use. The exact serving ID and context
window are not exposed in this session. Final live qualification uses Pi
1.0.0 with `openrouter/anthropic/claude-sonnet-4.6` and native-confirmed
low thinking.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` 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-09 08:56:41 -05:00
941a3fa991 Pin Copilot native dependencies with the maintained lockfile refresh (#15572)
Pin the three optional GitHub Copilot 1.0.88 native packages for Runner and server using the maintained lockfile workflow. Synchronize the package contract and bound initial render readiness in the deliberately throttled browser fixture. Current-head CI and focused checks pass.

Co-Authored-By: Dotta <cryppadotta@users.noreply.github.com>
Co-Authored-By: lockfile-bot <lockfile-bot@users.noreply.github.com>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-08 09:37:53 -05:00
DottaandPaperclip fc6304dfe5 feat(runner): add experimental OpenAI Dot provider over MCP Events (#15402)
## Thinking Path

> - Paperclip manages AI agents, tasks, permissions, and execution
budgets.
> - Paperclip Runner gives each provider the same admitted task and tool
authority.
> - OpenAI Dot runs outside the local process tree and needs
asynchronous work delivery.
> - The merged MCP gateway supplies OAuth consent and signed event
delivery.
> - A personal assistant grant cannot safely stand in for an assigned
agent.
> - This pull request adds a separate Dot agent connection and a durable
Rust Runner bridge.
> - The operator can assign work to Dot and inspect its accepted work,
tool receipts, and result.

## Linked Issues or Issue Description

**Agent or provider**

OpenAI Dot, as an experimental provider of the existing Paperclip Runner
adapter.

**Why this adapter is useful**

An operator can assign normal Paperclip tasks to an existing Dot. Dot
can read its mailbox, request work on an assigned task, use admitted
task tools, and submit a result. Paperclip keeps company scope,
checkout, approvals, known budget limits, and activity attribution.

**How the agent is invoked**

A dedicated `/mcp/runner` OAuth resource pairs one Dot grant with one
agent. A signed MCP mailbox event wakes Dot. Dot explicitly accepts the
assignment. The Rust Runner owns the durable turn and operation
receipts. The first release supports self-hosted instances with a local
Runner controller.

**Additional context**

This extends the merged public MCP gateway from #14846 and the assistant
invitation and device-consent work from #14933. This also integrates the
merged assistant tool and configuration expansion in #15380. Dot retains
its dedicated agent resource and cannot receive personal configuration
permission. The public assistant connection remains a personal
connection.

## What Changed

- Add a durable Rust Dot provider and its TypeScript Runner driver.
- Add closed PRP v3 external-provider operations and native execution
input v6.
- Add company-scoped pairing, mailbox, assignment, and operation
records.
- Reuse merged browser/device consent, client metadata verification,
webhook admissions, refresh, secret rotation, and warm-standby gates.
- Keep Dot scopes, issuer, grants, event workers, and tool access
separate from personal assistant access.
- Add Dot configuration, pairing, readiness, and consent UI. Keep agent
grants out of the personal Connections entry.
- Regenerate the Dot-only migration after master. Preserve published
gateway migrations. Make the new migration safe to reapply.
- Document setup, recovery, accounting limits, evidence, and remaining
account qualification.
- Reverify reconnect callbacks and wake outstanding work with a fresh
mailbox reference; preserve the existing assignment and operation
receipts.
- Clean up Dot bindings and waiting runs on OAuth revoke and
refresh-token replay. Old grants cannot revoke replacement bindings.
- Restore the pairing reference when an unsaved agent form is reopened;
document board-only pairing routes in OpenAPI.
- Accept a clean Rust exit after the acknowledged shutdown receipt.
Unexpected exits still require recovery.
- Clear the cached binding after a successful revoke so a failed
connection refresh cannot restore it.
- Add production-component Storybook states and screenshots for pairing
and connection review. All preview account data is synthetic.
- Persist normalized completion, serialize Dot turns and durable work
admission, and poll subscription readiness.
- Serialize mailbox writes and cursor reads; retain paused fence
acknowledgement without task authority.
- Authorize admitted review runs without changing the worker assignee.
Include the fenced assignment ID in production stop notices.

## Verification

- This PR integrates master `4a8178e9c`. Dot migration
`0317_messy_famine.sql` follows the published history and is safe to
reapply. The merge preserves the reserved migration connection,
batch-commit handling, private task checks, task monitors, and native
accounting.
- Local workspace typecheck, full build, and UI token gates pass. The
server typecheck passes after the review fixes. Database and native
executor regressions pass.
- All twelve real Rust/PostgreSQL Dot integration tests and twelve Dot
driver tests pass. The tests cover native document writing and
finalization, durable replay, queue admission, mailbox ordering,
admitted reviews, stale authority, production stop references, and
paused acknowledgements.
- Current head `d0e7e0626` passes all 57 checks: 53 pass and four are
intentionally skipped. This includes full typecheck, build, tests, Rust
Runner verification, browser E2E, release verification, and Canary Dry
Run. Greptile rates this exact head 5/5. All review threads are
resolved.
- The full local root test run is slower than the sharded CI run and has
not completed. The full CI test gates pass on the current commit.
Focused local regressions pass.
- Real-account pairing and event delivery on this base commit remain
unqualified. Live account and setup proof are recorded in the follow-up
#15414.

The following screenshots use synthetic preview data. They show the
production pairing component and do not qualify a real account or the
full agent setup journey.

![Synthetic pairing
preview](https://github.com/paperclipai/paperclip/blob/codex/dot-events-prototype/doc/screenshots/openai-dot-runner/pairing.jpg?raw=true)

![Synthetic connected
preview](https://github.com/paperclipai/paperclip/blob/codex/dot-events-prototype/doc/screenshots/openai-dot-runner/connected.jpg?raw=true)

## Risks

- This base adapter uses `PAPERCLIP_ENABLE_OPENAI_DOT=1` plus Public MCP
and Paperclip Runner. The separate experimental-settings follow-up in
#15414 replaces this environment flag with saved operator settings.
- Dot does not expose provider token usage or cost. The operator must
acknowledge external billing. Known Paperclip budget gates still apply.
- Cancellation fences Paperclip authority. It does not confirm that Dot
stopped all external activity.
- Assigned skill files and third-party MCP bindings are unsupported and
reject admission. There is no mounted workspace, model selector, or
provider thread identifier.
- Hosted agent-broker and remote controller deployments are not
qualified.
- The new migration follows the merged master history. Existing
prototype databases still need the normal master migration history
before this Dot-only migration.

## Model Used

OpenAI Codex, based on GPT-6. The exact deployment ID and context window
size are not exposed in this session. Capabilities used: reasoning,
repository editing, code execution, and test 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 #123` 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
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-07 19:11:50 -05:00
DottaandPaperclip d0db8820db fix(connections): repair native baseline and approval continuations (#15420)
## Thinking Path

> - Paperclip manages AI agents and the tools they may use.
> - Connection setup separates provider preference from permission to
use a tool.
> - The first native connection baseline could not exercise its intended
decisions.
> - The browser used mutable task titles, and the provider fixture
already granted access.
> - Native provider-choice instructions also disagreed with the
preferred question format. Schema rejection gave no field guidance.
> - This pull request repairs those test preconditions and native
guidance, then fixes restart/approval defects exposed by the corrected
baseline. It also restores missing OpenCode tool-error evidence.
> - The benefit is an inspectable baseline before any further
instruction reduction.

## Linked Issues or Issue Description

Refs #15407.

The original 15-cell baseline remains 0 PASS / 15 FAIL. Ten cells
stopped on stale titles, two Codex cells had schema denials, two
OpenCode cells used already-granted tools, and one Claude cell returned
no native result. No intended user decisions were submitted. The exact
invalid Codex field and underlying Claude failure cause remain unknown.

[Original
campaign](https://github.com/paperclipai/paperclip/actions/runs/37562577199)
· [Original
report](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-37562577199-1/index.html)

## What Changed

- Match the browser's task route and visible identifier instead of a
title the agent can change.
- Start native provider-choice fixtures with no agent tool access.
Verify the public effective-access records.
- In the positive case, select Arcade, then grant its exact HubSpot tool
through the real access card. Require both saved decisions and exactly
one observed call.
- Return a canonical `providerQuestionSet` for native input and retain
the equivalent legacy `providerQuestion`.
- Keep invalid input rejected. Return bounded schema locations and
required field names without submitted values.
- Preserve Claude's exact session/content identity while allowing
authenticated registered instruction-copy paths to rotate on a new run.
- Reject duplicate approval reports for an existing exact tool-action
card before they create another human review.
- Wait for a recorded service-approval continuation within the existing
deadline; retain missing or failed continuation grades.
- Forward OpenCode tool activity through the runner facade, preserving
bounded errors and execution-part identity without inventing host-call
joins or exposing arguments.
- Preserve original grades, costs, scope limits and diagnoses in the
dated repair report.

## Verification

- Eval typecheck passes. Support suite: 1,801 PASS, one intentional
skip; Node checks: 128 PASS.
- Connection/schema tests: 51 PASS. Real-server public fixture setup:
one PASS with zero providers.
- Browser support regression: five PASS, including renamed and wrong
tasks.
- Focused Rust safe-feedback test: one PASS.
- Repository typecheck and build pass before the latest master replay.
Post-replay connection/shared/real-server fixture checks: 52 PASS; eval
typecheck passes. The browser review fix additionally passes all five
browser checks and seven suite checks.
- The full local repository run was interrupted incomplete after about
45 minutes, with five integration failures retained. All five pass in a
separate targeted invocation (1,250 unrelated tests skipped). No full
local-suite pass or root cause for the initial local failures is
claimed.
- Corrected frozen source `162cc90fdabe7f505b88ae095044531b82784c92`:
**10 PASS / 5 FAIL** across the [passing Codex
canary](https://github.com/paperclipai/paperclip/actions/runs/37575158761)
and [remaining 14
cells](https://github.com/paperclipai/paperclip/actions/runs/37576261807).
The canary passes all 17 checks. Claude's two provider-choice
continuations fail on restart, Claude service approval exposes an early
evaluator rejection, Codex service approval creates a duplicate
approval, and OpenCode provider-second times out after both decisions
with no HubSpot call. No original result is regraded.
- Final ledgers count 31 actual runs: 27 succeeded, two failed, two
cancelled during cleanup. All 15 cleanup/budget checks pass. The late
Claude continuation is absent from its earlier workflow snapshot; it
remains in the result/API/final ledger. Original evidence retains 279
hashes. Recorded LLM subtotal $0.04553787 is incomplete billing, not
actual total cost; local runtime is unmetered.
- New repair regressions reproduce the Claude attach failure, duplicate
approval acceptance and dropped OpenCode tool events before their
respective fixes. Nine Rust attachment checks, 127 ACPX host/adapter
tests, 33 completion/control-plane checks, nine eval deadline tests, 59
OpenCode proxy/driver tests, one Rust tool-error/redaction check, and
TypeScript/Rust composer parity pass. Eval typecheck, repository
typecheck and build pass. Existing support coverage is 1,802 PASS plus
128 Node PASS, one intentional support skip; two additional deadline
tests also pass.
- New-source full CI/review and live canaries are pending. The next
bounded selection is Claude provider-decline, Codex service-approve and
one OpenCode provider-second diagnostic with repaired event evidence. No
broader campaign or instruction-reduction qualification is claimed.
- Initial corrected campaign
[37574251834](https://github.com/paperclipai/paperclip/actions/runs/37574251834)
was cancelled during shared build after review found the breadcrumb
whitespace assumption. Its matrix job has zero steps and no provider
execution. The real adjacent-span browser regression now reproduces the
old failure and passes after the fix.

## Risks

- The corrected baseline remains 10/15. The new restart/approval fixes
require live qualification; OpenCode evidence forwarding does not itself
establish or fix its prior behavioral failure.
- The positive provider case now expects three runs, including separate
access approval. Its new results are distinct from the original invalid
fixture.
- The old Claude missing-result cause and rejected Codex field are
unknown. These repairs do not retroactively explain or erase either
failure.
- Path rotation must preserve prompt, custom instruction, skill/content
identity and protected provider settings; regression checks reject stale
or changed content. No connection authorization, JSON schema, budget,
cleanup, or final-result requirement is relaxed. Historical Everyday
prompts and gateway setup remain unchanged.

## Model Used

OpenAI Codex, GPT-6. The exact deployment variant and context window are
not exposed in this session. Used repository inspection, code editing,
test execution and retained-evidence analysis.

## 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-07 06:18:51 -05:00
DottaandPaperclip a6306ba606 feat(runner): consolidate Cursor production integration (#15075)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native Runner keeps provider sessions under company authority,
approvals, budgets and durable recovery.
> - Cursor work was spread across candidate branches. The published
branch lacked later plan, permission and cleanup fixes.
> - Production also needs public installation and matching runtime
assets for local and Daytona execution.
> - This pull request consolidates Cursor onto current mainline recovery
behavior and completes that installation path.
> - The installed v11 release passed focused local and Daytona
qualification after the generic mode and lifecycle cleanup. The later
model-selection correction and current mainline merge produce v14
artifacts that need matching release qualification.
> - Cursor admission is enabled in source; publish only an artifact
combination with matching qualification. Native AskQuestion and complete
per-run dollar accounting remain excluded.

## Linked Issues or Issue Description

Refs: #14435, #14631, #14669, #14699, #14724.

This completes the Cursor implementation by @cryppadotta from combined
source `22c78242a4e0c2369fecf0c2dc4e7600fbad6706`. It preserves newer
mainline recovery, completion and warm-directory behavior. Pi and
Copilot remain gated.

## What Changed

- Generate named Rust and TypeScript ACPX release profiles from one
manifest. Share runtime pins with packaging and server verification.
Preserve vendor runtime versions; bind the updated ACPX patch to Cursor
profile v14 and reject stale generated declarations at build/typecheck.
- Remove ACPX model allowlists, including the former Codex and Pi
restrictions and the duplicate developer test-drive gate. Send any
explicit model ID unchanged to its provider and verify the effective
selection before prompting. The bundled ACPX package forwards unlisted
IDs, rejects mismatched acknowledgements, and restores the exact
selection after session load. It does not expand Cursor model aliases.
Provider rejection, mismatch, or missing model controls fails without a
fallback. Model examples live in evaluation fixtures, outside runtime
declarations.

- Add pinned Cursor execution, contained instructions, exact model
verification and Agent/Plan/Ask modes.
- Carry an opaque generic `mode` identifier in shared native execution,
sidecar, Rust and recovery contracts. The provider adapter owns
supported modes, defaults, native translation and acknowledgement.
- Keep native RPC recognition, accepted-plan interpretation and
permission evidence behind provider adapters. Shared settlement and
recovery verify normalized facts and their committed evidence.
- Replace the Cursor-only warm-attachment branch with a runner-owned
capability. Only Cursor opts into it. Move profile compatibility and
optional usage parsing into provider metadata and adapters.
- Write generic plan-wait receipts. Read exact historical Cursor
receipts through a separate compatibility decoder. Reject mixed formats
and preserve existing authority checks.
- Carry native plans, semantic questions, todos, child activity,
permission identities and partial usage diagnostics through the Runner.
- Preserve durable response delivery, cancellation, warm ownership and
process retirement.
- Finish accepted planning runs successfully. Keep their tasks open for
explicit direction. Acceptance does not start implementation.
- Ship `paperclipai runtime setup cursor` and its provisioner through
the public package. npm installation does not download Cursor. Setup
uses the OS account's closure-keyed cache so system-wide npm packages
can remain read-only. Run it as the Paperclip service account.
- Include Cursor in normal provider packs and Daytona images for macOS
ARM64/x64 and Linux x64.
- Reject stale release packs by source revision and current ACPX/Cursor
pins before assembly writes files. Verify current Cursor
version/profile/closure again at runtime.
- Ship all three daemon targets and the expected Linux image-pack
identity. A macOS controller uses its packaged Linux daemon for Daytona.
Image mismatches fail before provider launch.
- Use the vendored Runner boundary for installed readiness probes.
Verify the actual installed Cursor probe.
- Verify compiled public Daytona plugins and their release versions in
installed smokes.
- Record exact artifacts, the acceptance matrix, retained failures,
supported capabilities and rollback behavior in the [readiness
report](https://github.com/paperclipai/paperclip/blob/codex/cursor-production-readiness/doc/plans/2026-10-03-cursor-production-readiness.md).

## Verification

- Current head `f7ec5cc1f0e30c62a829c016ff2013a2a9d79037` merges
mainline `faa8e452c73bae5e044dd6379179a00106abb131`. It keeps Cursor
plan and cancellation guards alongside mainline historical-question
filtering. The evaluation catalog includes both Cursor and expanded
adapter accounting cases (683 total). Recursive typecheck, full build,
696 lifecycle/recovery tests, 45 fixture tests and fixture typecheck
passed. Current-head CI passed: 56 successful checks, one neutral and
four skipped. [Complete
CI](https://github.com/paperclipai/paperclip/actions/runs/37557996535).
The fresh Base Greptile review is 5/5 on this exact head, with 304 files
reviewed, zero new comments and zero unresolved threads. The user
authorized overriding the CODEOWNER review gate after checks passed; no
failing checks are overridden. Prior results below retain their own head
identities.
- Corrective head `3d2b168366258036f6b6a6fccb382c49138cc601` fixes the
post-merge Apex finding. Automatic-review and new-evidence
reconciliation preserve pending child results and recheck delivery under
the status lock before completing. Account repair now excludes unrelated
secret consumers and requires the failed agent's identity. Regression
coverage includes the commit race, delivery statuses,
current-run/current-intent exclusions, repeated reconciliation, both
database reconciliation paths, and credential consumer boundaries. All
184 affected tests, server typecheck and server build passed.
Current-head Base Greptile review is 5/5, with 304 files reviewed, zero
new comments and zero unresolved threads. Current-head CI passed: 56
successful checks, one neutral and four skipped. [Complete
CI](https://github.com/paperclipai/paperclip/actions/runs/37535994724).
This Base review is distinct from the earlier Apex review.
- Merge head `5957c257a` reconciles mainline `b508a05c4`. It preserves
both accepted-plan waits and pending-child-completion checks, current
provider selectors, task-creation response identities, and mainline ACPX
missing-file handling. The combined patch is bound to Cursor profile
v14; historical records keep their original identities.
- Merge head `5957c257a` passed recursive typecheck, full build, 43
installed ACPX/package contracts, 107 provider UI and plan/recovery
tests, 593 database-backed lifecycle tests, 49 profile/native contract
tests, 45 Product E2E fixture tests, fixture typecheck, token gates,
three provider-free browser task-creation cases, and Runner
conformance/replay checks. Its complete CI passed (55 successful checks,
one neutral and four skipped), while Apex returned 2/5 with a
child-delivery finding addressed below.
- The local full-suite attempt again failed the unchanged Git streaming
test (360-second timeout) and was stopped. The concurrent local Rust
attempt failed four unchanged Codex process/deadline tests; all four
passed serially without code changes in 7.29 seconds after removing the
competing test load. These failed commands are retained and are not
reported as full-suite passes; the fresh Linux CI runs are tracked
separately.
- The previous head `907bdb2a2778c7ffeb4a662a91460c9d1ddfc9c5` earned
Apex 5/5 with zero comments after fixing all three findings: per-user
install cache, stale release-pack rejection, and public Linux smoke
account/home handling. Its real built installer passed from read-only
public packages on macOS ARM64 and Linux x64. All 137 release-registry
checks and 64 ACPX package contracts passed. That review does not cover
this mainline reconciliation.
- Prior `beadd3654` passed the full CI matrix; its one unchanged chat
test failure and successful single retry remain in the [CI
history](https://github.com/paperclipai/paperclip/actions/runs/37521449327).
Historical results below remain attributed to their original builds.

- Fixture follow-up `dd59d7e82b103a88b7cbd7d2c38b612c0fbbff7a` removes
provider-specific model choices from generic offline ACPX tests. The
fake sidecar preserves the model and session identity selected at open
through suspension. Affected verification passed: 106 Rust tests and 73
TypeScript tests. This commit changes test code only; the
production-code checks below retain their recorded identities. Its CI
and Greptile review later passed; those results belong to that
historical head.
- Model-selection cleanup `9a070808b48960a41fdfd369ae0636b95af82459`:
252 focused Runner tests passed (six platform skips), covering all six
ACPX agents, native model acknowledgement, rejected selections,
installation integrity and recovery identity. The merged branch passed
recursive typecheck, full build, token gates, server admission (19
tests), and the Product E2E catalog (45 tests). The acceptance catalog
passed all four tests. The full Rust suite passed: 643 tests, 2 ignored.
It verifies sidecar acknowledgement of unlisted models and rejection of
model mismatches. The final commits only update Rust tests; production
sources match the verified build at
`65ec3279ac50185e3cda109b5cfd9b4f56105de0`. No new paid provider calls
were made.
- The merge preserves both Cursor and the new mainline public-MCP
fixture cases. Auto-merge remains disabled; the latest follow-up status
is recorded above. The local `pnpm test:run` attempt hit the unchanged
Git streaming test's 300-second timeout and was interrupted before
merging mainline. The broad Runner attempt found obsolete single-model
assertions plus three macOS fixture-path failures caused by a
`/private/tmp` override. The assertions are corrected; affected
TypeScript checks passed with the standard macOS temporary directory,
and the complete Rust suite passed. Neither interrupted command is a
full-suite pass.
- Earlier declaration-cleanup head `6f4a5e9e2` passed recursive
typecheck, build, Rust and focused tests. Its CI later exposed a test
expecting duplicated Grok digest literals. The current source fixes that
assertion to compare launcher bytes with the shared manifest. Historical
successes and failed attempts are retained; no new live provider
qualification is claimed.
- Previous head `e75fde6098b0ddd8cec765bfb6ecaeecb88a26a6` passed
complete CI (56 successful checks, one neutral, four skipped) and
Greptile 5/5. [Historical complete
CI](https://github.com/paperclipai/paperclip/actions/runs/37489112305).
Those results are not claimed for the cleanup head.
- Frozen live application: `d7b696f9b8f79095233e9e3d56d23e6a6018dd48`.
Public package version: `0.0.0-cursor-verify.3d0c9b7761c6`. The
declaration cleanup preserves release pins and does not relabel that
tested artifact as a build of the new source. Mainline through
`e34abee670` was reconciled while preserving accepted-plan waits,
provider-capacity handling, and both Cursor and public-MCP fixtures.
- Clean normal installation, explicit Cursor setup and daemon resolution
passed on macOS ARM64, macOS x64 under Rosetta, and Linux x64. npm
lifecycle hooks ran without silently downloading Cursor.
- Historical v11 live matrix: **18/18 passed with cleanup** (nine local,
nine Daytona) after the generic mode and lifecycle cleanup. The campaign
has 23 attempts; all five failures and their diagnoses remain recorded.
Exact case identities, hashes and limits are in the readiness report.
All provider calls are real, use the explicit Luna model and
company-bound credentials, and run without qualification or
runtime-asset overrides.
- The immutable Daytona image is
`ghcr.io/paperclipai/paperclip-daytona-runner@sha256:d6259b6bba094702c13fc2283bd85550849c1c53145b656fb2746778f9fa1747`.
The public Daytona plugin is installed independently and its version is
checked.
- Recursive typecheck, full build, token gates and Runner
contract/conformance/replay checks passed on the frozen application. Its
complete Linux CI suite passed. The duplicate local full-suite command
was incomplete after timing failures; affected repeats passed, but that
command is not reported as a clean pass.
- Qualification fixtures passed typecheck, 1,675 Vitest tests (one
skip), 128 Node checks, three provider-free browser tests, and 150
focused lifecycle tests after the final diagnostic correction. The
affected legacy Cursor command file also passed all five tests after
removing its shorter 10-second override; it now inherits the suite’s
standard 15-second timeout. Greptile is 5/5 on `e75fde609` with no
unresolved review threads. CI results above are recorded separately from
historical build results.

## Risks

- Cursor v14 includes the updated ACPX dependency patch and release
identity. The v11 live matrix and image below remain historical
evidence. They do not certify new v14 package/image artifacts.

- ACPX accepts models beyond the qualification fixtures. Availability
and entitlement depend on the provider. Successful configuration is not
a claim of live qualification for every model.
- Shared mode is an opaque identifier. Provider adapters own its
meaning. Incompatible historical sessions remain fenced; exact committed
plan waits and task history remain inspectable.
- Native AskQuestion is excluded. Paperclip semantic questions are
supported. Authoritative per-run dollar accounting is unavailable;
partial counters remain diagnostics and unknown cost is not zero.
- Image input, detailed native diffs, deeper child transcripts and
native plan-file export remain follow-ups.
- macOS x64 has clean-install and daemon-startup proof under Rosetta,
not a separate live campaign on Intel hardware.
- Release only the tested package/image combination. Merging this PR
does not publish npm packages or deploy that image. Later builds need
their own release verification. Rollback disables new Cursor admission
while preserving records and recovery inspection.
- A model can fail an exact instruction: one cancelled-plan attempt
returned the wrong summary marker despite correct cancellation. The
unchanged repeat passed; both results remain in the report.

> ROADMAP.md was checked. This completes existing native Runner/Cursor
work; it does not add an independent core feature proposal.

## Model Used

OpenAI Codex, GPT-6. The exact serving variant and context window are
not exposed in this session. The agent used reasoning, repository
inspection, code execution, protocol tests and browser-backed Product
E2E tools. Cursor acceptance uses the explicit
`gpt-5.6-luna[context=272k,reasoning=medium,fast=false]` model. That is
the evaluated provider 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 tests locally and they pass — affected suites passed;
full CI and the retained local failed attempts are recorded separately
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 — 56 successful checks, one
neutral and four skipped on `f7ec5cc1f0e30c62a829c016ff2013a2a9d79037`
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
fresh Base review passed on `f7ec5cc1f0e30c62a829c016ff2013a2a9d79037`;
zero new comments and no unresolved threads. The earlier Apex finding
remains fixed.
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 20:48:15 -05:00
Devin FoleyandPaperclip 7eadc714d2 Verify native semantic input against its raw wire digest (#15301)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native runners send authenticated semantic tool inputs to the
control plane.
> - The runner hashes the complete input, but the receiver used a
redacted receipt hash.
> - Protected fields and credential-like document text can therefore
fail integrity validation even when the input is unchanged.
> - This pull request verifies the complete input with the existing
canonical hash function.
> - Receipt redaction and permanent rejection of altered input remain in
place.

## Linked Issues or Issue Description

**What happened?**

The Rust runner preserves tool arguments and hashes their canonical
JSON. The TypeScript receiver instead redacts the input before hashing.
A valid input such as a synthetic document containing `Bearer
fixture_token_123456` fails with `native_event_replay_conflict`. A
digest of redacted input can also pass without proving the original
protected values.

**Expected behavior**

Verify the complete transmitted input after authentication and exact
scope checks. Reject any incorrect digest before durable commit,
dispatch, or ACK.

**Steps to reproduce**

Run the new authenticated controller regressions against the prior
receiver. The protected-field and credential-like document cases fail,
and the redacted-digest rejection case receives an ACK. The same tests
pass with this change.

**Paperclip version or commit**

Reproduced from source at `858094ba8123c7edb56623597cd96f0391f7e2d4`
with synthetic fixtures. Applies to native runner deployments.

Related: #14937 preserves semantic input bytes for execution. GitHub
issue and PR searches found no duplicate fix; #14591 touches a separate
question-draft contract.

## What Changed

- Use the existing bounded raw canonical digest for incoming semantic
and MCP tool inputs.
- Keep receipt and diagnostic redaction unchanged.
- Share four digest fixtures between Rust and the authenticated
TypeScript controller, including protected fields, document text,
Unicode keys, and number boundaries.
- Test raw acceptance, altered protected values, forged and redacted
digests, canonicalization limits, permanent reconnect fences, and
authentication/scope rejection.
- Document the separate wire and receipt contracts and the unchanged
recovery fence.

## Verification

- Before the production fix, the new selected regressions produced three
expected failures and eight passes.
- Focused controller, receipt, and semantic-tool suites: 138 tests
passed.
- Rust shared digest fixture test: 1 test passed.
- Full workspace typecheck and build passed; the final receiver delta
also passed its TypeScript typecheck. Canonical Linux PR CI passed the
full aggregate test gate, runner checks, build, and canary dry run at
`efcd38e2d8a9fa6340db4f4e863b6febbe8ca32a`.
- Independent review passed, including 18 independently run
authenticated regressions and the Rust golden test, plus both
matching-digest size-limit cases after the test-only follow-up. Greptile
is 5/5 on the current head with no unresolved threads. Diff whitespace
and local secret/PII scan passed; fixtures are synthetic.

## Risks

The verifier remains strict: there is no redacted-digest fallback.
Existing authentication, scope, sequence, replay, settlement, and
authorization checks remain in force. Receipt storage and redaction
behavior are unchanged. This patch does not clear failed-run fences or
replay prior work. Synthetic tests prove the protocol mismatch; they do
not identify the contents of any historical rejected input.

## Model Used

OpenAI Codex (GPT-6), with reasoning, code execution, and independent
agent review. 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
- [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-05 20:21:01 -07:00
6c36c07a4f feat(adapters): add GPT-6.1 Sol and refresh shared coding harness pins (#14942)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents run through coding-agent adapters and the native runner. Both
use the same installed provider CLIs, model catalogs, and reasoning
controls.
> - OpenAI released GPT-6.1 Sol (`gpt-6.1-sol`) in Codex. Anthropic
released Claude Sonnet 5.5. The static Codex, Bedrock, and OpenCode
catalogs do not list these IDs.
> - The shared provider pack pins Codex 0.156.0 and OpenCode 1.18.32.
The evaluation image pins older Grok, Gemini, Kimi, Cursor, and GitHub
CLI releases. Codex 0.156.0 has no bundled metadata for GPT-6.1 Sol.
> - A model entry without a current harness, or a harness pin without
its runner integrity checks, fails at run time.
> - This pull request adds the verified model IDs and moves the harness
pins, executable digests, controller checks, and image pins together.
> - The benefit is that operators can select the current models, and the
native and local adapters share one current CLI installation.

## Linked Issues or Issue Description

Refs #13829 and #13838 (the September 22, 2026 model and harness
refresh). Related pull requests: #14993 (merged October 5, 2026,
superseding #14816) added the direct Claude Sonnet 5.5 entry and
refreshed the Claude runtime to Agent SDK 0.3.286 / Claude Code 2.1.286.
This pull request does not change the Claude runtime or the direct
Claude model list; it keeps the #14993 pins and adds only the Bedrock
Sonnet 5.5 ID. After #14993 merged, this branch was rebased onto
`master` (October 5, 2026). The six overlapping pin regions
(`docker/daytona-runner/Dockerfile`, `docker/daytona-runner/README.md`,
`package.json`, `pnpm-workspace.yaml`,
`packages/adapters/claude-local/src/index.test.ts`,
`packages/paperclip-runner/src/backends/native-backend-factory.test.ts`)
were resolved by keeping this pull request's Codex 0.160.0 and OpenCode
1.18.34 pins next to #14993's Claude 0.3.286 / 2.1.286 pins, taking the
union of the Sonnet 5.5 model IDs in the Claude test, and merging both
README paragraphs. The Sonnet 5.5 effort and CLI-gate lines in the
Claude adapter were identical in both pull requests and merged without a
diff. #14917 and #14918 reordered the Claude and Codex model lists
earlier; the new entries sit where those ordering rules put them.

Sources checked on 2026-10-02:

- [OpenAI Codex models](https://learn.chatgpt.com/docs/models): GPT-6.1
Sol uses `gpt-6.1-sol`, supports reasoning efforts from Light to Ultra,
and has Standard and Fast modes at launch. The page also records that
`gpt-5.4` and `gpt-5.4-mini` retired from Codex with ChatGPT sign-in on
August 31, 2026, and that `gpt-5.5` retires on October 14, 2026. Neither
retirement applies to the OpenAI API.
- [Codex CLI releases](https://github.com/openai/codex/releases) 0.157.0
through 0.160.0. The bundled model metadata in the 0.160.0 Linux binary
contains `gpt-6.1-sol`.
- [Claude Sonnet
5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview):
Bedrock ID `anthropic.claude-sonnet-5-5`, released September 28, 2026.
- [OpenCode releases](https://github.com/anomalyco/opencode/releases)
1.18.33 and 1.18.34 (fixes only). The OpenCode model registry lists both
added provider-qualified IDs.
- npm `latest` tags for `@xai-official/grok` 1.0.46,
`@google/gemini-cli` 0.62.0, and `@moonshot-ai/kimi-code` 2.1.1.
[xAI](https://docs.x.ai/docs/models),
[Google](https://ai.google.dev/gemini-api/docs/models), and
[Kimi](https://www.kimi.com/code/docs/en/kimi-code/models.html) list no
newer coding models.
- Cursor CLI 2026.10.01-e373342 is the version the official installer
resolves. The pinned digest is the SHA-256 of the versioned Linux x64
archive.
- [GitHub CLI 2.102.0](https://github.com/cli/cli/releases/tag/v2.102.0)
(security fixes). The pinned digest matches the release `checksums.txt`.

## What Changed

- Codex adapter: add `gpt-6.1-sol` to the model list, the Fast mode
list, and the Ultra effort set. It is the first entry: #14918 orders the
list newest version first, and its description notes the ChatGPT app
lists GPT-6.1 Sol first. Update the adapter documentation text.
- Claude adapter: add `us.anthropic.claude-sonnet-5-5` (Bedrock Sonnet
5.5) to the Bedrock catalog in the newest-Sonnet slot after Opus 5.5;
`us.anthropic.claude-sonnet-5` moves into the older-Sonnet group,
matching what `sortClaudeModels` from #14917 produces at runtime. Any
Sonnet 5.5 ID (direct or Bedrock-qualified) now gets the documented
`xhigh` and `max` efforts and requires Claude Code 2.1.284 or later on
the CLI lane (the Claude Code changelog entry for 2.1.284 adds
`claude-sonnet-5-5`). These two lines are identical to the ones #14993
merged, so the branch carries no diff for them.
- OpenCode adapter: add `openai/gpt-6.1-sol` and
`anthropic/claude-sonnet-5-5` to the static fallback catalog.
- Codex runtime pin 0.156.0 → 0.160.0 in the root and workspace
overrides, the runner package, the Codex ACP package patch, the
qualified ACPX profiles, the Linux x64 executable digest, the Rust
provider backend and its tests, the provider-pack manifest pins, the
remote controller pins, the sandbox npm install spec, and the opt-in
qualification scripts.
- Remote Codex compatibility window: upper bound 0.157.0 → 0.161.0. The
minimum stays at 0.149.0.
- OpenCode runtime pin 1.18.32 → 1.18.34 in the runner package, the
materialization script, the server and Rust qualified versions, the eval
and live-session labels, fixtures, and the configuration label.
- Evaluation image (`docker/daytona-runner/Dockerfile`): Grok CLI
1.0.46, Gemini CLI 0.62.0, Kimi Code 2.1.1, Cursor CLI
2026.10.01-e373342 with its digest, GitHub CLI 2.102.0 with its digest,
Codex and OpenCode version probes, and the refreshed lockfile digest.
The Claude Code 2.1.286 probe comes from #14993 and is unchanged here.
- `pnpm-lock.yaml` is not part of this pull request. The repository's
pull request gate rejects lockfile edits, and the refresh bot
regenerates the lockfile on master (the same flow #13838 used). The
Dockerfile `PAPERCLIP_RUNNER_LOCK_SHA256` default is the digest of the
lockfile that `pnpm install --resolution-only --ignore-scripts
--no-frozen-lockfile` (the refresh workflow's command) produces for the
combined pins on the rebased branch (`e1856797…`); that lockfile differs
from master only in the `@openai/codex` 0.160.0 platform packages, the
`@anthropic-ai/claude-agent-sdk` 0.3.286 override that #14993 introduced
(the open refresh-bot pull request #14872 carries that part),
`opencode-ai` 1.18.34 with its Linux x64 baseline, and the `codex-acp`
patch hash.
- Documentation: runner README, runner compatibility doc, environment
variable example, and a new `doc/adapter-model-audit-2026-10-02.md` with
sources and deferred items.
- Tests: Codex adapter catalog, server adapter models, Codex
compatibility window, native session executor pins, runner package
contract, OpenCode materialization, and UI effort options.

Unchanged on purpose: Claude Agent SDK 0.3.286 / Claude Code 2.1.286
(already on `master` from #14993), ACP bridges (`acpx` 0.13.1,
`claude-agent-acp` 0.73.0, `codex-acp` 1.6.2; newer upstream releases
need a separate qualification), the native Grok runtime 1.0.13, Pi
0.84.2 / 0.87.1 (the Pi 1.0 runner stack covers it), and Hermes 0.19.0
(current). `gpt-5.4` and `gpt-5.4-mini` stay in the picker because the
OpenAI API still serves them.

## Verification

Run on Linux x64 with Node 25.9.0 and pnpm 9.15.4 after `pnpm install
--no-frozen-lockfile` (the refreshed lockfile stays local; see above).
The results below were re-run on the rebased head (October 5, 2026) for
the suites the conflict resolution touches; the other rows are from the
original run and are covered by CI on every push:

- Rebased head: `packages/adapters/codex-local` 482 passed;
`packages/adapters/claude-local` 340 passed, 4 failed (`execute.remote`,
`test.probe`, `execute.acp-fallback`, `acp` spawn/env-hardening cases
that fail identically on unchanged `master` in this host environment);
`server` adapter-models + codex-runtime-compatibility +
native-session-executor + adapter-registry 607 passed, 1 failed (the
same adapter-registry override-pause case as before, also failing on
`master` here); `packages/paperclip-runner` native-backend-factory +
qualified-profiles 36 passed; `ui` codex-reasoning-effort +
config-fields + model-utils 19 passed. Rust, full typecheck, build, and
the Docker image are left to CI as before.

- `vitest run` in `packages/adapters/codex-local`: 13 passed. `vitest
run` in `packages/adapters/claude-local` (whole package, including the
new Sonnet 5.5 gate and effort tests): see the latest CI run and the
comment below. `vitest run` in `packages/adapters/opencode-local`: 48
passed, 1 failed (`runtime-config.test.ts` reads the host
`PAPERCLIP_OPENCODE_PROVIDERS` variable; it fails the same way on the
unchanged base).
- `vitest run src/__tests__/adapter-models.test.ts
src/services/native-runtime/codex-runtime-compatibility.test.ts
src/__tests__/adapter-registry.test.ts` in `server`: 84 passed, 1 failed
(`adapter-registry.test.ts` override pause test; it fails the same way
on the unchanged base).
- `vitest run` in `ui` for `codex-reasoning-effort`,
`agent-setup-fields`, `config-fields`, and `ComposerRunSettingsPicker`:
25 passed.
- `node --test test/acpx-codex-package-contract.test.mjs
scripts/materialize-opencode-binary.test.mjs
scripts/runner-protocol-eval-campaign.test.mjs` in
`packages/paperclip-runner`: 23 passed. The package contract test
verifies the installed Codex ACP executable digest and the 0.160.0 patch
pin.
- `vitest run src/drivers/acpx src/backends src/drivers/opencode
src/live/live-session.test.ts` in `packages/paperclip-runner`: 626
passed, 5 failed, 1 skipped. The 5 failures
(`installation-integrity.test.ts` `/proc/self/fd` module loading and one
OpenCode answer-selection test) also fail on the unchanged base under
Node 25; Linux CI runs Node 24.
- `pnpm run test:opencode:qualification` in `packages/paperclip-runner`
against the installed OpenCode 1.18.34 executable: passed.
- `codex --version` from the installed pack prints `codex-cli 0.160.0`.
The Linux x64 executable digest `12eb3e81…652aad` was computed from the
`@openai/codex@0.160.0-linux-x64` archive after checking its registry
`dist.integrity`.
- `pnpm check:token-gates`: all gates clean.
- `pnpm run typecheck:typescript` in `packages/paperclip-runner`:
passed. Package typechecks ran one at a time; see the comment below for
the server and UI results.

Not run here, and needed from CI:

- Rust tests and `pnpm -r typecheck` / `pnpm build` for the server (no
`cargo` in this environment; the server typecheck prepares the runner
vendor build).
- The Docker evaluation image build and the real-binary Codex startup
and session-resume probes (no Docker; the probes need the compiled
`paperclip-runnerd`). The trusted CI runner workflow covers them.
- Authenticated inference with any new model. This change is metadata
and startup validation only.

## Risks

- Codex 0.160.0 changes the bundled model catalog and app-server
behaviour (authoritative provider catalogs, incremental running-turn
tracking). The patched `codex-acp` 1.6.2 bridge is unchanged and
declares `^0.148.0`; it worked with 0.156.0 under the same override. If
CI probes show a protocol change, the pin can return to 0.156.0 by
reverting this pull request.
- The compatibility window upper bound moves to `<0.161.0`. Remote
images with Codex 0.157 to 0.160 become accepted. Older images stay
accepted down to 0.149.0.
- Until the refresh bot lands the regenerated lockfile on master, the
Dockerfile lockfile digest default does not match the committed
lockfile. The trusted CI workflow computes the digest from its own
resolution at build time, so this affects only a local build that passes
no digest.
- Existing saved model selections and effort settings are not changed.
Agents on `gpt-5.4` or `gpt-5.5` with ChatGPT sign-in need a model
change before the OpenAI retirement dates; that is documented, not
enforced.
- Rollout order: deploy the controller and runner from this change
before promoting a sandbox image that carries these pins. Older
controllers reject the new provider-pack pins.

## Model Used

- Claude Fable 5.1 (Anthropic, model ID `claude-fable-5-1`), 1M context
window, adaptive thinking, tool use. The model ran as a Paperclip agent
through the Claude Code harness, performed the web research, edited the
code, and ran the tests listed above.

## Checklist

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

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

---------

Co-authored-by: Bender (Fable) <noreply@paperclip.ing>
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 13:59:08 -07:00
cab4263dc9 feat(claude-local): add Sonnet 5.5 and refresh the qualified Claude runtime (#14993)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Claude local adapter lists models for users with a Claude
subscription.
> - The list needs Claude Sonnet 5.5 and its supported effort levels.
> - Sonnet 5.5 needs Claude Code 2.1.284 or later on both execution
paths.
> - The qualified ACP runtime previously used Claude Code 2.1.280.
> - This change adds Sonnet 5.5 and pins Agent SDK 0.3.286, which
includes Claude Code 2.1.286.
> - Users can select the model and run it with a qualified runtime.

## Linked Issues or Issue Description

Refs #3936. This replaces #14816 because the maintainer integration
cannot write to the contributor fork.

Thank you to @SkilLab-Tech for the model support, runtime refresh,
tests, and platform digest verification. This branch preserves both
original commits: `8d2f3261af61a2ac1120e51e8a8618732ace543b` and
`e68d1d002a3ed745f016fb11c50ac5a3c5a9ff8d`.

Related work:

- #14917 added Claude model ordering. This branch includes that merged
change and resolves its conflicts with #14816.
- #14942 updates the other models and harnesses. It remains separate.
Its matching Sonnet effort and CLI-gate changes are identical. Both PRs
merge with master. The second PR will need a rebase after the first
merges because adjacent runtime-pin and test edits conflict.
- #14954 is another Sonnet 5.5 change. It overlaps with the model
additions but does not include the qualified runtime refresh.
- #14039 makes the per-task effort picker model-aware. #3937 is also
related to effort selection.

The original author checked the [Claude Code
changelog](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)
and [effort
documentation](https://platform.claude.com/docs/en/build-with-claude/effort)
on 2026-10-01.

## What Changed

- Add the direct `claude-sonnet-5-5` model and Low, Medium, High,
X-High, and Max effort levels.
- Require Claude Code 2.1.284 or later for that model on the CLI path.
- Put Sonnet 5.5 after Opus 5.5 in the current-model group. Keep Sonnet
5 in the older-model group.
- Retain the Sonnet 5.5 assertions and the model-order assertions in the
server tests.
- Pin Agent SDK 0.3.286 and Claude Code 2.1.286 across overrides,
integrity digests, qualified profiles, Rust provider pins, and the
Daytona version check.
- Update the related adapter and runtime documentation.

## Verification

Local verification uses the resolved source tree and pnpm 9.15.4. Model
tests passed on Node 25.9.0. Runtime integrity tests use CI's Node
24.21.0.

- Five focused Claude test files pass: 62 tests. They cover model
defaults, model ordering, CLI gates, and remote execution probes.
- Server model-list and UI setup tests pass: 30 tests.
- The Claude adapter typecheck passes.
- Runner integrity and qualification tests pass on Node 24.21.0: 78
tests. Four descriptor-loader tests fail on Node 25.9.0; all four pass
on the CI version.
- The runner package contract passes: 10 tests.
- Full local typecheck stopped with exit 137 in the database package
under the container's 4 GB memory limit. The production build reached
the runner Rust build, then stopped because `cargo` is absent.
- The full stable local Vitest run was stopped after all current-head CI
test shards passed. It did not complete locally. The 180 focused tests
listed above passed.
- `git diff --check` passes. The branch changes 20 files against master.
It has no lockfile or workflow changes.
- The original author verified all three platform digests against
registry integrity and ran the Linux executable. Its version was
`2.1.286 (Claude Code)`. See #14816 for that evidence.
- Greptile reviewed head `6db3d3f1` and gave 5/5 with zero comments.
Both Superagent scans and Commitperclip pass. All current-head CI jobs
pass, including build, typecheck, Rust, test shards, browser tests, and
the canary dry run.

## Risks

- The controller and provider pack must use matching runtime pins.
Deploy them together.
- CI owns `pnpm-lock.yaml`. The master lockfile refresh must resolve the
SDK override. Refresh the Daytona lock digest with that lockfile.
- Images built with Claude Code older than 2.1.284 need a rebuild before
the CLI path can use Sonnet 5.5.
- The runtime remains at SDK 0.3.286. This PR does not take the later
0.3.287 patch.
- A live Sonnet 5.5 session and a Daytona image build are not part of
the local verification.

## Model Used

- Original work: Anthropic Claude Code, `claude-sonnet-5-5`. Review:
`claude-opus-5-5`. The author reported `xhigh` effort, tool use, and
code execution. The original context window was not reported.
- Merge repair and PR preparation: OpenAI Codex, based on GPT-6, with
tool use and code execution. The runtime does not expose the exact model
identifier or context window 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

## Squash Attribution

Keep these trailers in the squash commit to preserve the original author
and AI attribution:

```text
Co-Authored-By: Claude Code (Ivan) <SkilLab-Tech@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
```

---------

Co-authored-by: Claude Code (Ivan) <ivan@skillab.com.br>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 11:03:20 -07:00
DottaandPaperclip a386a59998 Reduce repeated native completion guidance and preserve final replies (#15151)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents receive task constraints and completion tools from
Paperclip.
> - Completion tools already define the procedure for reporting a
result.
> - Repeated procedure text adds instructions to each full task turn.
> - The final reply must still explain a blocker and link a saved
document.
> - This pull request removes repeated procedure text and keeps these
visible outcome requirements explicit.
> - A document receipt supplies the exact link, and stricter evals check
the persisted reply and browser navigation.

## Linked Issues or Issue Description

Refs: #14961. Related: #14948 and #15007.

**What happened?**

Native task envelopes repeat completion procedure text. A reduced
envelope needs explicit final-reply requirements. The `write_document`
receipt also lacks a canonical document link.

**Expected behavior**

Keep the completion tools as the source of procedure details. Require
one accepted completion result before the final reply. A blocked reply
must explain the reason, owner and unblock action. A document reply must
contain a working link to the saved document.

**Steps to reproduce**

1. Run the native assigned-skill document case and native blocker case.
2. Inspect the run-attributed provider final and its persisted comment.
3. Check the blocker explanation or open the final reply's document
link.

## What Changed

- Remove repeated completion procedure text from the native task
constraints and backend instructions.
- Keep explicit blocker and document-link requirements in full task
turns.
- Return a company/task-scoped `documentHref` from `write_document`.
Preserve the link in the idempotent mutation receipt.
- Repeat canonical links for this run's current saved revisions in
accepted completion feedback. Give blocked providers final-response
guidance for the cause, owner and unblock action.
- Keep internal document/comment anchors when Markdown issue links load
cached issue details.
- Add a manual six-cell comparison suite with strict source, build,
default-instruction and budget admission.
- Capture eighteen shared runnerd RPC projections and six direct
OpenCode HTTP projections across start, resume and continuation phases,
using scripted local transports and no provider execution.
- Apply v3 checks only to the manual instruction comparison; preserve v2
checks for the existing native completion suite. Check the actual
persisted blocker reason and exact saved-document link. Click the
rendered document link and check the original content marker in the
classic document card or the new document tab.
- Forward exact OpenCode finishing calls through the controller. Wait
for acceptance, keep accepted feedback and concrete rejection text, and
reject malformed responses. Preserve ordinary dynamic-tool response
handling.
- Settle the completion decision and tool response before mapping a
racing idle/error/abort event or handling explicit close/interruption.
Reject a concurrent finishing call before controller admission.
- Add a provider-free regression through real runnerd, the OpenCode
proxy and a fake provider. Reject the first completion, accept the
corrected report in the same turn, and propose one result.
- Keep all original verdicts unchanged. Treat replay under new checks as
separate diagnostics.

## Verification

- `pnpm -r typecheck` and `pnpm build` pass locally.
- Native document-authority tests pass, including company/run
authorization and idempotent replay.
- Native runtime-context, backend and measurement tests pass.
- Final-answer calibration, protocol scoring, source-admission and
catalog tests pass. Wrong reasons, absent links and wrong link targets
fail.
- `pnpm test:e2e:runner:typecheck` passes. Discovery lists exactly six
single-attempt local cells with the declared models.
- Exported `prepareNativeInstructionPreflight` then
`verifyNativeInstructionPreflight` pass on this clean committed source.
They build locally and make zero provider calls.
- Corrective live confirmation is incomplete. Source 3a7349d passed both
Claude and both Codex cases. OpenCode saved the correct document but
omitted its final link; its blocker case was canceled before paid
execution. Preserve this failure. The e171282 confirmation was stopped
during build after fresh review found a completion-settlement race; it
executed zero providers. Source c3e0cb303 fixes that race. Two affected
OpenCode cases await fresh review and one bounded confirmation; earlier
results remain attributed to their original source.
- OpenCode proxy parsing, driver, factory and input tests: 81 pass
across retained focused runs, including six settlement races.
Evaluator/scoring/admission checks: 122 pass. The real proxy regression
passes. Fresh local prepare then verify passes with 18 shared and 6
direct scripted captures, fresh SDK/Rust builds and zero providers.
- The full local suite recorded two failures: a webhook timeout and a
Git-scan load count mismatch. Both files pass in isolation with
unchanged assertions/time budgets; preserve the original failure log.
Fresh c3e0cb303 CI and review are pending. This PR remains draft.

## Risks

- Final-answer wording can vary by provider. The checks cover the
declared release-access blocker and saved document fixture, not general
answer quality.
- A single trial does not establish general equivalence, cause, speed,
cost or live resume behavior.
- `documentHref` is an additive receipt field. It points to the current
saved document, not an immutable historical revision. Replaying an older
receipt does not fabricate a new link.
- The correction adds four production paths for document receipts,
accepted completion feedback and UI navigation, plus four OpenCode
controller/proxy paths, beyond the original three instruction paths.
Completion rejection must remain repairable; the production-boundary
regression covers it.
- Preserve the frozen comparison context for live measurement. A
merge-tree check against current master is clean. Do not relabel earlier
live results as results from a later source tree.

## Model Used

- OpenAI Codex, GPT-6 family. The exact serving model ID and context
window are unavailable in this session. Capabilities used: reasoning,
code editing, shell execution, test authoring and evidence review.

## Checklist

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