Commit Graph
1618 Commits
Author SHA1 Message Date
DottaandPaperclip cd690de4d3 fix: recover native instructions from the admitted run checkpoint
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 07:53:14 -06:00
DottaandPaperclip 67714af9ff fix(server): adopt running providers without retired launch assets
Preserve over-quota remote files during cache recovery without weakening save validation. Reuse the retained Runner without materializing launch context from a deleted predecessor home. Record the isolated regression and live qualification evidence.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 07:28:08 -06:00
DottaandPaperclip e14ca5f3e9 fix(server): recover remote agent files on an empty controller
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 07:06:12 -06:00
DottaandPaperclip a18f6b85a3 docs: record hosted enrollment and live runtime qualification
Preserve failed attempts, current verified evidence and remaining acceptance gates.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 06:43:43 -06:00
DottaandPaperclip 8f44c1370b fix(server): check ephemeral runtime after native selection
Fresh runs retain their initial legacy label during workspace preparation. Check remote storage authority there and validate the resolved native warm lifecycle in runtime selection. Reject actual legacy execution before admission.

Reproduced both boundaries before the fix. All 156 focused tests, workspace typecheck and build pass. A real Codex/Daytona fixture completed two native runs; full overlap qualification continues separately.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 06:43:42 -06:00
DottaandPaperclip 247552fe07 test(server): avoid deep traversal in durable file assertions (#18533)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Cloud web servers restore agent files from shared storage after
replacement.
> - The durability test checks restoration, corruption, cancellation and
retry.
> - Its generic equality assertions traverse every byte in many large
buffers.
> - The post-merge check for #18531 exceeded the 15-second test timeout.
> - This change uses native buffer equality and keeps every byte check.

## Linked Issues or Issue Description

Refs #18531.

The post-merge Cloud-source verification run timed out in the new
cold-folder test. Other shards passed. The unchanged test passed
locally. This change removes avoidable assertion cost; it does not
increase test or production timeouts.

## What Changed

- Use `Buffer.equals` for the cold-folder content assertions.
- Keep the concurrency, cancellation, cleanup, old-projection and retry
assertions.
- Record packaged-image proof, the hosted deployment state and the
original CI failure in the existing plan.

## Verification

- Eight durability tests passed against a real local PostgreSQL fixture.
Object storage uses controlled asynchronous streams.
- The same test file took 10.03 seconds before and 5.90 seconds after
this change. The changed cold-folder case took 561 ms after the change.
- The first local attempt could not start embedded PostgreSQL and ran no
tests. The existing external test database enabled the comparison.
- Original failed CI:
https://github.com/paperclipai/paperclip/actions/runs/41296253723 . That
failure remains in the qualification record.
- Server typecheck and build passed. All latest-head PR checks passed,
including the full test, typecheck, build and browser gates. One
cancelled runner job was retried after its log showed an infrastructure
shutdown; the retry passed. This PR changes no production code or
database schema.

## Risks

- A failed content check now reports a boolean mismatch instead of a
large byte diff. Equality still covers buffer length and every byte.
- Local timing is evidence for the fixture, not a general CI performance
guarantee.
- Hosted active-agent and rollout acceptance remain incomplete as
recorded in the plan.

## Model Used

OpenAI Codex, based on GPT-6. The exact runtime snapshot and
context-window size are not exposed. Used code editing, shell execution
and test 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
- [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-11-01 05:13:30 -06:00
DottaandPaperclip 1d348bbef0 fix(server): restore durable agent folders with bounded concurrency (#18531)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A replacement web server restores agent files from shared storage.
> - The old restore reads each object in sequence.
> - Modest network latency makes a 1,024-file folder exceed its
deadline.
> - This pull request uses at most eight concurrent restore streams.
> - Every file must pass its size and hash checks before the folder is
published.

## Linked Issues or Issue Description

Refs #18518 and #18526. Local deployment qualification found that a 64
MiB folder could not be restored after the old server filesystem was
removed.

## What Changed

- Restore at most eight files concurrently within the existing file
authority service.
- Cancel sibling transfers on failure. Await all workers before removing
the temporary folder.
- Keep the existing deadline, file-transfer database pool, authorization
and publication rules.
- Add regression coverage for bounded concurrency, corruption, settled
cancellation, retained previous bytes and retry.
- Document the behavior and update the deployment plan with local
qualification evidence.

## Verification

- Real PostgreSQL and S3-compatible storage: 1,024 files of 64 KiB each,
plus instructions, with 25 ms added to each object GET. Delete the
entire predecessor home and disable local adoption before reading
through the successor.
- Before: the read failed after 30.065 seconds. After: the same case
passed in 4.180 seconds and fetched 1,025 objects. All owned test
resources were cleaned.
- The durable-file suite passed eight tests against PostgreSQL. Server
TypeScript compilation passed. All 56 latest-head CI checks are complete
and green or intentionally skipped, including full typecheck, build,
unit and browser suites. Greptile is 5/5 with no review findings or open
threads.
- The plan separately records a released-container overlap proof: 130
reads, 26 saves, zero failures, two deleted predecessor containers and a
retained authenticated session. That image predates this restore change.

## Risks

- A cold folder can use eight simultaneous streams instead of one. Two
file-transfer database connections bound the simultaneous restore
callers. Streams verify bytes without loading entire objects into
memory.
- The 30-second deadline is unchanged. The measured size and latency do
not qualify every folder at the maximum storage limits.
- No schema, API or UI changes. Paid-model and hosted deployment
acceptance remain separate work.

## Model Used

OpenAI Codex, GPT-6. Tool use, code execution and repository review. 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-11-01 04:09:47 -06:00
DottaandPaperclip d941ed3879 feat(server): verify existing-volume ephemeral enrollment (#18529)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Cloud web servers can now keep durable state in PostgreSQL and S3.
> - Existing servers still have files and a decision signing key on
their volume.
> - The volume must stay attached until every data owner verifies its
migration.
> - This pull request adds a dedicated maintenance process for that
transition.
> - Cloud can preserve the original key and remove the volume only after
a matching receipt.

## Linked Issues or Issue Description

Refs #18518 and #18526. Existing-volume enrollment is a required step in
the zero-downtime web deployment work. This is the Core maintenance
side; the Cloud transition is a separate private change.

## What Changed

- Package a standalone maintenance entry that starts no normal app
routes or execution workers.
- Coordinate the existing agent-file, run-evidence and skill migration
owners. Follow every page and verify shared bytes before final
eligibility.
- Require stopped writers. Refuse active execution, missing local bytes,
local workspaces and external instructions.
- Read the existing decision key without generating a replacement.
Preserve normal key creation for ordinary server startup.
- Require an attempt token for status and export. Export the original
key only after successful migration. Keep status and errors free of
secret material.
- Document the Cloud ownership boundary, deadline, retry and retention
requirements.

## Verification

- Full workspace typecheck and build passed before the review fixes. The
final server TypeScript compilation passed after correcting Drizzle's
optional predicate type.
- Production runtime bundling passed: 2,702 inputs, 122 chunks,
including the maintenance executable.
- The focused suite passed 21 cases using PostgreSQL and real
S3-compatible storage. It covers multi-page migration of 26 agents,
exact reads after deleting the predecessor home, corrupt-object
rejection, active/missing-data refusal, and the bundled plain-Node
process with authenticated export and clean SIGTERM exit.
- Regression cases refuse unsaved terminal working copies, require
explicit stopped/cleaned receipts for unavailable copies, clean 101
expired traces through the owning service, and enforce the deadline
after migration succeeds.
- Initial integration attempts exposed fixture cleanup ordering
problems; corrected runs pass. CI also caught a Drizzle predicate type
error, now fixed and compiled locally.
- All repository CI gates passed on a4db955403, including typecheck,
build, browser suites and serialized tests. Greptile reviewed that head
at 5/5; all four review threads are resolved. Hosted enrollment and
active-agent continuity remain separate acceptance work.

## Risks

- This is an explicit maintenance entry. The caller must confirm all
prior deployments stopped and keep normal tenant routing closed through
detachment.
- A timeout blocks export but an owner may finish its current bounded
operation before observing cancellation. Cloud must confirm process exit
before detaching. SIGTERM has a ten-second hard exit deadline.
- The authenticated export contains the original signing key. The Cloud
caller must put it only in the stack vault and must not log the body.
- Local-workspace and external-instruction migrations remain their
existing owners' responsibility. Enrollment fails closed until those
data are eligible.
- No database schema changes. Ordinary server startup is unchanged
unless this maintenance entry is explicitly launched.

## Model Used

OpenAI Codex, GPT-6. Tool use, code execution and repository review. 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-11-01 03:56:44 -06:00
DottaandPaperclip 73cd8eb9a5 fix(server): deliver answers promptly during web handoff (#18530)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Its web servers can overlap while Railway replaces one deployment.
> - An answer can reach the replacement while the original server owns
the native execution.
> - A competing delivery claim can make the owner miss the first
notification.
> - The normal retry interval then delays the answer by 30 seconds.
> - This pull request gives pending answers a one-second retry in
ephemeral mode and verifies delivery between separate processes.

## Linked Issues or Issue Description

Refs #18518 and #18526. This closes a measured native-question delivery
delay during control-plane web deployment overlap.

## What Changed

- Register question delivery through its owning service. Use a
one-second retry for ephemeral servers and retain the configured cadence
for ordinary servers.
- Keep the existing durable claims, response identity, authorization and
continuation behavior.
- Add a two-process PostgreSQL regression for a claim held by the
non-owning server. Verify one command, settlement, idle behavior and
reactivation by another committed answer.
- Keep the assembled startup fixture on the real registration function.
Update the deployment plan with current evidence and remaining
acceptance work.

## Verification

- The same local two-process race took 30.157 seconds before the fix and
1.197 seconds after it. The command sink is simulated; PostgreSQL,
notification transport, interaction response, delivery claim and worker
are real.
- The cross-process regression and assembled startup suite passed 122
tests. No further sweeps or pending inspections occur after settlement.
A second answer wakes the owner through PostgreSQL without a test-owned
sweep.
- Server TypeScript compilation passed. All PR CI gates passed on
d1d426c0dc, including full tests, typecheck, build, browser shards and
serialized suites. Greptile reviewed that head at 5/5 with no findings.
- Live provider continuation, hosted staging deployments and production
acceptance are still separate work.

## Risks

- An unresolved answer causes more frequent reconciliation in ephemeral
mode. Settled history does not keep the worker active. Existing claim
fencing and bounded error attempts are unchanged.
- A 30-second abandoned claim still needs its existing stale-claim
recovery. This change addresses released claims, not proof of provider
liveness.
- The test simulates the provider command sink. It cannot establish that
a paid model consumed the answer or that a remote execution survived a
deploy.
- No schema, API or UI changes.

## Model Used

OpenAI Codex, GPT-6. Tool use, code execution and repository review. 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-11-01 03:39:48 -06:00
DottaandPaperclip 16787e4167 Qualify rolling web deployments and preserve Stop through handoff (#18526)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The web server owns request handling and remote execution
coordination.
> - Deployment must start a ready replacement while the old server still
serves.
> - An outage test does not prove that two live servers can overlap
safely.
> - This pull request adds a separate Product E2E cell for that
boundary.
> - The existing run, file, recovery, and retained-session checks still
apply.

## Linked Issues or Issue Description

Refs #18518. The runtime prerequisite is merged; this PR qualifies its
ephemeral server and deployment contracts.

## What Changed

- Add the explicit `rolling-web-deployment` Codex Daytona workflow.
- Start independent A/B/C homes and compiled builds behind a test
ingress.
- Wait for readiness before routing, then drain and delete the old home.
- Observe active authority before handoff and use the existing read-only
recovery oracle.
- Require ordinary reads and saves to succeed throughout replacement.
Read back every accepted save exactly once.
- Preserve the five-minute outage suites and their existing validators.
- Add a model-free supervisor smoke and an unready replacement control.
- Require graceful exit before deleting an old home; forced cleanup
cannot satisfy the oracle.
- Preserve a durable Stop through lease release/expiry until the
recovered execution owner acknowledges it. Permit only fenced
reattachment of the original execution for Stop cleanup; submit no new
turn.
- Exclude events saved by A during shutdown from evidence of B making
progress.

## Verification

- E2E TypeScript check passed.
- Affected harness checks: 143 passed. Catalog, fixture and report
checks: 120 passed.
- Actual supervisor smoke passed two replacements: 436 reads, 45 saves,
zero request failures, and confirmed owned resource cleanup.
- B became ready in 18.7 seconds; C became ready in 109.2 seconds. A
prior C timeout remains failed evidence.
- Fresh browser proof: 11 checks passed, 246 reads, 50 acknowledged
saves, zero failures, 1,058ms reconnect, both old homes deleted and
cleanup confirmed.
- Stop lease-gap regression: three PostgreSQL delivery tests passed with
a simulated provider edge. Current server TypeScript build/vendoring
passed.
- Full harness: 5,814 passed, 17 failed, four skipped. Two shutdown
races passed the focused file; two report timeouts passed an isolated
42-test rerun. Onboarding/workflow-security/Pi/date-expired fixtures are
unchanged on inspected master; the host embedded PostgreSQL fixture
remains a setup limitation. This is not a green full local suite.
- CI at `172509b8be` passed all gates. Greptile is 5/5 with every review
thread resolved. The earlier access-service race failure passed its
isolated regression and the subsequent full CI.
- Final review corrections: six focused executor cases, three PostgreSQL
command-delivery cases, 19 harness cases and server/E2E typechecks
passed.
- Three live attempts failed before agent creation: two harness setup
gaps were fixed, then provider authentication failed. The saved OpenAI
key returns 401; a refresh is pending. The Daytona probe reported
cleanup uncertain, and no sandbox with that attempt label was found
through the authenticated staging manager. No live model execution is
claimed.
- Live Runner overlap, released-container qualification and hosted
deployment proof remain pending. Merging this opt-in qualification lane
does not claim those results.

## Risks

- The source lane shares workspace dependencies and does not establish
container packaging correctness.
- The live workflow needs an explicitly owned S3 bucket, PostgreSQL,
pinned remote image and provider credentials.
- Qualification cleanup stops all owned processes after failure. A
failed replacement must not be reported as a pass.

## Model Used

OpenAI Codex, GPT-6. Tool use, code execution and repository review. 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-11-01 02:53:27 -06:00
DottaandPaperclip 2b2b5a43b7 fix(daytona): restore the recorded directory for file recovery (#18527)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A stopped sandbox can hold workspace files that still need a durable
copy.
> - File recovery must reopen the exact allocation and directory
recorded by the run.
> - Workspace preparation can place that directory below the allocation
root.
> - Daytona resume returned the allocation root even when recovery
needed the recorded child directory.
> - This pull request lets the file-recovery owner request that exact
directory.
> - Ordinary resume keeps its allocation-root behavior. The recovery
source checks stay strict.

## Linked Issues or Issue Description

**What happened?**

A stopped native run had a prepared remote workspace. The recovery
service stopped and retained its allocation. The next file-recovery step
failed with `source_binding_invalid` and `reopened_cwd_mismatch`.
Daytona resumed the correct allocation and matched its sentinel, but
returned the allocation root instead of the workspace directory recorded
on the lease.

**Expected behavior**

The file-recovery owner must reopen its exact recorded directory without
creating an allocation, an empty directory, or an agent turn. Ordinary
execution resume must keep returning the allocation root for normal
workspace preparation.

**Steps to reproduce**

1. Prepare a task workspace below a Daytona allocation root.
2. Stop and retain the allocation with unsaved workspace files.
3. Request source-bound file recovery.
4. Before this change, the provider returns the allocation root and the
strict cwd check rejects it.

**Paperclip version or commit**

Reproduced from `050365e09d88411960fc3bacc1c08c46c0d9b6fa`.

**Deployment mode**

Docker with the bundled Daytona provider. Local tests use synthetic
provider boundaries and disposable PostgreSQL.

Refs: #18517, #15749. Related retained-export work: #17916. That work
does not change the Daytona resume handler.

## What Changed

- Add an optional driver-only `requestedCwd` resume field to the SDK
contract and existing host forwarders.
- Set the field only after the owned file-recovery path verifies the
recorded source.
- Require Daytona to match the requested directory to the recorded lease
directory. Require a normalized absolute path without NUL bytes. Keep
the allocation and sentinel checks.
- Keep ordinary resume unchanged when the field is absent.
- Add provider, host, and real workspace-preparation regressions.
Document the separate directory contracts.

## Verification

- The original provider regression failed for reusable and ephemeral
leases. The scoped regression also failed to read a real retained file
from the wrong root. Ordinary resume controls passed before the fix.
- Current provider handler: **345/345 passed**. This includes
exact-directory, malformed, missing, foreign, sentinel, reusable,
ephemeral, ordinary-root, and real-file cases.
- Removing only the owned producer's cwd request makes its real
PostgreSQL regression fail with the original `reopened_cwd_mismatch`;
the source file was restored exactly afterward.
- Current host selection: **10/10 passed** against disposable PostgreSQL
17. It covers the inspected owner, sandbox forwarding, generic plugin
forwarding, normal resume without the field, same and later task
workspace preparation, and ownership rejection. The same-workspace
control retains saved bytes and does not append another workspace path.
- Current SDK and Daytona builds, server build, module boundaries, maps,
and diff checks passed. The server used its normal unchanged-Runner
cache. Its canonical input digest matched the previously verified build,
and the canonical assessor accepted the copied original stamp and
outputs. The changed SDK and server compiled from current source.
- Local package-wide validation exposed two unchanged 30-second timeouts
in the 145,000-member tar-listing cases. A single-file control
reproduced both timeouts. That test mocks this provider module. The
failures remain recorded; no timeout changed. The earlier package run
had 497 passes, two failures, and seven skips. It is historical evidence
from the abandoned broader resume experiment, not final-source package
acceptance.
- Initial host attempts timed out during database setup before any
assertion. The final host selection used the existing supported
pre-migrated disposable template. No test timeout changed.
- Greptile reviewed exact head
`8d0e577d1234ad394887255f13707c010dee6d24`: **5/5, no actionable issues,
zero review threads**. [Current
review](https://github.com/paperclipai/paperclip/pull/18527#issuecomment-6555253315).
- The official [Ponytail
review](https://github.com/paperclipai/paperclip/pull/18527#issuecomment-6555237850)
also assessed exact head `8d0e577d1234ad394887255f13707c010dee6d24`:
**5/5, no findings**. Its check is terminal neutral; its completed
source assessment is not a test-execution claim.
- [Primary
CI](https://github.com/paperclipai/paperclip/actions/runs/41286802674)
initially lost its spot runner in the UI/CLI workspace lane. The log
records an explicit shutdown signal and no test assertion result. UI,
CLI, lane scripts and dependencies are unchanged; the adjacent
identical-source baseline lane passed. The single failed-lane retry
passed at the same source. The initial failure is retained. All
exact-head CI gates are now green.
- No live repair or image deployment is claimed by this PR.

Commands:

```sh
node packages/plugins/sandbox-providers/daytona/node_modules/vitest/vitest.mjs run --config packages/plugins/sandbox-providers/daytona/vitest.config.ts packages/plugins/sandbox-providers/daytona/src/plugin.test.ts
node node_modules/vitest/vitest.mjs run --project @paperclipai/server server/src/services/workspace-recovery.test.ts server/src/__tests__/environment-runtime.test.ts -t 'recovers a protected retained source|owned export directory|prepares the (same|later) task workspace|does not reopen a retained source|resumes only the exact stopped sandbox lifecycle|explicit export directory'
pnpm -C packages/plugins/sandbox-providers/daytona build
pnpm --filter @paperclipai/server build
node scripts/check-module-boundaries.mjs
node scripts/check-maps.mjs
git diff --check
```

## Risks

- A provider that does not support the optional field can still return a
different directory. Recovery keeps failing closed on that mismatch.
- Ordinary resumes omit the field. The tests cover the same workspace
and a later task so that normal preparation does not gain an extra path
prefix.
- The field grants no source ownership, stop proof, file-persistence
proof, or execution authority. Existing allocation, company, task, run,
claim, and cwd checks remain in force.
- No schema migration, retry-policy change, model replay, or
historical-row repair is included. Existing failed attempts remain
historical facts. Deployed file recovery still needs its normal
admission and independent persistence and physical-stop receipts.

## Model Used

- OpenAI GPT-6 through Codex. Used reasoning, source inspection, tool
use, and code execution. The exact serving model identifier and context
window are not exposed in this session.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 02:47:30 -06:00
DottaandPaperclip 006d5691a6 feat(server): support volume-free web server handoff (#18518)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Its web server also owns controller admission and user commands.
> - A rolling deployment starts a replacement before the old server
exits.
> - Shared database state alone does not preserve local agent files,
browser chunks, or in-process commands.
> - This pull request adds an opt-in ephemeral server contract and a
local overlap test.
> - The benefit is a web server that can relinquish traffic and local
files without losing acknowledged work.

## Linked Issues or Issue Description

Refs #18403, #18327, #18335, #18341.

**Current behavior**

The control-plane web server still has local agent-file authority and
local command targets. A new container can miss saved bytes or send a
command to the wrong process. An existing browser tab also needs chunks
from its original build.

**Proposed behavior**

Eligible servers share only PostgreSQL, object storage and stable
secrets. A replacement waits for readiness. The old server drains
admitted requests, keeps owner commands available through handoff, and
releases controller leases. Explicit maintenance adopts existing files
before the volume is removed.

**Reason and benefit**

This is the application prerequisite for rolling app-only deployments.
Schema migrations and permanent multi-replica operation are outside this
change.

## What Changed

- Store agent-file manifests in PostgreSQL and immutable bytes in S3.
Treat local roots as disposable projections. Preserve existing
permission checks and edit conflicts.
- Add an explicit migration, eligibility and object-retention command to
the production runtime bundle.
- Add `/api/ready`, admitted-request drain, browser restart signaling
and retained immutable UI chunks.
- Carry transaction-aware work hints across controllers during handoff
and active execution. Keep listeners closed when idle.
- Deliver durable Stop and runtime responses to the execution owner.
Recheck request lifecycle and access before response dispatch.
- Reject local-only configuration in ephemeral mode. Keep the feature
disabled for existing installations by default.
- Add an isolated PostgreSQL/S3/proxy/browser deployment harness with
independent server homes and retained failure evidence.

## Verification

- All CI checks pass on `ce17b95019d3cf1cabd357d19b6d37f96782cc5c`:
workspace typecheck, build, Runner checks, server/general tests and
browser shards. Greptile reviewed the runtime changes at 5/5 with all
findings resolved; the final commit updates maps and the plan.
- Local targeted checks passed: coordinator 27; Stop/recovery 33;
PostgreSQL command delivery 6; route/workspace regressions 8; bootstrap
Stop 1; restart recovery 75. PostgreSQL command tests simulate the
provider edge.
- Local browser proof passed 91 reads and 19 saves; reconnect took
1,013ms. The tab opened Audit from S3 after deletion of A's whole
home/build. This uses compiled workspace code and local-trusted auth,
not released containers or live agents.
- Local workspace typecheck/build passed; current server and runtime
bundle passed. The earlier broad local suite was stopped after three
hours and is not a passing receipt. Its retained failures and isolated
reruns are documented in the plan.
- Stacked #18526 adds stricter graceful-exit proof, an unready
replacement control, live Runner qualification and a Stop handoff
correction. Hosted enablement remains gated on those results and Cloud
#1096. No hosted stack has been enabled.

## Risks

- Apply migration 0422 before enabling the feature. Existing data must
pass each owner's migration and eligibility checks. Do not discard a
volume based on a single migration page.
- Durable manifests remain authoritative after the opt-in is disabled.
Rolling back to a binary that ignores them is unsupported.
- Cold directory restoration and complete shutdown timing still need
qualification before enabling a hosted stack.
- Retained UI assets must cover the supported browser and rollback
window. Cleanup is explicit; no new idle maintenance polling is
introduced.
- This change does not claim production zero downtime or authorize a
fleet-wide enablement.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 01:58:54 -06:00
DottaandPaperclip 050365e09d Preserve native workspace files after lifecycle Stop (#18517)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent termination must stop execution and preserve unfinished
workspace files.
> - A native run can acknowledge a lifecycle Stop, then finish without
an accepted result.
> - The file preservation worker required a board actor even when the
exact native Stop receipt was valid.
> - This left a prepared remote workspace allocated without a file
recovery action.
> - This pull request admits the exact audited receipt for file
preservation only.
> - The existing recovery service can then save the files and stop the
same allocation without another agent turn.

## Linked Issues or Issue Description

**What happened?**

A cancelled native run can have a terminal, unowned coordinator and a
prepared remote workspace. Agent lifecycle cancellation records a valid
run-only Stop receipt without a board user. The preservation worker
rejects that receipt because it uses the board Stop predicate. The
source lease remains active. A resolved execution watchdog does not
supply the missing file recovery action.

**Steps to reproduce**

Seed a cancelled native run with a terminal-failure coordinator, no
result or owner, an acknowledged and audited run-only Stop, and a
prepared remote workspace. Omit board attribution. Start the registered
cancellation preservation worker. Before this change, it records no
workspace recovery marker.

**Expected behavior**

Record file recovery for the exact bound allocation. Keep the cancelled
result, accounting, task state and watchdog history. Use the normal
recovery service to stop, save and clean up that allocation without
another provider turn.

**Paperclip version or commit**

Reproduced on source `1e8e32290c657227857aeda2620a73db52bab4f2` with
real local PostgreSQL 17. The observed deployment uses a sandbox
provider and remote workspace storage. Related current workspace work:
#18514. Public PR and issue searches found no duplicate repair.

## What Changed

- Expose the existing exact run-only Stop receipt check. Reject empty
audit identifiers.
- Use that receipt only in cancelled workspace preservation. Keep board
Stop and continuation checks unchanged.
- Defer preservation while the run still holds a live controller lease.
- Schedule that wait at the actual controller lease expiry. A lease
renewal observed under the preservation lock also sets the next
deadline.
- Add a PostgreSQL regression for the remote-workspace-only lifecycle
record, resolved watchdog history, normal recovery admission, ownership
controls, rollback and idle behavior.
- Document the separate file recovery obligation and its physical
cleanup limits.

## Verification

- Before the fix: the registered-worker PostgreSQL regression fails
because the file recovery marker is absent.
- After the original repair at `6fd1042efd`: 20/20 focused tests and all
five sibling suites pass, 320/320 tests. The exact-head server build and
typecheck pass.
- The repository reviewer then found that a live controller caused a
fixed 30-second retry. Both the existing-lease and real row-lock renewal
cases fail against that source. The new
`adb1d4eccdd48be4c86906d5bd111a6e39f20191` schedules the actual recorded
deadline before locking and after the locked reread. The lock still
enforces the ownership guard.
- At `adb1d4eccd`: all 22 focused PostgreSQL controls pass. The directly
affected retention and board receipt sibling suites also pass, 124/124
tests across three files. They prove no intermediate reads or
transactions before expiry, preservation after expiry, and no extra
execution. Server typecheck and the exact-head server build pass.
- Map checks, module boundary checks and `git diff --check` pass.
- Run `pnpm exec vitest run
server/src/services/native-runtime/native-cancelled-workspace-preservation.test.ts
server/src/services/native-runtime/native-failed-workspace-recovery.test.ts
server/src/services/acknowledged-native-stop.test.ts` with the supported
external test-database variable set to a disposable local PostgreSQL
database. The earlier broader run also covered run control and workspace
recovery.
- Exact-head [canonical
CI](https://github.com/paperclipai/paperclip/actions/runs/41274963476)
completed successfully. All 59 current-head checks are terminal with
zero failures; required `ci / verify` and `ci / e2e` pass. Both
[Greptile](https://github.com/paperclipai/paperclip/pull/18517#issuecomment-6553528545)
and the [repository
assessment](https://github.com/paperclipai/paperclip/pull/18517#issuecomment-6553542139)
reviewed exact `adb1d4eccd` at 5/5, with zero findings or unresolved
threads. The repository assessment's check concludes `NEUTRAL`; the
validated assessment itself is 5/5. Earlier reviews, including the valid
4/5 deadline finding at `6fd1042efd`, remain in review history. The
[earlier CI
run](https://github.com/paperclipai/paperclip/actions/runs/41273965963)
is also retained. No old result substitutes for a current-head gate.
- Real sandbox recovery and physical cleanup remain unverified. Earlier
failed QA outcomes remain failed. This PR changes no test grade or
historical row.
- Repo-wide local tests and typecheck were not run. The focused server
checks cover this change; canonical CI supplies the remaining repository
gates.

## Risks

- The newly admitted receipt permits only file preservation. It cannot
authorize a continuation, accept a native result or certify provider
termination.
- Recovery still requires exact company, task, run, lease, allocation
and workspace bindings. Accepted results and live owners remain with
their existing owners.
- Provider or storage failure can leave recovery pending. The source
must remain retained until saved-file and physical termination receipts
exist.

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

## Model Used

- OpenAI GPT-6 through Codex. Used reasoning, source inspection, tool
use and code execution. The exact serving model identifier and context
window are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 00:17:46 -05:00
DottaandPaperclip 1e8e32290c Give metadata project tasks private remote workspaces (#18514)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A task can belong to a project without using that project's files.
> - The specification gives a task without a selected or configured
source its own private folder.
> - The remote source planner instead rejects such a task when its
project has no configured workspace.
> - This stops an ordinary delegated task before native execution
starts.
> - This pull request selects an empty, task-owned remote source for
that narrow default case.
> - Explicit source choices, existing workspace authority, and
repository requirements retain their current checks.

## Linked Issues or Issue Description

Refs #18504 and #18351. The earlier reference-project fix covered
additional project mentions. This fix covers the task's own
organizational project.

**What happened?**

A task in a project with no configured workspace fails with
`remote_workspace_source_unavailable`. Its project has no workspace
policy, its four workspace selection and binding fields are null, and it
requests no repository, branch, or local folder. The failure occurs
before native runtime selection. A derived project folder exists in the
project facade even when no source is configured; that derived path does
not grant file access.

**Expected behavior**

Use the task's private remote workspace. Keep the project on the task
for organization. Do not adopt the project folder, agent home, or
another repository. Preserve explicit workspace and source requirements.

**Steps to reproduce**

1. Create a project without configured workspaces or a workspace policy.
2. Assign a normal task in that project to a native sandbox agent. Leave
all workspace selections and bindings unset.
3. Start the task with remote workspace storage enabled.
4. On the prior source, observe the source-unavailable error before
allocation. On this source, observe a company-owned remote workspace
whose `sourceIssueId` is the task and whose filesystem project and
source IDs are null.

**Paperclip version or commit**

Reproduced against the deployed source planner at
`756599e4ea069c9338c320fe8846523d3dfb92a0`. This branch starts at
`987e0932bf66e703750cd04698b3c7e8993580a7`; the relevant planner and
preparation inputs at that parent match the deployed source.

**Deployment mode**

Native sandbox execution with remote workspace storage. The regression
tests use real PostgreSQL with the current migrations.

## What Changed

- Allow an implicit empty source only after a company-scoped query
confirms the project has no workspace rows and no explicit workspace
policy.
- Keep existing bindings, pending selections, explicit source choices,
Git requirements, and local folder choices outside this default.
- Add real PostgreSQL source controls and an assembled heartbeat
preparation control through workspace reservation and the environment
acquisition boundary.
- Clarify the existing task-owned folder contract in the implementation
specification.

## Verification

- Causal RED: the new source control and the assembled allocation
control both fail against the unchanged deployed planner with the
observed source-unavailable error.
- GREEN: 19 focused PostgreSQL controls pass across the source planner
and assembled heartbeat preparation suites. The allocation control
checks the persisted company/task owner, null filesystem project IDs,
private remote root, original organizational project, and unchanged
project and host sentinel files.
- Negative controls retain configured repository sources and reject a
configured source without a URL, an explicit missing source, an unknown
selection, a required project policy, a required branch, an explicit
local folder, a foreign project, and unsupported read-only project
sources.
- Current-source transitive TypeScript checks and `node
scripts/check-maps.mjs` pass. The map check is structural evidence only.
- Fresh exact-head Greptile is 5/5 with zero unresolved threads at
`680461e180232d0f4a057528617e39b64b4f0e3a`.
[Review](https://github.com/paperclipai/paperclip/pull/18514#issuecomment-6552946468).
The official [Paperclip
assessment](https://github.com/paperclipai/paperclip/pull/18514#issuecomment-6552931726)
is 4/5 and remains recorded unchanged. A separate non-author source
review found no actionable issue after the full producer/consumer trace,
with manual confidence 4/5. Neither static review ran the tests or
proved deployed native execution.
- Full repository tests, build, and type checks passed in [canonical
CI](https://github.com/paperclipai/paperclip/actions/runs/41269733360).
All 59 checks are terminal: 55 success, three skipped, and the official
Paperclip check neutral; no failed or pending checks. The successful
build checked out merge preview
`03dce9f9bc708e778dd214ca85dfa1ba58e0a806`, with parents current main
`9dbbfa4fb298448db83ace946b338bff321d8b2a` and this exact head. Its four
helper blobs match this head; the four added mainline document-harness
paths remain unchanged. Local tests use source aliases with the current
DB, shared, and Runner source, rather than borrowed generated
declarations.
- Actual QA staging qualification is pending deployment. The previous
failed journey and cleanup evidence remain failed; these local checks do
not relabel them.

### Review follow-up

- Fresh workspace retry: the normal producer sets `taskDirectory:true`
for this empty-source case.
[Heartbeat](https://github.com/paperclipai/paperclip/blob/680461e180232d0f4a057528617e39b64b4f0e3a/server/src/services/heartbeat.ts#L2288-L2296)
separates the saved filesystem project from the organizational project.
[Environment
selection](https://github.com/paperclipai/paperclip/blob/680461e180232d0f4a057528617e39b64b4f0e3a/server/src/services/heartbeat/environment-selection.ts#L506)
selects the fresh task directory. Preparation passes that flag, and the
planner's existing task-directory return runs before the new binding
guard. The proposed fresh failure omits that producer flag. The existing
fresh-intent and binding checks stay strict. This is source evidence,
not an extra runtime test claim.
- Empty policy object: the [public project policy
schema](https://github.com/paperclipai/paperclip/blob/680461e180232d0f4a057528617e39b64b4f0e3a/packages/shared/src/validators/project.ts#L24-L43)
requires `enabled:boolean`. The project PATCH schema makes outer fields
optional and does not make nested policy fields optional. A clear uses
`null`; `{}` is rejected. A defensive parser's treatment of unknown
stored data does not establish a valid `{}` producer. Keep the narrow
fallback closed for non-null policies.
- Boolean grouping: JavaScript evaluates the existing predicate as
`sourceId || (projectId && !implicitTaskDirectory)`. The explicit-source
and metadata-default controls cover those branches. The optional
parentheses suggestion does not identify a behavior change; this
reviewed source remains frozen.
- The official 4/5 assessment and its static verification limits remain
visible. The independent manual review withdrew its initial fresh-retry
concern after the full producer trace. Actual staging qualification
still requires deployment and a new real journey result.

## Risks

- The new query runs only for a source-less default admission. It reads
one authorized project and uses `NOT EXISTS` for that project's source
rows. It adds no recurring poll, write, provider call, or local folder
access.
- A project with an explicit workspace policy remains subject to the
prior source requirement. This conservative rule does not reinterpret
policy fields.
- The allocation control uses the real planner and PostgreSQL
reservation. It stops at environment acquisition, so it proves workspace
ownership rather than provider filesystem execution. Live staging
qualification is still required.
- No API, database schema, permission, model, budget, run limit, or QA
journey oracle changes are included.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. This session does not expose a more precise backend model ID
or context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 23:09:30 -05:00
34f8d25089 fix(github): expose review finding categories (#18429)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - GitHub review bots submit structured assessments through task-bound
tools.
> - Each repository can set its own finding categories.
> - The schema accepts a string, but the server rejects values outside
the saved review policy.
> - Review instructions did not list the accepted values. The error did
not list them either.
> - This change gives agents the values before submission and keeps
server validation.

## Linked Issues or Issue Description

**What happened?**
Review submissions failed with an unknown finding category. The agent
corrected the assessment before publication. The sampled trace has two
rejections followed by a processed review. Historical tool inputs are
null. Authorized diagnostic inspection found no saved raw provider trace
for the representative run. The exact rejected values remain unknown.

**Expected behavior**
Agents can find the accepted categories before submission. Unknown
values still fail validation.

**Steps to reproduce**
Set a custom finding category. Start a review. Submit a different
category. Before this change, the instructions and error do not list the
accepted value.

## What Changed

- List configured categories in manual and automatic review
instructions.
- Return categories from the saved assessment policy in `begin_review`.
- Describe the dynamic constraint in the shared discovery schema. Keep
custom categories valid.
- List accepted values in category errors. Keep authorization and
publication checks.
- Add contract and database integration tests. Update documentation and
access maps.

### Hypothesis and thesis for a fix

The missing category guidance can cause avoidable submission retries. A
model can also ignore the policy returned by metadata reads; the
historical inputs do not establish which occurred. The repair belongs to
the GitHub review contract. Use the saved policy categories at review
start, explain the constraint, and retain server rejection. A fixed
global enum would reject valid custom categories.

## Verification

- Baseline `f1d7808`: two new contract assertions failed for missing
category guidance and error detail. The same assertions pass after the
change.
- `pnpm exec vitest run
server/src/services/chat-github-review-policy.test.ts
server/src/services/chat-github-tools.test.ts`: 41 passed.
- `pnpm exec vitest run
server/src/__tests__/chat-channels.integration.test.ts -t 'returns
snapshot finding categories'`: 1 passed. Real PostgreSQL and service
code; simulated GitHub HTTP. Checks policy changes, rejection before
publication, accepted custom category persistence, and processed
publication.
- `node scripts/check-maps.mjs`: passed. Structural evidence only.
- Shared TypeScript check passed. Server TypeScript checking was killed
by the 8 GiB memory limit, including a separate retry after the other
checks stopped.
- Full typecheck and build could not complete: `cargo` is absent. Full
tests were stopped after concurrent checks exhausted memory. CI must
supply the full checks.
- Follow-up compiler repair: the unchanged baseline reproduces TS2352 in
the category discovery test. Runtime matchers replace the unsafe schema
cast. They retain both guidance and custom-category assertions. The
repair is commit `0dcb94c676`, with current master merged at
`14d7052854`. The final head is
`c46b8f35add9255fc71be294d27f5a7865bcb47f`; the remaining code-comment
review finding was removed and resolved.
- Final-head CI: all gates pass, with no failed or pending checks.
Greptile gives this head 5/5 with no outstanding findings; the only
inline thread is resolved. The workspace test shard passed on one
bounded rerun after an earlier CLI child-server readiness timeout; no
code change was made for that rerun.
- The review host passed full recursive typecheck and build after the
compiler repair and master integration. Fresh database rechecks hit the
host PostgreSQL semaphore limit. The full local test command hit a
pre-existing chat line-selection failure before assertions. These local
limits do not replace the passing final-head CI evidence.
- No live model or GitHub publication at the changed revision. No
deployment or merge.

## Risks

- Instructions add policy text. An agent can still ignore it.
- Existing bot catalogs get the schema description when tools are
synchronized. Trusted review instructions and `begin_review` also expose
categories.
- The service test uses simulated GitHub HTTP. It does not prove that
deployed agents avoid retries.

## Model Used

The original worker used OpenAI `gpt-6.1-sol` through Codex with
reasoning, tool use, and code execution. A later Codex review repaired
the test compiler error. That review runtime exposes GPT-6 but no exact
snapshot or context-window size.

## Checklist

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

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Dotta <bippadotta@protonmail.com>
Co-authored-by: cryppadotta <34892728+cryppadotta@users.noreply.github.com>
2026-10-31 22:06:32 -05:00
DottaandPaperclip e09f40888a fix(recovery): preserve native task access during resolution (#18489)
## Thinking Path

> - Paperclip controls agent execution and task ownership.
> - A native run needs its task binding until it reports its result.
> - Direct task updates already reject self-status changes that remove
this binding.
> - Recovery resolution can also change the source task status.
> - That route did not use the same protection.
> - This change rejects the unsafe status change before the task or
recovery receipt changes.
> - The run can then use semantic completion while normal recovery
permissions remain effective.

## Linked Issues or Issue Description

Refs #18411.

**What happened?**

A running native owner can resolve an older recovery action with
`sourceIssueStatus: "in_review"` or `"done"`. The request succeeds and
changes its own task status. That can release the execution binding
before the run reports. Later task tools fail with
`paperclip_runner_tool_binding_not_authorized`.

**Expected behavior**

Return a conflict before the task status or action receipt changes. Tell
the run to report through `paperclip_finish` or `paperclip_block`.
Preserve unchanged-status resolution, Board recovery, legacy-agent
behavior, and the existing conversation and handoff rules.

**Steps to reproduce**

1. Give a running native owner the task execution lock and an older
recovery action.
2. Call `POST /api/issues/{id}/recovery-actions/resolve` as that run.
Use `outcome: "restored"` and `sourceIssueStatus: "in_review"`.
3. Before this fix, the route returns 200 and changes the status. After
this fix, it returns 409 with `native_run_status_reported_by_finish` and
makes no task or action mutation.

## What Changed

- Reuse the existing native self-status guard inside recovery
resolution's source-task transaction.
- Let the guard receive the requested status from either route contract.
- Add HTTP route regressions for rejected review/completion transitions
and continued task editing after rejection.
- Cover unchanged-status native resolution, Board recovery and
legacy-agent resolution.
- Update execution semantics and both recovery maps.

## Verification

- Baseline `91fdf02`: the two new rejection cases fail because the real
Express route returns 200. Three safety cases pass.
- Fixed source: all 198 tests in
`server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts`
pass.
- `node scripts/check-maps.mjs` passes. This is structural evidence.
- Greptile and Paperclip Review both give the integrated head 5/5 with
no actionable findings.
- Full recursive typecheck, full build, and a repeat of all 198 route
tests pass at integrated head
`0fa104dfb240500acd01303cd446363ea39c6c75`. All current-head CI gates
pass (55 successful checks/statuses; no failed or pending checks).
- The full local `pnpm test:run` command fails in chat-test line
selection with `No test found`, before assertions. This also occurs with
the unchanged master chat test file. It is not a passing full local
suite.
- The route tests use the real route, validation and guard. They mock
service and database boundaries. The observed hosted failure establishes
the original mechanism. Fixed-source live provider acceptance remains
unverified. No deployment or merge is part of this PR.

## Risks

- A native owner now receives a conflict for a previously accepted
recovery status change. It must use the existing semantic result path.
- This prevents a new binding loss. It does not prove that an old remote
executor stopped or recover missing provider state.
- Board, legacy, conversation and handoff behavior retains existing
authority. The regression includes representative allowed paths.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools and code
execution. The runtime does not expose a more specific snapshot 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 (198 focused route cases;
the full local command has the recorded selection failure)
- [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-31 22:06:08 -05:00
DottaandPaperclip 756599e4ea fix(workspaces): keep project references without source folders (#18504)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents can receive project references in normal task and chat
messages.
> - Remote workspace preparation checks those references before a native
run starts.
> - A project with no workspace source has no folder to attach.
> - The current check rejects that project as an unsupported read-only
folder.
> - This pull request keeps the project reference and reports the
missing source without attaching files.
> - Projects with configured sources keep the current remote access
restrictions.

## Linked Issues or Issue Description

Refs #18403 and #18351. This is a product prerequisite for the hiring
journey. It changes no journey code.

**What happened?**

A native chat run failed before execution when its message referenced an
authorized project with zero configured workspaces. The error was
`workspace_validation_failed`: “This remote runtime cannot safely
provide read-only project folders.” The project had no repository or
checkout. The failed QA run and original grade remain preserved.

**Expected behavior**

Keep the task workspace when a referenced project has no configured
source. Report that no project folder was attached. Continue to reject
configured cross-project sources that require an unsupported read-only
mount.

**Steps to reproduce**

1. Use a native remote task folder with multi-project references
enabled.
2. Mention a same-company project that has no configured workspaces in a
normal comment.
3. Prepare the run workspace.

**Paperclip version or commit**

Reproduced on `b889ac39b7fbed558c5f4cfbbc2b73c4ca916810` with the real
workspace resolver and PostgreSQL migrations. The staging failure was
recorded in workflow
[41253428446](https://github.com/paperclipai/paperclip-cloud/actions/runs/41253428446).

## What Changed

- Distinguish authorized project references with a known empty workspace
list from configured sources.
- Return a resolution warning and failure receipt for an absent source.
Do not attach a folder or create a workspace.
- Preserve project authorization, company filtering, the disabled
remote-source gate, and the read-only restriction for configured
sources.
- Add real PostgreSQL regression cases and document the reference
contract.

## Verification

- Causal RED on unchanged `b889`: the metadata-only project case failed
with the same read-only error. The real repository negative already
passed.
- GREEN: eight PostgreSQL cases pass. They cover an absent source with
the remote-source switch both on and off, a saved existing workspace, a
repository, a configured source without a repository URL, the disabled
remote gate, mixed references, and a foreign company.
- The existing assembled workspace test also passes: a real read-only
project source is rejected before reservation or environment
acquisition. Total: 9 selected tests pass; 119 unrelated tests were not
selected.
- Tests use PostgreSQL 17 and the current source migrations. The local
Vitest configuration selects current DB, shared, and Runner sources
because the borrowed dependency output predates the remote workspace
feature.
- Current-source TypeScript checking of both changed TypeScript files
and their dependency graph passes. It uses the repository's real Express
actor declaration.
- `node scripts/check-maps.mjs` and `git diff --check` pass.
- Canonical reproduction: `pnpm exec vitest run --project server
server/src/services/heartbeat/remote-workspace-source.test.ts` with the
existing embedded PostgreSQL support or
`PAPERCLIP_TEST_POSTGRES_ADMIN_URL` set to a disposable test cluster.
- Historical `0f2b` passed all 59 CI checks. A separate non-author
manual source audit reported no actionable findings at confidence 4/5;
it did not rerun tests or qualify live QA. The official 4/5 review
requested a flag-scope test and saved-workspace control. This
test-and-documentation update adds both, with production source bytes
unchanged.
- Current-head canonical [CI
41258109282](https://github.com/paperclipai/paperclip/actions/runs/41258109282)
passed: all 59 checks are terminal (55 success, 3 skipped, 1 neutral),
with no failures or pending checks. Build and typecheck passed. The
eight-case regression file passed in the canonical Linux server 1/12
lane. Its checkout `6f69ccca70d10e78885b133fb54a80940bf175a5` has
parents `b889` and this exact head; its tree equals this head.
- Fresh Greptile and official Ponytail assessments each give 5/5 for
exact `27660027d12ff31427d611019e90dabfb6d8503a`, with zero unresolved
review threads. The separate manual audit remains 4/5.
- Live QA remains pending on a reviewed app build. This regression proof
does not claim that the hiring journey passed.

## Risks

A project source could be added after project hydration. This change
uses the same run-preparation source snapshot as the existing
authorization and source check. It only permits a positively known empty
workspace list. Configured sources, unknown shapes, foreign projects,
and existing execution authority keep their current checks. No schema,
credentials, provider, model, budget, or filesystem permissions change.

## Model Used

OpenAI Codex, GPT-6 family. The session does not expose a more specific
backend model ID or fixed context window. Used reasoning, repository
tools, TypeScript and test execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 20:19:28 -05:00
DottaandPaperclip 66e8fab944 fix: complete native chat responses and improve API discovery (#18364)
## Thinking Path

> - Paperclip must perform work and report its outcome accurately.
> - A chat response and its delegated or operator-owned work are
separate stages.
> - Native chat contracts instead required literal completion of the
user's whole request.
> - Agents kept searching or waiting even when a truthful handoff should
finish the response.
> - OpenCode also has separate acknowledgement backlog and
empty-response failure paths.
> - This PR aligns chat completion with its current stage and makes
OpenCode completion truthful.

## Linked Issues or Issue Description

Refs #18098 for retained OpenCode evidence and #18377 for separate eval
setup, oracle and reporting repairs.

**What happened?** Real pinned OpenCode 1.18.34 reproduced an MCP
timeout behind 800 text fragments. Pilot
[41222196525](https://github.com/paperclipai/paperclip/actions/runs/41222196525)
separately exposed a fabricated successful reply after a reasoning-only
response. Later restart attempts timed out without an answer. Their
native criterion literally required restarting the instance, although
the chat instructions and authority required an operator handoff.
General authority guidance alone did not resolve it.

**Expected behavior:** A standing chat completes its current authorized
response. It performs and verifies permitted actions, verifies delegated
handoffs, or explains the specific unavailable action and operator path.
The worker's task remains separate. Ordinary execution tasks must still
complete their requested work. Empty provider responses must not become
invented success.

**Version and reproduction:** Actual pinned OpenCode and native Rust
Runner, with retained full-stack AWS attempts. Product baseline master
`51ea624344`. This PR adds no historical catalog to master.

## What Changed

- Build standing-chat completion contracts from the server-owned
conversation identity. Scope each current request to the response stage;
preserve request text, criterion IDs, order, human-response scope and
source revisions. Require verified authorized actions and truthful
handoffs. Ordinary task contracts stay strict. Existing admitted inputs
retain their saved contract during recovery; new contract content uses
the existing revision/hash mechanism.
- Guide prospective defaults to their owning resource and preserve
existing work unless backfill is requested. Guide unavailable
board/operator operations to the supported handoff. These are general
chat instructions with no eval identities or expected answers.
- Batch adjacent assistant text for at most 50 ms and 4,000 UTF-8 bytes.
Preserve text, metadata and order; flush before non-text frames and
shutdown.
- Give an empty OpenCode response one correction within its existing
turn, model, reasoning, context and deadline. Accept actual completed
answer parts with incomplete headers. Preserve actual active tool work,
bound idle evidence grace and fail truthfully if correction stays empty.
- Reject empty OpenCode terminals in Rust without actual prose or an
accepted semantic result. Never invent successful replies or evidence.
Refresh generated project-discovery contracts.
- Preserve accurate public API-discovery descriptions for existing
project defaults and managed instance restart operations, including
their field scope and authority limits.

## Verification

**Qualified: [pilot
41256592937](https://github.com/paperclipai/paperclip/actions/runs/41256592937)
passes 3/3, with all 35 independent checks passing.**

| Case | Checks | Full case duration | Evidence and cleanup |
| --- | --- | --- | --- |
| Instance restart | 9/9 | 140.1 s | complete |
| Project defaults | 11/11 | 204.2 s | complete |
| Project work | 15/15 | 204.0 s | complete |

All three are original-attempt results from source
`c51e079f7f2364305b131ffd549e263ff78c5335`, containing the exact product
files from `13c2b61f31d873a475ea0c3c026b19926ff42301`. Actual saved
conversation contracts were inspected, as were ordinary native worker
contracts where present. Each protected archive includes the actual API
state and final PNG; cleanup completes. Original queries,
`openrouter/deepseek/deepseek-v4.1-flash-1017`, finite case clocks,
concurrency one and zero eval retries are preserved. Earlier passes do
not transfer into this qualification.

Both current heads pass all checks: product **62** (56 success, one
neutral, five skipped), catalog **56** (54 success, one neutral, one
skipped). Both have exact-head Greptile **5/5**, zero unresolved review
threads and clean mergeability. The three trusted private-evidence
protocol files remain byte-identical to the dispatch workflow. Raw
evidence stays protected.

- **2,044 API discovery tests pass.** Red controls showed that “restart
instance” selected unrelated drain/settings operations and “save project
defaults” selected repository replacement. Accurate public summaries now
rank the existing operations correctly; route registration preserves
descriptions. No endpoint, permission or field behavior changes.
- **112 real-database, authenticated HTTP, native Runner and OpenAPI
consumer tests pass locally**, using disposable task-owned Docker
PostgreSQL. It was removed afterward; shared IPC was untouched. These
cover persisted contract selection, admitted native input and the model
envelope together. The isolated CI suites also pass.
- **77 focused contract/input/context tests pass.** Red controls catch
the wrong conversation predicate; canonical identity requires both agent
and user IDs, including the actual heartbeat projection. Ordinary tasks,
agent-only issues and planner tasks remain strict. Coalesced requests
preserve criterion identities, source hashes and human-response scope.
- **144 OpenCode driver tests pass**; native core **441 pass, one
ignored**; packaging **56 pass, six skipped**. Server typecheck and
build pass.
- Real pinned OpenCode/native Runner: a delayed 25-second
acknowledgement completes within the original 30-second MCP deadline.
The text-fragment control changes 817 notifications / 54.1 seconds /
timeout to 45 / 19.0 seconds / accepted finish. Separate fast,
six-minute and real authenticated API probes complete 32 tool calls plus
finish. These do not reproduce every remaining historical MCP timeout,
and no common cause is claimed for all such failures.

Retained failures remain attributed to their original source. Earlier
runs exposed fabricated empty-response success, prospective-default
backfill, a literal whole-task chat criterion, fixture readiness and
oracle/reporting defects. The immediately preceding
[41250502608](https://github.com/paperclipai/paperclip/actions/runs/41250502608),
product `c0bf249807` / source `7b1de24ce1`, is **1/3**: work 15/15;
restart 4/9 with the repaired contract actually admitted but no answer;
defaults timed out before settlement, then exceeded the unchanged 256
MiB original-evidence allowance. Defaults domain behavior on that
attempt remains inconclusive. #18377 retains the full attempt ledger,
including missing archives and pre-paid cancellations. The fresh 3/3
establishes these selected outcomes; it does not establish full-catalog
reliability.

## Risks

The shared contract change applies to standing native chats across
providers. It changes model instructions and completion scope, while
permission, approval and review gates remain enforced by their existing
owners. Incorrect model claims remain possible; the product evals
independently require actual mutations, native work and delivery. The
correction adds at most one provider request within the existing
deadline; text batching can delay adjacent text by 50 ms. Three
qualified attempts do not establish full-catalog reliability.

## Model Used

OpenAI GPT-6 through Codex, with repository inspection, tool use, code
execution and live eval tooling. Exact hosted model revision and
context-window size are not exposed.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have 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

- [x] Final same-source three-cell pilot passes 3/3 with required
evidence and cleanup

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 19:52:42 -05:00
DottaandPaperclip b889ac39b7 fix: serialize native completion replies and bounded retries (#18502)
## Thinking Path

> - Paperclip manages agents and their work.
> - A delegated task reports its result to the source conversation
through a durable completion outbox.
> - Native execution can succeed before the presentation worker saves
the accepted final reply.
> - The outbox treated that short interval as a missing answer and
cleared the target run.
> - The presentation worker then rejected the valid answer because its
delivery no longer belonged to that run.
> - This change retains the existing target for one fixed presentation
grace while accepted presentation is pending.
> - The existing presentation owner can save the reply without another
model run or more budget.

## Linked Issues or Issue Description

**What happened?**

A completion-delivery retry can run immediately after a native callback
succeeds. It clears the callback's delivery target before the
presentation worker saves the accepted answer. The reply then fails with
`chat_completion_superseded`. A daily run limit correctly blocks the
unnecessary replacement run, leaving the conversation active without its
saved answer.

**Expected behavior**

The outbox must retain its current target and attempt while that exact
native run has accepted presentation work. The existing presentation
worker must save the answer once, acknowledge the delivery, and settle
the conversation. Existing actor, session, result, digest, budget and
retry checks must remain enforced.

**Steps to reproduce**

1. Accept a native DONE result and current-turn final message for a
completion callback.
2. Run its due completion-outbox handler after terminal projection but
before reply presentation.
3. Run the existing presentation worker. Before this fix it rejects the
reply because the outbox has cleared the target.

**Paperclip version or commit**

Reproduced on `b7f1c3769c00a107ffe4128b48b0ef8cc452cf3f` through the
real PostgreSQL outbox and presentation services. The reported failure
remains preserved. A new QA run is required after deployment; local
tests do not qualify the deployed fix.

Related: #17696 schedules accepted-response recovery. #18118 preserves
canonical completion receipts. #18364 handles provider output and
response-stage contracts. Those changes do not protect the
completion-outbox target during this interval.

## What Changed

- Defer a new execution attempt when the existing selector finds pending
presentation for the same company, conversation, run and agent.
- Retain the queued delivery target and attempt with an atomic
compare-and-set. Await the existing scoped worker notification before
that write in the same transaction.
- Serialize retry with reply insertion under the existing
child-task-first lock. Recheck locked task Done state and the delivery's
stable completion-event version, status, target, attempt and exact
lease. A delivered, retargeted or newer-claim winner prevents another
wake. Admit the next attempt only after the winning transaction commits
and releases its locks.
- Limit presentation grace to five existing one-minute delivery leases,
measured from the original run `finishedAt`. Clamp both the delivery
lease and the native retry deadline to that immutable limit. Repeated
sweeps cannot extend it. After expiry, resume the existing retry,
exhaustion and daily-limit checks.
- Keep publication authority in the existing materializer. The candidate
query only defers a retry. Read the freshly reloaded delivery status,
target and saved receipt after acquiring its child-task lock.
- Fence both hold and retry writes with the exact claimed event version,
attempt and lease. A stalled old hold cannot overwrite a newer lease.
- Keep completion-event identity separate from mutable task ownership
versions. Ordinary Done reassignment preserves its existing completion
event; a real reopen retains normal supersession.
- Add real PostgreSQL coverage for the observed ordering, outer commit
and rollback, one saved reply, conversation settlement, idle SQL, retry
boundaries and superseded deliveries.
- Document the completion-outbox and presentation contract.

## Verification

- Before the fix, the real PostgreSQL regression fails with
`chat_completion_superseded` in `existingChatCompletionReply` when the
outbox handles the terminal run first. After the fix, the same test
passes without a new model wake.
- Focused command: `vitest run --project @paperclipai/server
server/src/services/native-runtime/agent-chat-response-recovery.test.ts
server/src/__tests__/chat-completion-delivery.test.ts` — **95 pass** on
`45f53a8c32fcca0bbdacf717286d37e30c1ba308`, using a disposable database
on an owned local PostgreSQL 17 container.
- Controls preserve retries for failed, cancelled, missing-final,
missing-accepted-result, old-generation, foreign-company and
foreign-agent targets. Reset or superseded task versions retain
supersession. Digest and external-context declines never authorize a
reply, never extend the fixed window, and leave it at exact expiry. An
external native deadline cannot extend the limit. A valid reply at the
last millisecond saves once without another model run.
- The first reviewed head `b6f9c484b9567bc60af6d684c04e00058c1048ed`
received Greptile 5/5 but an independent 3/5 review correctly found an
unbounded hold. Three new real PostgreSQL controls failed on that
source. This head adds the fixed bound and makes them pass. The earlier
review, controls and CI remain retained; its review score does not
qualify the new head.
- The bounded predecessor `7300d2a978a5c4b3c13d85899bed3e98ae3c49fa`
received an independent 4/5 review that correctly found an
expiry-versus-in-flight-reply race. A real PostgreSQL advisory gate
reproduced it after reply authority checked the delivery but before
insertion. The retry lock and exact claim CAS now make that control
pass. Both orderings, outer rollback, delivered/retargeted/superseded
winners and competing lease claims pass. The next-wake test can acquire
both parent and child locks, proving dispatch occurs after release. The
valid 4/5 review and failing control remain retained.
- At `39dd86e8f51d937cf382b2757736e0477201d21d`, both reviews found
valid remaining defects: the reply helper still used its pre-lock
delivery snapshot, and ordinary Done reassignment could stall a delivery
by changing the task version. Four real PostgreSQL controls fail on that
source and pass here: concurrent retry-first, a newly saved receipt
after waiting, and reassignment within grace or at expiry. A real reopen
through the issue service still supersedes the old event.
- A later coordinator review found the hold CAS still lacked the attempt
and lease fences already present on retry. A real PostgreSQL producer
barrier reproduced an old hold shortening a newer claim from 120 seconds
to 60 seconds. The same exact claim fences now prevent that overwrite.
This failed control is retained; no old run was blindly retried.
- The real worker saves one exact run-owned reply and acknowledges the
delivery only after outer commit. An outer rollback publishes no reply.
After settlement, advancing the scheduler clock by 60 seconds causes no
further SQL.
- Module boundaries, map structure, `git diff --check` and the canonical
server build (including TypeScript and Runner vendor preparation) pass.
The first local build stopped in the host package-manager setup; the
installed pinned pnpm completed the build. Full repository typecheck,
test and build gates pass in current-head CI; they have not all been run
locally.
- Final local checks also caught a test cleanup type error (TS2677) and
one 94/95 readiness failure: the worker saves its comment before
post-commit conversation settlement finishes. The test-only follow-up
removes an invalid cleanup type predicate and waits on the existing
bounded worker-quiet check before reading final state. All assertions
and the same five-second bound remain. Source
`45f53a8c32fcca0bbdacf717286d37e30c1ba308` passes all 95 cases and the
canonical server build. The earlier failures are retained.
- The final policy cleanup removes only 15 newly added narrative comment
lines (seven service, eight test), as required by CONTRIBUTING.md. Both
TypeScript AST signatures and `removeComments=true` emitted JavaScript
are identical to tested source `45f53a8c32`. This was checked with the
TypeScript 6.0.3 API and the installed native TypeScript 7.0.2 compiler.
Assertions, timeouts and behavior are unchanged; the 95 tests were not
repeated for identical compiled code.
- The superseded `45f53a8c32` CI run recorded two 15-second timeouts in
attention-retention cases. That failure remains retained. The test and
its ten inspected owner or support files are identical on the tested
master revisions. The canonical base run passes all 53 attention cases,
and the comparison PR passes the same server lane, including those two
cases in 9.3 and 9.8 seconds. This does not establish the timeout cause.
Current-head CI is a new run after the required comment cleanup, not a
retry of the failed source.
- The optional Paperclip review bot ended neutral without a completed
assessment because its execution paused. That result is not an approval.
A separate [independent read-only
audit](https://github.com/paperclipai/paperclip/pull/18502#issuecomment-6550216227)
reports 5/5 confidence on exact head
`9cfd3f74c69cc7a2da7b4ee5d1fca80f15d4af0c`, with no findings. Its manual
assessment does not replace or relabel the incomplete bot result.
- Current head `9cfd3f74c69cc7a2da7b4ee5d1fca80f15d4af0c` has a fresh
Greptile 5/5 review with no open threads. [CI run
41249007430](https://github.com/paperclipai/paperclip/actions/runs/41249007430)
passes all primary jobs and both required gates (`ci / verify` and `ci /
e2e`). All 59 PR contexts are terminal, with no failed contexts. The
actual CI checkout is `18db9e2750d6a799f26b5b8ba31bcccbea254227`, which
combines master `681f7b77262a9df6c1b4aad55291bf960061e491` with this
exact head. Fresh QA verification on the deployed application remains
required before claiming the live failure is fixed.

## Risks

A candidate can retain a delivery whose stricter presentation checks
still prevent publication, but only within the fixed five-minute window.
The existing worker keeps publication authority. If a valid reply
remains unavailable at expiry, the normal callback retry may require
another admitted model run; the original result and completed child work
remain preserved. Existing retry, exhaustion, model-run and spending
limits still apply. Failed or cancelled execution and genuinely missing
accepted output retain the existing retry path.

## Model Used

OpenAI GPT-6 through Codex, with repository inspection, tool use and
code execution. The runtime does not expose the exact hosted revision 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-31 18:07:41 -05:00
DottaandPaperclip 681f7b7726 perf(server): retire aggregate maintenance polling (#18425)
Reviewed and verified at 901c4c4bdc.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 17:22:31 -05:00
DottaandPaperclip 9ca9af544a Drive remaining live run and resource recovery from durable work (#18419)
Reviewed and verified at 6a4c193906.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 16:00:35 -05:00
DottaandPaperclip eb12cfc96b perf(github): activate connection work from events and deadlines (#18395)
Reviewed and verified at f77620b9a4.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 15:38:43 -05:00
DottaandPaperclip 5e4cc01073 feat(workspaces): keep remote files off the webserver disk (#18403)
Keep native sandbox workspace files independent of the webserver disk. Use encrypted saved versions and Postgres ownership so a replacement server can recover files and continue work. Enable the path by default for new eligible workspaces when durable storage is configured.

Preserve explicit opt-outs and existing host workspaces. Include safe snapshot repair, Files access, import, migration and retention. Bound saved-Files resources, preserve imported Git recovery, reject unfinished Git operations, publish immutable concurrent captures, and verify permanent object-version deletion.

Validated 471 targeted local controls, build/typechecks, all 40 CI partitions, fresh Greptile 5/5 and security review. The PR records original failed attempts and scoped retries.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 14:54:01 -05:00
DottaandPaperclip 75fa37f30f fix(server): expire native backups from retention deadlines (#18380)
Reviewed and verified at 5b137b5cda.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 14:31:31 -05:00
DottaandPaperclip 453f5fbb78 perf(external-objects): schedule scoped refresh obligations (#18384)
Reviewed and verified at 3e58e12f87.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 14:09:24 -05:00
DottaandPaperclip c32ecf6657 fix(server): schedule only outstanding merge confirmations (#18382)
Reviewed and verified at bc22051c56.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 13:44:46 -05:00
Nicky Leach 6484f96c28 fix(workspaces): inspect storage only when needed (#18410) 2026-10-31 11:43:18 -07:00
DottaandPaperclip 9a3f395737 fix(server): settle routine history without idle scans (#18399)
Reviewed and verified at 0b65f490d9.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 13:19:31 -05:00
Dotta 3937215a05 Qualify explicit native written references in the basic question journey (#18459)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Basic task journeys must prove that people can answer an agent and
receive saved work.
> - The question journey asks for a choice, then a typed reference, then
a saved note.
> - A native choice card can offer a real written-answer control as well
as predefined options.
> - The old observer rejected that form before a person could type the
reference.
> - This pull request accepts that explicit native control and keeps
exact answer and work evidence.
> - The separate text-only and named-tool qualifications keep their
stricter contracts.

## Linked Issues or Issue Description

Refs #18346 and #18456. The integration inherits the reviewed fixture
prerequisite #18387 and Agent Chat recovery #18465 through their actual
merged parent. The producer fix in #18456 is separate from this basic
journey contract correction. Public duplicate PR and issue searches
found no other correction for this form equivalence.

**What happened?**
The basic question journey requires the reference card to have
`answerMode: text`. It rejects a native single-select card even when its
canonical form explicitly enables a written answer. This makes the
observer test a widget shape in addition to the requested behavior.

**Expected behavior**
The person must make a real choice and type the complete reference. A
native card with an explicit written-answer control can satisfy the
second step. Selecting a predefined option cannot satisfy it. The agent
must resume the bound work and save both actual answers in its own task
document. The document must survive reload.

**Steps to reproduce**
Use the focused recording and real QuestionForm browser test in this PR.
Keep the reference as a single-select native question with one
predefined option and `customAnswer.enabled: true`. The previous grader
rejects `question-resume.forms`. The previous browser helper rejects
`single_select` before it uses the written-answer control.

**Paperclip version / commit**
Original source base `f2db909393de124caf6a5380a52d4e0e1d621661`. Current
integration `a417fd827347ed6f7998774a9de6aee70b76d867` merges exactly
`12b0cc630471ee151ec5bc8e41a34f09236d6723` into reviewed question source
`faec4ce6d775a34d303d200987e4e84d6dc26caf`. The scheduled failure on
`82d15946c5844d3ae41c6ade62fa224053f20a9a` remains a failure. Its saved
card had no canonical written-answer capability and would still fail
this change. The retained normalized events do not prove whether the
original provider flag was omitted or false.

**Deployment mode**
Attached native task journeys, including QA Cloud. This PR changes the
observer and grader. It does not change the app, provider prompt, model,
budget, timeouts, cleanup, or runtime deployment.

## What Changed

- Accept one provider-bound single-select reference card with explicit
canonical custom answers and valid, distinct options. Keep pure-text
reference support.
- Make the browser select the actual written-answer control and fill the
real rich input. Opt in only for the basic question journey.
- Keep the exact no-option typed response, immutable card, board actor,
native request and continuation, saved agent document, reload, model,
environment, checkpoints, and existing one-to-three-run checks.
- Reject missing or disabled custom capability, inferred legacy
capability, malformed or extra questions, foreign native identities,
changed cards, substituted options, and wrong or missing reference text.
- Add a real production QuestionForm and TaskChatRichInput Chromium
probe. It first selects a predefined option, then proves the helper
clears it and submits only the exact custom text.
- Document the contract correction and preserve the historical failed
attempt and its separate cleanup outcome. Keep necessary-question and
named-tool documentation qualification unchanged.

## Verification

- Before the observer change, the focused grader regression failed only
the new valid-written-reference case; the other 108 cases passed.
- Before the browser helper change, real Chromium passed the text
control and four rejection controls but failed the valid native
written-answer control at the old pure-text assertion.
- Initial focused Runner E2E unit selection at `af07f4de`: **256 passed
across 9 files**. This includes question/resumption, clarification
evidence/flow/collection/deadline, necessary question, documentation,
contracts, and report catalog tests.
- Initial real Chromium selection at `af07f4de`: **12 passed**. Six new
production QuestionForm/control checks and all six existing
document-readiness checks pass. No form or rich-input component is
mocked.
- Historical test-only head `faec4ce6d775a34d303d200987e4e84d6dc26caf`
adds a direct canonical-absent legacy `freeText` grader negative and
renders the actual legacy presentation in the browser. All four
production helper blobs remain identical to the reviewed head. A
temporary legacy inference mutant makes the new negative fail. After
restoring production source, **179 focused unit tests and all 6 real
QuestionForm checks pass**. The six document-readiness specs and their
helper are unchanged.
- Original [CI run
41205748589](https://github.com/paperclipai/paperclip/actions/runs/41205748589)
failed the staged-listen Runner handoff test; that failure is preserved
and was not retried. Its Runner source closure was identical to an
earlier passing canonical lane. The symptom also recurred on other heads
and is tracked independently; no infrastructure attribution or live pass
is claimed.
- Current integration `a417fd827347ed6f7998774a9de6aee70b76d867`
preserves **all 12 question files byte-for-byte** from faec. Every other
tracked path is identical to exact merged parent
`12b0cc630471ee151ec5bc8e41a34f09236d6723`, which contains actual
prerequisite `baf651c8d0122efc93f3ef03e891919eeb666215`. There is no
manual conflict resolution or additional production edit.
- On that integrated head: **257 focused Vitest tests across 9 files,
206 required Node source/reporter tests, and 12 real Chromium tests
pass**. Map/module-boundary checks and catalog discovery pass. The
actual `--preview` command passes with a synthetic question target and
an intentionally unavailable adapter; it performs no credential read,
adapter loading, provisioning or model call. It retains maxRuns3, a
600000ms campaign bound and zero retries.
- Exact-head [CI run
41210806950](https://github.com/paperclipai/paperclip/actions/runs/41210806950)
passes, including official typecheck, build, all eight browser shards,
both Runner Vitest lanes and aggregate verify. All 59 current PR
contexts are terminal with no failures. Fresh [Greptile
summary](https://github.com/paperclipai/paperclip/pull/18459#issuecomment-6543878408)
explicitly reviews `a417fd827347ed6f7998774a9de6aee70b76d867` at 5/5
with no findings; its exact-head check succeeds and all threads are
resolved. No fresh deployed journey pass is claimed yet.
- Catalog discovery lists the existing question journey. Map checks and
module-boundary checks pass. Diff checks pass.
- `tsc -p tests/runner-e2e/tsconfig.json` was attempted. The fresh
integrated checkout still lacks compiled Runner, plugin SDK, and adapter
declarations. The attempted local check reports 344 diagnostic lines
from dependency/type closure and zero diagnostics in all 12
question-owned paths. Official exact-head CI establishes the full
typecheck/build gates. Full repository build, typecheck, and test suites
were not repeated locally for this observer change.
- The first broad local report selection lacked the CLI loader and then
hit sandbox IPC restrictions. Locked dependency installation and an
authorized local IPC run resolved those setup errors; the full selected
256 tests pass. The initial localhost probe also needed the normal
local-listen permission.
- No fresh QA pass is claimed. The coordinator must qualify the final
reviewed runtime and harness together. Prior failed results remain
preserved.

## Risks

The basic journey accepts one additional form with explicit native
provenance. It still rejects the original closed card without a
written-answer capability. The separate producer default fix must reach
the selected remote provider pack before it can affect a deployed run.
Local browser and grader tests do not prove that artifact served or that
a model completed the live journey. Existing cleanup and physical-stop
obligations remain separate.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, source inspection, browser
testing, and code execution. The host does not expose the exact
underlying model version 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 available 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 work above
- [x] I have described the issue in-PR following the bug template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket or instance-derived details
- [x] I have run the selected tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented 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
2026-10-31 13:16:40 -05:00
DottaandPaperclip dce383c733 perf(server): stop recurring attention retention scans (#18388)
Reviewed and verified at a61af9888e.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 12:28:40 -05:00
DottaandPaperclip b6b57079b9 fix: evaluate status cards on committed changes and deadlines (#18401)
Reviewed and verified at 21795e222a.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 11:41:59 -05:00
DottaandPaperclip e40de0c9e8 perf(ci): refresh test weights and narrow graph dependencies (#18464)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Contributors need fast, reliable CI feedback.
> - Diff-aware CI selects test files and partitions them into runner
jobs.
> - Stale cost estimates put several slow suites on the same runner.
Broad imports also couple small tests to large modules.
> - This PR refreshes test costs, runs independent graph discovery in
parallel, and narrows three dependency boundaries.
> - Selection safeguards and CODEOWNER-only AWS routing stay in force.

## Linked Issues or Issue Description

Refs #18398. This follows the audit of [PR #18427's verification
run](https://github.com/paperclipai/paperclip/actions/runs/41169978784).

The audit found 403 selected general-server files without timing
weights. Three suites measured at 232s, 122s and 116s shared one shard
because each received a roughly 2s fallback weight. Local graph
discovery across four projects took 43.7s serially and 21.7s with two
workers. A reverse-order repeat took 37.7s serially and 22.6s with two
workers. Both comparisons produced identical selection results. This is
a local measurement, not a claim about production CI speed.

## What Changed

- Refresh general-server costs for 1,285 of 1,309 current files and
serialized costs for all 163 files from two successful protected-master
Cloud readiness runs. Retain prior costs for unmeasured files, including
dedicated chat and native-runner suites.
- Record passing server file costs, including collection, setup and
environment preparation. A weekly hosted workflow validates trusted
source runs and opens a timing-only PR. It tests shard coverage, pauses
while a refresh PR is open, and never merges automatically.
- Discover at most two project graphs concurrently in isolated,
heap-limited Node processes. Cache repeated inventory reads within one
selection. Worker errors and timeouts retain the full task plan.
- Fetch only the merge commit and parents for the selector. A real
shallow-clone regression proves the complete diff still includes more
than 300 files, renames and deletions.
- Share the identical log viewer and run details between both
AgentDetail pages. The viewer test imports the shared implementation and
runs each of its 13 distinct cases once.
- Extract the pure API error class while preserving the API client's
public exports. Import delivery work signals through their existing
narrow DB export.

## Verification

- PASS: `pnpm -r typecheck` and `pnpm build`.
- PASS: 284 CI selection, timing, shallow-diff, sharding and routing
tests.
- PASS: 74 further cache, routing and graph-proof tests.
- PASS: 94 targeted UI assertions across the viewer, run invocation, API
errors/client and progress helpers. All 76 assertions in the 12 server
suites made independently selectable also pass.
- PASS: `pnpm check:token-gates`, module-boundary checks, YAML parsing
and `git diff --check`.
- PASS: [Full PR CI and required `ci / verify`
aggregate](https://github.com/paperclipai/paperclip/actions/runs/41206683345),
including all 12 general-server shards, all nine serialized shards,
workspace groups, chat suites, Runner lanes and build checks.
- PASS: [GitHub hosted real-workspace selector and cache/routing
qualification](https://github.com/paperclipai/paperclip/actions/runs/41206683205).
- PASS: Both Greptile and Paperclip reviews are 5/5 with no actionable
findings or inline comments on `7dc65c51b8`. The PR has no merge
conflicts.
- PASS: The production refresh parser accepted all 107 structured
file-cost records from a real successful server CI job, including
setup/loading cost.
- Local `pnpm test:run` completed all six chat shards successfully. The
duplicate monolithic local run was stopped after the complete remote
suite passed; it was not completed locally.

The focused log-viewer command improved from 18.84s (26 duplicate
variant cases) to 8.49s (all 13 distinct behavior cases). The dependency
audit confirms 12 server files and the API-error test no longer need
conservative always-run retention. Repartitioning the audited PR with
the new costs changes the slowest shard from 810s to 591s of summed
historical test execution (1,124 of 1,142 files measured). This is a
workload simulation, not measured new CI wall time.

## Risks

- Two graph processes use more peak memory. Each has a 2 GiB heap limit
and a three-minute timeout. Any failure preserves the original task
plan. Real workspace qualification runs in GitHub CI.
- Historical logs contain test/hook costs only. New reporter records add
loading/setup costs after merge. The manifests identify measurement
coverage and source runs. These weights change placement, never
permission to skip tests.
- Runner load adds timing noise. The refresh uses medians and requires
at least 90% measurement coverage in each lane.
- GitHub may require approval to run checks on a PR created with
`GITHUB_TOKEN`. Refreshes remain reviewable and do not merge themselves.
- The shared viewer is a mechanical extraction. Both pages retain their
existing exports, and the behavior assertions remain covered. AWS runner
authorization is unchanged.

## Model Used

OpenAI Codex, GPT-6, with repository inspection, reasoning, code
execution and GitHub tools. The exact deployment ID and context-window
size were not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub 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 (focused checks and six
chat shards; complete suite passed in CI as detailed 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-31 11:05:12 -05:00
DottaandPaperclip b7f1c3769c feat(native): record verified provider-pack session admission (#18469)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Remote native sessions can use an installed pack or a retained
earlier pack.
> - The current app revision does not identify the pack that a session
admitted.
> - Core already verifies the selected pack and binds its launch
artifacts.
> - Normal run records lack a closed receipt for that admitted
selection.
> - This pull request records that receipt after session admission and
attachment.
> - Operators can compare the actual Core admission identity with their
expected pack.

## Linked Issues or Issue Description

Refs #17749 for protected provider-pack selection and #18343 for
retained controller recovery. The related OpenCode producer repair is
#18456. Those changes do not publish the closed run receipt added here.
A search found no existing `nativeProviderPackAdmission` PR.

**What happened?**

Core can admit a compatible installed provider pack with a source
revision that differs from the current app. A retained session can also
keep its original pack. The normal run record does not show the admitted
pack digest, proxy digest, and source revision. An expected launch path
or current app revision cannot fill that evidence gap.

**Expected behavior**

The run has a closed, server-owned receipt after actual session
admission and attachment. The first receipt remains immutable history. A
separate current-proof state verifies only the actual current admission
epoch. Retained recovery needs positive original provenance, and missing
legacy evidence stays unknown.

**Steps to reproduce**

1. Select and verify an installed pack whose digest differs from the
current app pack.
2. Open the native session successfully.
3. Inspect the normal run profile for a bound admission receipt.

**Paperclip version or commit**

The original selected base was
`8bcc5a01edd5d87540401521e6f30d3df43e1848`. The branch now includes
exact actual prerequisite parent
`3ee4c5b6138da82d0b1f51aa010540561bf43c22`; the PR diff against it is
the five receipt, executor, test and documentation files.

**Deployment mode**

Core remote native execution with provider-pack selection and retained
session attachment.

## What Changed

- Retain the verified selected pack identity only after a backend
returns the matching admitted session.
- Publish `runnerProfileJson.nativeProviderPackAdmission` from the
session callback after attachment succeeds.
- Mark the receipt with `stage: session_admitted` and `authority:
core_verified_selection`.
- Store bound company, agent, run, session, runner, logical
`runnerEnvironmentLeaseId`, pack digest, OpenCode proxy digest, and
source revision fields. Retained attachments identify
`inheritedFromRunId`. The logical Runner scope is distinct from the
physical environment lease.
- Lock the current coordinator claim before the profile write. Check
owner, attempt, generation, controller boot, lease expiry, phase, and
absence of an accepted result. Merge JSON fields without replacing other
profile data.
- Restore retained metadata only from the exact prior closed Core
receipt, positively verified prior state and matching retained binding.
Capture same-run prior provenance from the locked claim row before
invalidation; cross-run recovery reads only the exact source. Legacy
absence remains unknown while recovery continues.
- Preserve the first receipt as history. Atomically mark a new opaque
admission epoch pending in the existing mandatory claim transaction.
Publish current verification only for the matching claim and epoch after
actual attachment; changed or unsupported admission becomes unknown
without blocking authorized execution.
- Preserve synchronous session publication and quarantine ordering
before the best-effort receipt write. Fresh replacement selects its
newly verified pack; a captured retained-process flag cannot relabel the
replacement with an older pack. Preserve the existing private pack
authority even when a local dirty revision is ineligible for the closed
receipt.
- Add focused admission, recovery, identity, PostgreSQL ownership, lock,
and JSON-preservation tests. Document the receipt contract.

## Verification

- RED: the actual managed-backend path verified and admitted an
installed pack but had no closed metadata. Failed open published no
evidence. Additional controls fail when retained recovery invents
missing history or dirty-revision eligibility gates the existing private
authority.
- RED calibration: removing mandatory pending invalidation fails the
actual pre-admission control; reusing the retained flag for fresh
replacement falsely restores the old pack. Removing the epoch fence
fails the real PostgreSQL stale-callback case; reintroducing a
receipt-specific execution error fails both authorized
Runner/logical-lease replacement controls.
- GREEN: 49 focused Core tests, all 33 admission identity/transaction
tests (20 pure and 13 PostgreSQL), and all 23 existing private-authority
tests passed on exact integrated head
`165a9096cf3e0d34d2db1e6b52960ad4ac0ad132`. No all-skipped run is
counted.
- Final test-only head `11ac34baf00552a5d322b5f5f1a8e491859cacec` adds
the positive executor-callback SQL-writer wiring control, exact
session/identity/claim/epoch assertions, profile preservation, and
null-session zero-write check. Removing only the production writer call
makes it fail on a missing receipt. All70 focused identity/Core tests
pass with this closure; production code, the13 PostgreSQL tests and
the23 private-authority tests are byte-identical to the qualified165
source (106 distinct passing controls across the combined proof).
- The PostgreSQL tests used an owned loopback-only cached Postgres 17
container with the supported `PAPERCLIP_TEST_POSTGRES_ADMIN_URL` helper
and aliases to current DB/shared source. The container was removed
afterward. They cover immutable history, JSON preservation, stale claims
and epochs, expired leases, terminal runs, changed/unsupported
replacements, and a failed write retaining pending proof.
- Historical pushed `f7f12fe` CI executed all 24 earlier admission
tests, including nine PostgreSQL cases, in server5. Its warm-quarantine
failure exposed the new hook-ordering issue fixed here. The same run
also encountered a six-character UUID fixture-prefix collision and the
independently repaired cached issue-link browser selector; those
historical failures are not claimed as green.
- Node 24.22.2 and Vitest 5.0.3. The credential-free normal QA runtime
import preflight passes with networking disabled. Map contracts, token
gates and `git diff --check` pass.
- Local TypeScript validation still sees stale borrowed Runner/shared
declaration mismatches outside the changed ranges. No diagnostics remain
in the new helper or changed test/hook ranges; clean current-head CI is
required.
- Repository-wide typecheck, full tests and build were not completed
locally. A full local executor attempt reached this host's unsupported
native PostgreSQL listener and was interrupted; its result is not
counted. Canonical run `41214512239`, attempt 2, is successful on exact
final head `11ac34baf00552a5d322b5f5f1a8e491859cacec`. All 59 checks are
terminal: 55 success, 3 skipped and 1 neutral; none failed or pending.
The actual Linux suites execute all 33 admission tests (including 13
PostgreSQL cases) and all 1,022 executor tests successfully. The
[original five failures and bounded unchanged-source
controls](https://github.com/paperclipai/paperclip/pull/18469#issuecomment-6545593767)
remain preserved. One failed-only request was made; GitHub expanded the
reusable workflow call and dependents. No second request was made. Fresh
exact-head Greptile review is 5/5, all review threads are resolved, and
the PR is mergeable.
- These local results claim no live provider admission, rollout or
recovery.

## Risks

- The authority is Core's verified selection plus successful session
admission. It is not an independent provider statement or continuous
runtime measurement.
- Receipt fields cannot grant execution or replace the existing
provider, process, lease, workspace, or recovery checks.
- Legacy missing receipts and unavailable database reads remain unknown.
The current release cannot label an older admitted pack.
- The closed receipt requires a clean, 40-character hexadecimal source
revision. Verified local `-dirty` packs still execute and retain their
existing private recovery authority; their closed admission proof stays
`unknown`, so it cannot certify an immutable source revision.
- The first receipt is historical. Consumers must require current state
`verified`; pending or unknown cannot certify the current pack. Changed
Runner scope or pack evidence does not add execution policy.
- A receipt save failure leaves the atomically invalidated state
pending. The existing artifact authority, cancellation, workspace and
process checks remain responsible for execution safety.
- The receipt adds no manifest, environment, credential, or filesystem
path to the run record.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code editing, and tool
use. The session does not expose an exact model build ID or
context-window capacity.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
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-31 10:59:24 -05:00
DottaandPaperclip 3ee4c5b613 Make saved execution receipt recovery react to durable work (#18409)
Reviewed and verified at 8f306e0a6e.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 10:03:59 -05:00
DottaandPaperclip 42fd568cf8 Drive issue recovery from committed changes and exact deadlines (#18402)
Reviewed and verified at 11b49125db.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 09:41:27 -05:00
Dotta 12b0cc6304 fix(chat): recover committed native Agent Chat replies (#18465)
## Thinking Path

> - Paperclip manages agent work and keeps its results available to
users.
> - Agent Chat needs a visible reply before the conversation can wait
for more input.
> - Native result commitment and reply presentation are separate
obligations.
> - A completed conversation can retain a valid final message without a
saved reply.
> - Existing reply recovery excludes these completed conversation turns.
> - This pull request repairs that persistence gap through the existing
recovery worker.

## Linked Issues or Issue Description

**What happened?**

A native Agent Chat turn completed successfully and saved its workspace.
Its accepted result and final assistant message were durable, but no
reply appeared in the conversation. The chat stayed active. The
deployment hiring journey in #18351 then reached its deadline while
waiting for the first reply.

**Expected behavior**

Recover the exact accepted turn's final reply once, then use normal
conversation settlement. Keep later user input active. Do not run the
agent again or replace a selected or deleted reply.

**Steps to reproduce**

1. Create an active conversation with one admitted native turn.
2. Commit an accepted DONE result and a final-channel assistant message
for that exact run, session and turn.
3. Finish workspace finalization before live heartbeat reply
presentation. Leave no saved reply.
4. Run normal response recovery. Before this fix it finds no
conversation candidate and leaves the chat active.

**Paperclip version or commit**

Reproduced with actual services at frozen master
`8bcc5a01edd5d87540401521e6f30d3df43e1848`. The production predicate
also exists in the deployed revision that exposed the failure.

Related work: #18351. The broader receipt and recovery work in #18118
and #18409 does not touch these source files.

## What Changed

- Discover unanswered committed Agent Chat turns through the existing
native response presentation worker.
- Recheck company, agent, responsible user, current execution and
conversation generation under the normal transaction locks.
- Require the accepted result digest and an exact final message from the
same native run, session and accepted turn. Keep external publication
authority separate.
- Commit the reply and presentation receipt before normal conversation
settlement. Later input stays active. Recovery does not repeat agent
work.
- Preserve skip decisions and selected or deleted replies. Add database
controls for foreign identity, stale sessions, partial commitment,
duplicates and ordinary internal task behavior.
- Document the recovery boundary in the developer guide.

## Verification

- Real-service RED/GREEN uses all 418 canonical migrations in isolated
PGlite and the exact new regression fixture. Before the fix: zero
candidates, no reply, recovery returns false and the chat stays active.
After the fix: one candidate, one exact reply, recovery returns true and
the chat waits. A repeat returns false and creates no second reply.
- All 20 canonical regression cases pass locally through a fixture-only
PGlite bridge. Only local database provisioning and `createDb` selection
differ from the normal embedded PostgreSQL fixture. Production services,
SQL queries, transactions, protocol validation and assertions remain
real. Linux embedded PostgreSQL CI is required before merge.
- Focused current-source no-emit typing passes for both production
modules and the new regression file, with normal Express augmentation
and source aliases. The broader local presentation/ownership and
conversation-settlement PGlite bridge run was interrupted before it
reported results; it is not counted as a pass. No repository-wide local
build is claimed from borrowed workspace dependencies. Clean-build CI
and canonical PostgreSQL consumer tests remain required.
- `git diff --check` and the scoped source/test secret scan pass. No
captured run data, credentials or private target identities are
committed.
- No live journey retry, deployment, configuration change or test-plan
admission was performed. The original failed journey remains failed;
this production fix still needs deployed qualification through the
unchanged journey.

- Current-head [canonical Linux
CI](https://github.com/paperclipai/paperclip/actions/runs/41207018345)
passed all 57 terminal checks with no failure or pending check. The new
20-case database regression actually passed in [server shard
8](https://github.com/paperclipai/paperclip/actions/runs/41207018345/job/124555006090),
at 13:59:25 UTC (2,643 ms). Typecheck, build and the existing consumer
lanes passed. Fresh [Greptile
review](https://github.com/paperclipai/paperclip/pull/18465#issuecomment-6544208002)
on exact `f32a432e10b377ae6277d6f728995d5fedcf9d7b` is 5/5; the
review-thread inventory is empty with no pagination. No live deployment
or journey pass is claimed by these checks.

## Risks

Eligible active conversations can gain a previously missing reply.
Recovery accepts only the exact saved final message under its accepted
result and current conversation identity. It does not run a model,
repeat hiring or change a prior test grade. Reply persistence precedes
waiting-state settlement; existing conversation recovery retains
ownership of a later interrupted settlement. No schema or public API
changes are included.

## Model Used

OpenAI Codex, GPT-6 family. The session does not expose a more specific
backend model ID or fixed context window. Used reasoning, repository
tools, TypeScript and real database test execution.

## Checklist

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 09:07:52 -05:00
DottaandPaperclip 12d8c3043e fix(native): fence retries when replaying an audited Stop (#18457)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs keep Stop intent and retry state in durable records.
> - A provider error can leave a failed retry with an earlier
acknowledged Stop.
> - The replay path returned the existing receipt before it closed that
retry.
> - This pull request applies the existing retry fence to the validated
replay.
> - The same Stop can settle without another provider cancellation or a
new receipt.

## Linked Issues or Issue Description

Refs #14733 for the related caller-bound Stop contract. This change
covers a later retry that already has a Stop acknowledgement. The older
CI-only #14743 is not a production delivery PR.

**What happened?**

A failed native run can have a retryable coordinator and an earlier
audited Stop. A repeat Stop returns the old acknowledgement without
moving the coordinator to `terminal_failure`. The final
failed-to-cancelled transition requires that fence, so the Stop cannot
settle through that path.

**Expected behavior**

A valid replay closes the same retry and keeps the original intent and
acknowledgement. It does not send a second provider cancellation.
Physical stop and workspace cleanup still require their own evidence.

**Steps to reproduce**

1. Store a failed native run with a `retryable_failure` coordinator.
2. Store a matching run-scoped Stop with a dispatched acknowledgement
and audit IDs.
3. Call `cancelNativeSession` for that same run and inspect the
coordinator.

**Paperclip version or commit**

Reproduced on public master `f2db909393de124caf6a5380a52d4e0e1d621661`.

**Deployment mode**

Core native execution. The regression uses the real cancellation
executor with controlled persistence and provider boundaries.

## What Changed

- Reuse the existing guarded coordinator fence for a validated Stop
replay.
- Test repeated replay, unchanged receipts, one fence, and no second
provider cancellation.
- Reject foreign company, run, issue, scope, effect, and missing-audit
receipts before any write.
- Check that an acknowledged Stop with an unconfirmed remote lease still
fails the physical-stop guard.
- Document the separate retry fence and physical-cleanup requirements.

## Verification

- RED on the selected public base: the new executor case returned
success but left the coordinator in `retryable_failure` with a future
retry. One case executed and failed for that assertion.
- GREEN: 62 focused tests passed across
`native-session-executor.test.ts` and
`native-cancellation-request.test.ts`. These include ownership, caller
conflict, changed-phase, and receipt controls.
- Command from `server/`: `node ../node_modules/vitest/vitest.mjs run
src/services/native-runtime/native-session-executor.test.ts
src/services/native-runtime/native-cancellation-request.test.ts -t
'native session cancellation|caller-bound native cancellation|failed
native retry caller admission'`.
- Canonical Linux CI passed all 1,018 executor cases and all 32
caller-cancellation cases. The exact file completion lines are in
[server shard
2](https://github.com/paperclipai/paperclip/actions/runs/41203989386/job/124545366271)
and [server shard
10](https://github.com/paperclipai/paperclip/actions/runs/41203989386/job/124545366219).
- Node 24.22.2 and Vitest 5.0.3. Map contract checks and `git diff
--check` pass.
- Local dependencies are linked from an existing checkout. Full local
TypeScript validation reports older Runner/shared declarations that lack
current Kimi and continuity APIs. The changed ranges have no
diagnostics. The canonical clean CI Typecheck + Release Registry gate
passed.
- A broader two-file run was stopped when an unchanged integration case
tried to start embedded Postgres and hit the host listen restriction. It
is not a passing full-suite result. No host settings or other services
were changed.
- Repository-wide `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build`
were not completed locally. Current-head CI passed against clean source
and dependencies.
- Fresh [Greptile
review](https://github.com/paperclipai/paperclip/pull/18457#issuecomment-6543772487)
on `dbc1c1a5b71450194d568725592969660864cb5a`: 5/5 with no actionable
findings. The review-thread inventory has no threads and no pagination.
Full [current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/41203989386)
passed: 59 terminal checks, 55 successful, 3 skipped, and 1 neutral. No
failure or pending check remains. Merge status is CLEAN. No live
recovery, rollout, or physical termination is claimed.

## Risks

- A wrong or stale Stop must not close another retry. Existing
run/coordinator locks, caller checks, receipt binding, and the final
compare-and-set remain in place.
- This fix changes logical retry settlement only. Provider termination,
workspace preservation, lease cleanup, and continuation gates remain
separate.
- The regression controls persistence and provider boundaries. It does
not establish the physical state of a remote provider.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code editing, and tool
use. The session does not expose an exact model build ID or
context-window capacity.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
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-31 08:25:16 -05:00
DottaandPaperclip c2971badde perf(server): recover independent native replies concurrently (#18421)
## Thinking Path

> - Paperclip manages work for AI agents.
> - A native run can commit its result before its reply is saved.
> - The response recovery worker saves replies from those committed
results.
> - It checks each candidate in series, so one task can delay unrelated
tasks.
> - This pull request checks up to four independent tasks at once.
> - Each task keeps serial checks, and the existing coordinator owns
retries and shutdown.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Recovery of committed native task replies.

**Current behavior**

The worker checks one candidate at a time in a batch of up to 25. A
database lock or a slow read for one task delays replies for other
tasks.

**Proposed behavior**

Check up to four company-and-task groups at once. Check candidates
within each group in their existing order. Keep the current batch limit
and company selection.

**Reason and benefit**

A ready task reply can be saved while another task waits for a database
lock. The change reduces waiting under a reply backlog.

**Breaking changes**

Replies for different tasks can be saved in a different order. There are
no API or schema changes. Other deadline workers keep serial dispatch.

Related work: #17696 adds the recovery worker. #17501 reduces its read
payloads. #18367 adds its timing spans. These changes are already
merged. The PR search found no open change that adds this concurrency.

## What Changed

- Add optional keyed concurrency to the shared scoped deadline worker.
- Enable a limit of four for native response recovery, keyed by company
and task.
- Await all active checks before the pass ends. Retain per-candidate
failure backoff, drain behavior and pending work.
- Test concurrency limits, task order, company separation, drain/resume,
shutdown, retries and idle wake behavior.
- Add a PostgreSQL regression that holds one task's finalization row
lock while a second task saves its exact accepted reply.
- Document the worker's concurrency and sleep contract.

## Verification

- The PostgreSQL lock regression fails with serial dispatch. It passes
with this change. Both accepted replies are saved once after the lock is
released.
- `pnpm exec vitest run
server/src/__tests__/scoped-deadline-work.test.ts
server/src/__tests__/delivery-work-coordinator.test.ts
server/src/__tests__/company-work-batch.test.ts
server/src/__tests__/deadline-work.test.ts
server/src/services/execution-preparation-timing.test.ts` — 55 tests
pass.
- `pnpm exec vitest run
server/src/services/presentation-ownership-read.test.ts` with its
documented dedicated PostgreSQL URL — 21 tests pass. The disposable
database was dropped.
- `pnpm -r typecheck` — passes.
- `pnpm build` — passes.
- One matched local replay with 25 older pending replies and one fresh
reply used the real worker, a 10-connection PostgreSQL pool and 8 ms
delay in each network direction. The saved fresh reply was first
observed after 29.193 s with serial dispatch and 9.798 s with this
change. All 26 replies were saved exactly once in both runs, with no
worker errors. Both disposable databases were dropped. This is one
synthetic workload pair, not a staging measurement.
- `pnpm test:run` was attempted. Embedded PostgreSQL could not
initialize its template after five attempts, so the broad run was
stopped. The changed PostgreSQL tests pass on the separate local server.
Remote CI is green. This PR does not claim a measured staging speedup.

- The [first CI browser
shard](https://github.com/paperclipai/paperclip/actions/runs/41162257463/job/124422204506)
failed during company cleanup after its task assertions and empty-run
check passed. Company deletion hit the
`activity_log_company_id_companies_id_fk` constraint. The fixture uses
paused process agents and reported no runs. The one failed-jobs rerun
passed all 45 browser tests. All CI checks are now green.

## Risks

- Four checks can use more database connections than serial recovery.
The limit applies to this queue only; the batch limit stays at 25.
- The shared helper has more dispatch logic. Its default remains serial.
Tests cover task order, retry deadlines, drain and waiting for active
checks during shutdown.
- This improves reply recovery under backlog or lock contention. It does
not establish a target for total agent-turn latency.

## Model Used

OpenAI Codex, based on GPT-6, with code editing, tool use and local test
execution. This session does not expose a more specific model ID or
context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 07:39:53 -05:00
DottaandPaperclip 492d537340 fix(native): recover controllers across webserver replacement (#18343)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native execution runs in a remote Runner while the webserver owns
its controller.
> - Encrypted PRP checkpoints and session snapshots already survive a
webserver restart in Postgres.
> - Ordinary warm and per-turn admission still needs local markers and
supervisor metadata to find that state.
> - Replacing the webserver with an empty native controller directory
can therefore lose a usable retained session.
> - This change adds bounded recovery metadata to the existing snapshot
transaction and reconstructs local projections from the selected durable
source.
> - The benefit is native execution continuity across webserver
replacement, with the existing ownership and agent lifecycle policies.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Native remote controller recovery and retained-session continuation
during a webserver upgrade.

**Subsystem affected**

server/ — native runtime, checkpoint persistence, recovery scheduling
and internal upgrade reporting. Product E2E qualification also changes.

**Current behavior**

Without both the local PRP marker and supervisor file, normal
continuation can return before discovering the saved Postgres
checkpoint. The snapshot already exists in Postgres, but its local reuse
compatibility envelope cannot be reconstructed.

**Proposed behavior**

Select the existing durable source, validate its identity and ownership,
restore its PRP state and supervisor projection, then use normal
authenticated admission. Missing or inconsistent evidence holds
recovery. It does not authorize fresh provider work.

**Reason and benefit**

A replacement webserver must recover active execution and later continue
its retained session without the old server's native files. This is one
component of deployment continuity. HTTP traffic switching, workspace
storage migration and Railway rollout remain separate.

**Breaking changes**

No new public endpoint, schema migration or database pool. The private
run-profile envelope is additive. Disk-independent rollback also
requires a reader for the staged controller format and compact
checkpoint part; the first production release containing these readers
is the floor. Older file-backed sessions need an owner checkpoint or the
bounded internal importer.

**Additional context**

Related foundations: #17401, #17916, #17254, #14621, #14622. The
implementation contract and open acceptance gates are in [the dated
plan](doc/plans/2026-10-30-native-controller-checkpoints.md).

## What Changed

- Persist a versioned recovery envelope, at most 4 KiB, beside the
redacted session snapshot in its existing transaction. Keep it out of
public run projections.
- Compare frozen admission separately from prepared attachment
instructions during staged recovery, preserving exact
template/identity/authority checks.
- Bound the existing lazy checkpoint pool at three connections after
measured two-slot burst backlog; keep request/renewal capacities and SQL
operation counts unchanged. The tuning is a separate commit.
- Discover and restore the exact selected retained source without local
native markers. Preserve the 32-candidate window, progress barriers and
current authority checks.
- Fence snapshot and result writes. Acquire coordinator, issue and run
locks in order and check expiry after lock waits. Combine snapshot
ownership/read work into one statement.
- Reuse existing recovery deadlines and drain/resume scheduling.
Retained-owner waits preserve the original unstarted run and actual
lease deadline. Stop, ownership and provider-progress fences precede
deferral. Add bounded native evidence reporting, retained-source import
and retention protection.
- Admit a settled warm source with an authenticated idle goal-read
suffix while retaining active-work and mixed-authority holds.
- Permit lifecycle `turn.stop` checkpoints after accepted results under
existing ownership fences. Claim the existing successor coordinator
before retiring the old warm session, and stage shared attachments only
after verified retirement. Preserve omitted isolated-home defaults and
existing fresh skill-selection order during recovery without hiding real
configuration changes.
- Carry the exact durable six-field PRP binding during active recovery
after a healthy warm handoff. Keep the Runner mismatch guard and
preserve opaque attachment IDs.
- Preserve an already verified active or idle warm process during remote
preparation; revalidate its proof/liveness and retain later
authenticated PRP attachment. Ordinary resumed leases retain suspension
checks.
- Drain retained source events under their original authority, reconcile
immutable source accounting and block unknown source tool dispatch
before target work.
- Persist compact staged handoff intent through authenticated adoption
and recover direct/listener command-loss windows without another Runner
or duplicate attachment.
- Rebuild suspended lifecycle receipts for resumed prepared tasks, and
retry missing lifecycle reads after partial PRP materialization without
overwriting contradictory evidence.
- Add normal warm/per-turn diskless continuation coverage, real Postgres
races and SQL-cost checks. Add a reproducible paired load workload.
- Give only the explicit outage fixture a 15-minute provider idle
window, with a red/green catalog regression preserving all production
timing and lifecycle policies.
- Publish the goal-less task-session pointer in the existing
post-acceptance terminal checkpoint transaction, with current ownership,
accepted-result, reset and newer-progress fences. Keep a private bound
receipt so late completion cannot duplicate or resurrect publication.
- Use a retained warm sandbox in the dedicated continuity fixture, and
accept an exact output token followed by an explanation. Keep the strict
identity oracle.
- Extend the explicit Daytona cell to a five-minute active outage and
another replacement after completion. Require retained provider
identity, a new tool receipt and a useful follow-up result. Add an owned
loopback Postgres E2E fixture for hosts that cannot start embedded
Postgres.

## Verification

**Merge recommendation — `fc68584ce6231a02e47ecd743f55b036ccea034f`:
ready for the qualified native-controller component.** Full CI, fresh
review, local application paths, controlled performance qualification
and the strict live Linux/Daytona case pass. Independent resource
cleanup is complete. Broader rollout, browser reconnection and the
unexecuted transport/platform combinations remain integration gates.
Integrated 484 passed full local recursive typecheck/build and ordinary
active→completion→cache-loss→C component qualification. Fresh review
then found a valid attached-wake failure: preparation appends attachment
instructions before the verifier compares execution to the frozen
admission. 9f4 fixes that by separately checking the pre-preparation
admission and exact prepared execution. Both hashes are captured
privately per admission; the full template, identity, configuration and
authority checks remain. Its regression fails before the fix; 36 focused
cases, 42 staged source/target cases and server typecheck pass
afterward. The review thread is resolved. Exact-head full CI passes
([run
41168228822](https://github.com/paperclipai/paperclip/actions/runs/41168228822):
48 successful jobs, one intended skip); the complete `pnpm test:run`
partitions are forced, with the five native suites in the Runner lane.
This is not a claim that an unsharded local command passed. The fresh
exact-head Greptile check succeeds with 5/5 and all six threads
resolved.

The original two-connection database comparison closes **steady PASS and
burst FAIL**. Every relative CPU/WAL/request-p99 gate passes and all
operations/ownership remain correct, but candidate arm 3 drains in
1,015.99 ms and baseline arm 4 in 1,059.67 ms against the unchanged
1,000 ms absolute gate. Those results remain failed. A separate 2→3→4→2
diagnostic reproduces drain times 1,051.57 / 956.79 / 882.02 / 1,065.72
ms: three is the smallest tested passing cap, and the repeated two-cap
failure survives run-order/cache effects.

Separately reviewable `fc68584ce6` changes the existing lazy checkpoint
pool default to three connections. Request capacity stays ten and
liveness two; idle release, shutdown fencing, transaction counts and
pool count are unchanged. Thirteen DB lifecycle/cap tests and DB
typecheck pass. Full recursive typecheck/build pass at exact fc68584,
with the matching server build stamp. The final paired native
feature-cost comparison explicitly uses the **same cap-three policy and
common current DB factory in both variants**; its baseline is
controlled, not the unmodified historical cap-two configuration.
Original gates and workload counts remain unchanged. The one strict
Linux/Daytona case started at 04:40:56 UTC only after both new profiles
passed; it passed on the first attempt with all 49 workflow checks.
Independent cleanup confirms all three owned sandboxes absent, owned
Postgres/controllers/observer gone, VM terminated, root volume absent
and ephemeral SSH key/agent removed.

**Final controlled cap-three qualification: PASS.** Baseline native
implementation `59da15066a` and candidate `fc68584ce6` use the same
current DB factory and checkpoint policy (request/liveness/checkpoint =
10/2/3). Eight 65-second ABBA arms cover 300 controllers and 10,000
historical tasks. All correctness, absolute and 10% relative gates pass;
original cap-two failures remain unchanged.

| Mode | DB CPU µs/op, baseline → candidate | WAL B/op, baseline →
candidate | DB-request p99 ms, baseline → candidate | Maximum drain |
| --- | --- | --- | --- | --- |
| Steady | 542.40 → 554.83 (+2.29%) | 1509.01 → 1558.27 (+3.26%) |
107.11 → 111.90 (+4.48%) | 26.35 ms |
| Burst | 1036.36 → 1063.11 (+2.58%) | 4153.12 → 4317.64 (+3.96%) |
103.736 → 103.841 (+0.10%) | 930.14 ms |

Every matched arm preserves operation/statement/transaction counts,
including 3,900 PRP and 3,900 snapshot transactions. All three actual
pools are included; there are zero lost owners, missed lease deadlines,
dropped operations or errors. Peak Postgres CPU is 18.31%/9.47% of two
cores and memory 614.29/684.42 MiB (steady/burst). The benchmark uses
one Node process simulating 300 controllers; it does not qualify
two-webserver overlap, HTTP latency or hosted capacity. Its observer SQL
contributes to measured database CPU. The original unmodified cap-two
baseline is separately retained as failed; this cap-three comparison is
explicitly controlled.

The exact final-source 8/512/8,192-chunk test also passes: zero recovery
SQL, transactions or changed rows in each text-only interval, zero idle
SQL, seven lifecycle transactions and twelve changed rows per sample.
Existing lease traffic remains separate. The final ordinary managed
application replay passes active recovery, completion, native-cache
removal and C continuation; its UNKNOWN local debug-daemon provenance
and partial instruction-observer limits remain recorded. The live case
uses the attested Linux producer instead.


**Live qualification: PASS, one attempt, no retries.** Campaign
`native-controller-retained-fix-fc68584ce6-ec2-20261031T044055Z` started
04:40:56 UTC on the exact final Linux webserver source; suite definition
hash `12f9bb97823c1537e43f0398e7cddf39890f77bce7b413ca4dfd944f4a30e5d5`.
The existing immutable image and attested Bookworm Runner artifact are
unchanged.

- A was SIGKILLed and its native cache discarded. B started after
300,149 ms, naturally acquired generation 2, authenticated at 316,624 ms
and resumed at 317,682 ms within the original 420,000 ms grace. The same
active run, Runner, provider PID/start fingerprint and one
submitted/started/accepted turn were preserved; one final
result/terminal and workspace finalization completed, with no
retry/recovery action.
- After active and queued completion, B was SIGKILLed and its native
cache discarded again. C received exactly one ordinary task-comment API
follow-up, completed a new tool and produced a useful reply while
preserving native/provider/Runner identities. This closes the earlier
failed post-C gate. A separate C OS-process PID field was not exported;
the physical-PID proof is specifically A→B.
- Four distinct results were accepted and published; all four
finalizations committed at attempt 1, all four accounting-v2 projections
settled, and the task-session pointer advanced to C. The coordinator
independently checked these facts and all 49 canonical checks against
the sanitized receipts.
- Canonical cleanup passed and independent checks confirmed three exact
sandbox 404s plus complete inventory/zero owned remnants, no owned PG or
controller/observer processes, EC2 terminated, root volume absent, and
the ephemeral SSH key/agent removed by 04:54:25 UTC.

Live scope is classic remote Codex warm continuity with non-native
storage dependencies available. Prepared-task completed B→C, full
per-turn application disk loss, browser reconnection, two-server load
and overall Railway/HTTP continuity were not live-qualified here.
Earlier failed campaigns and the original cap-two burst failure remain
failed historical evidence. A report-renderer cache setup failure was
preserved; the normal sanitizer subsequently succeeded with an explicit
cache path and a new output directory, without changing validators.


The repair keeps retained events under their original six-field
authority until persistence and accounting accept them. Unknown semantic
effects stay unresolved. A compact staged target survives source
bootstrap, cached-command delivery and authenticated handoff, including
an uncertain commit response. Direct and same-guest-listener recovery
require the verified original Runner and the exact endpoint. Target
snapshot publication marks readiness in memory, with retirement
coalesced into an existing command write. Headers contain only the
staged descriptor/digest; a prequeue template is written once as a
changed checkpoint part and then recovered from the existing
command/receipt. No second session snapshot transaction, streaming SQL
path, new pool or recurring idle scan is added.

| Current repair gate | Evidence and scope |
| --- | --- |
| Source-tail regression | Real Runner protocol RED reproduced
attachment rejection. Frozen core/transport pass five source-tail cases:
source usage attribution, held persistence/no premature ACK, lost commit
response plus cache loss, unknown semantic hold and accounting rejection
hold. |
| Handoff loss windows | Direct and listener modes pass
queued/prepared/activated/completed boundaries (eight cells), preserving
the actual Runner/provider process. Missing adoption proof and changed
endpoints reject recovery. |
| Compact storage | A 31 KiB attachment grant writes its separate part
once, leaves it unchanged across source snapshots and removes it at
queueing. Headers do not duplicate the grant. |
| Accounting | 21 real-Postgres usage tests and 19 source-binding tests
pass. Recovery hydrates immutable source receipts without resetting
their producer or billing classification; conflicting/incomplete usage
holds. |
| Admission and malformed evidence | Driver 16, staged evidence 42,
restart classifier 27 and source usage 19 focused cases pass. Four
malformed-file regressions pass at d6a7, whose executor is
byte-identical at 484, and server typecheck passes. Full executor file:
990 pass; 16 embedded-Postgres `initdb` setup failures before
assertions, retained separately. |
| Required checks | Exact fc68584 recursive typecheck and build pass
locally, with matching server stamp. Forced full CI succeeds (48 jobs
pass, one intended skip); all PR checks are clean. Maps/token gates pass
for their unchanged source surfaces. Fresh exact-head Greptile is 5/5,
all six threads resolved. |
| Ordinary application path | Exact fc68584 managed component passes
active recovery after natural expiry, completion, native-cache loss and
ordinary C continuation. Production bytes match before/after; temporary
fixtures restored and owned DB/services cleaned. UNKNOWN local
debug-daemon/partial instruction-observer limits remain; the separate
live case uses the attested Linux producer. |
| Producer | Locked Bookworm build from exact 5b7 Rust tree
d03e494217, equal to final fc68584 Rust
source. SHA-256
65b8f8cfdd6099e9ad24f1ca154e8a260777269cc82f6e23c6e6a180c531eaaf;
38,515,328 bytes. Actual Debian 12 execution and live admission pass.
Controller/admission/DB changes do not relabel the producer source. |
| Historical cap-two comparison | Exact 59da baseline vs 5b7 candidate,
300 controllers/10,000 history, ABBA 4×65 s per mode, all three actual
pools and real snapshots. Steady CPU/op 541.36→554.64 µs (+2.45%);
WAL/op 1512.13→1560.99 B (+3.23%); DB-request p99 102.78→105.99 ms
(+3.12%): PASS. Burst CPU/op +4.71%, WAL/op +5.29%, p99 −0.10% pass
relative gates, but absolute drains above fail. Identical operation/SQL
counts, zero lost leases/drops/errors. One Node process simulates 300
controllers; this does not qualify two-webserver overlap or HTTP
capacity. |
| Live acceptance | Strict final-source Linux classic Codex case passes
1/1 on attempt 1, all 49 checks. Active recovery within grace and useful
retained C continuation succeed; four
accepted/published/committed/settled outcomes. Independent provider,
PG/process, VM/root and SSH cleanup complete. Prepared/task and broader
rollout limits are explicit above. |

**Historical qualification snapshot through `9eb9ac6`.** The head at
this snapshot was `9eb9ac6f9e312f3ebe8040f5a7565e88ae8824f3`. Server and
Runner package sources are byte-identical to `283e05ffaa`; the two later
commits change the explicitly scoped qualification and its documentation
only. It includes master through the storage-owner fix
`45a3a92e6dc52d20923b9aa34a22fee2ec5443f9` (#18357). At that snapshot,
CI/review passed but the strict post-C native recovery gate failed; the
PR stayed draft and required another native repair. Prior `39a4343` CI
and review passed, but its full live workflow failed; that grade remains
unchanged. The first repaired `435ccd2` live attempt failed before any
injected outage. It exposed a legitimate terminal snapshot before result
acceptance; no accepted result ID or publication receipt was observed.
Its canonical report remains 0/1 `candidate_failure`, with cleanup
passed and independent provider absence confirmed. `0862062` defers
publication until result acceptance and fixes the fresh review's
coordinator/issue lock-order finding. Both failures have deterministic
real-Postgres regressions. The `0862062` live attempt then proved
accepted-result publication but failed active recovery: a resumed-lease
preparation guard demanded suspension after the exact live Runner was
already verified for adoption. `64c0b746` preserves that verified
active/idle-warm process, revalidates its proof/liveness, and keeps
ordinary suspension checks and later PRP authentication. Its live run
passed preparation but exposed a second active-warm boundary: all
durable binding fields matched except opaque turn/item attachment IDs,
which the server had regenerated. `7a203274` carries the complete
verified six-field binding and keeps the strict Runner mismatch guard.
Its cloud case then passed active adoption, completion, publication and
accounting. The queued continuation exposed accepted-result retirement
writes and an implicit-home fingerprint drift; both are fixed with
deterministic regressions in `39a4343` before this fresh full
qualification.

The prior live case exposed a real publication gap. A goal-less native
turn could persist its accepted result and terminal snapshot before
provider cleanup, while the task-session pointer was still empty. Normal
later admission then selected a fresh session. The fix publishes that
pointer and a private bound receipt in the **existing post-acceptance
terminal checkpoint transaction**, before cleanup. Earlier terminal
observations persist without a handled receipt or continuation pointer.
No result-acceptance or snapshot transaction was added. The late
completion path recognizes the receipt. This also prevents a late
callback from restoring a pointer after a user reset. Goal/control
publication keeps its existing owner.

The dedicated Daytona fixture now uses the existing warm/reusable
environment. Its sandbox, Runner and provider storage must survive. The
former generic per-turn fixture disposed the sandbox after completion
and kept provider-history backup bytes under the discarded directory.
Whole per-turn disk-loss acceptance therefore has a separate
provider-backup storage dependency. It remains distinct from the passing
native per-turn component checks with backup storage available. The
60-second lease, 300-second outage and 420-second grace are unchanged.

| Gate | Current repair evidence |
| --- | --- |
| Assembled regression | Baseline fails with an accepted result and
terminal snapshot but a NULL task pointer while real provider cleanup is
held. The fix passes normal continuation and reset cases, with no
pointer seeding. Exact merged `92b7447` passed 2/2 twice, including
after normal package TypeScript output refresh. Production files are
byte-identical at frozen `435ccd2`. |
| Persistence and concurrency | 19 helper/transaction cases and all 59
existing control-port cases pass on `0862062`. They cover bound result
IDs, reset/newer epochs, Stop, lock waits and expiry, receipt replay,
missing stubs, foreign bindings and atomic 4 KiB rollback. Existing
snapshot transaction count stays one. The new tests reproduce the exact
live missing-result-ID error and the inverse replay/status lock order
against `435ccd2`, then pass after the correction. Replayed results
still reject stale generations. |
| Completion | All 32 completion-boundary tests pass on merged
`92b7447`; the source is unchanged at `435ccd2`. Native result-shaped
session metadata is preserved. |
| Qualification fixture | A valid review report reproduced three
rejected correct replies. Exact token-boundary matching fixes them. 140
focused E2E/catalog cases and Product E2E typecheck pass. Wrong tokens,
marker prefixes/suffixes and wrong authors remain rejected;
retained-identity checks are unchanged. |
| Required checks | Full recursive typecheck and standard build passed
at `435ccd2`. Both exact commands also passed on `0862062`, with its
exact server build stamp; both also pass on `7a203274`, with its exact
server build stamp. Fresh `0862062` Greptile passed 5/5, with zero
unresolved threads. The `64c0b746` normal CI then passed all 49 jobs (48
success, one expected skip) and Greptile passed 5/5 with zero unresolved
findings. The `7a203274` normal CI also passed 48 jobs with one expected
skip, with fresh Greptile 5/5 and zero unresolved findings. Current
`39a4343` recursive typecheck and standard build both pass with
persisted exit codes and its exact build stamp; fresh Greptile is 5/5
with zero unresolved findings. Its normal CI completed successfully: 48
jobs passed and one expected job skipped. The fresh live result remains
separately failed. The `0862062` normal CI had 46 passing jobs, one
expected skip, one worker communication failure and its aggregate
failure; GitHub states the self-hosted runner lost communication. No
failed assertion or specific OOM/spot cause was established, and no
blind retry was used. |
| PostgreSQL supplement | One corrected all-pool pair at the preceding
repair passed 300-controller/10,000-history correctness and absolute
gates. SQL 76,590→75,990; transactions 9,013→8,713; UPDATE rows 11,613
each; 300 correct pointer writes each. PG CPU 31.99→30.46 s, WAL
70.36→67.87 MB, request p99 100.98→103.12 ms. This is one pair, not a
repeated improvement claim or an exact `0862062` CPU measurement. Its
two later changes defer premature publication and reorder existing
locks; they add no transaction, stream/idle writer, pool or timer. The
first collapsed-pool attempt remains invalid and retained. This is not
an exact final-head CPU/WAL measurement; later fixes change ordering,
identity selection and in-memory skill replacement without adding
snapshot transactions, pools, stream writes or idle SQL. |
| Live publication proof (`0862062`) | Baseline run
`06fcc806-f186-4190-9b57-087b61d75533` accepted result
`58f912dc-94d9-4b4d-bd3d-d5f689c83fd3`; the publication receipt names
the same result, the task pointer has parameters and `lastRunId`
matches, and the normalized native identity matches the following active
run. Accounting v2 settled. |
| Active recovery (`0862062`) | **FAIL.** SIGKILL/cache discard at
23:07:28.666 UTC; hold 300,000.859 ms; B ready at 308,896.486 ms;
natural generation-2 ownership at 312,906 ms. At about 319 s,
preparation failed `runner_harness_state_mismatch:
resumed_not_suspended`. No authenticated after-receipt passed within 420
s. Exact original Runner PID 668/start/fingerprint was independently
still alive; provider auto-stop was 15 minutes. No retained C follow-up
qualified. Canonical 0/1 `cleanup_failure`/cleanup-failed report remains
failed; subsequent independent cleanup deleted all three owned resources
with exact 404s and confirmed full intended-account inventory with zero
owned resources. |
| Verified adoption preparation (`64c0b746`) | 91 focused cases pass,
including actual preparation for four active providers and a distinct
prior/current warm proof. Unproved resumed state, dead process and stale
warm owner remain rejected. The earlier options-only fixture missed this
gate. No spawn, backup restore or PRP-authentication bypass was added.
Server typecheck passes. |
| Active warm identity (`64c0b746`) | **FAIL.** B claimed generation 2
at 312,995 ms. Preparation passed, then strict PRP recovery rejected the
generated attachment IDs at about 319 s. The saved and desired Runner,
lease, normalized session and run IDs matched; only
`turn_attachment_…`/`item_attachment_…` differed from generated
`turn-<run>`/`item-<run>`. Canonical 0/1 cleanup-failed report remains
failed; independent cleanup confirmed deletion/404s and zero owned
provider resources. |
| Six-field identity repair (`7a203274`) | Actual server-factory
regression RED4→GREEN38. A real Rust Runner test passes healthy first
run → random-ID warm handoff → held active second run → restored
controller. It verifies a new live authenticated connection, exact
identity, same Runner/provider OS identities, no duplicate launch/turn,
and no redispatch or invented receipt for an uncertain tool. The
synthetic wrong pair still fails the unchanged guard. This protocol case
does not claim business completion. Server and Runner typechecks pass. |
| Active recovery/completion (`7a203274`) | **PASS for the active
component.** Full five-minute SIGKILL/cache-loss hold. B ready at
308,936.651 ms; natural generation 2 observed 312,979 ms; authenticated
at 317,720 ms and resumed processing at 318,527 ms. Same run
`1e1ccb00-0728-4935-97da-57562d81cb42`, Runner
`246f73f7-a689-4177-a9c2-7ce711d63aed`, remote PID 669/start
23:48:27.470, provider lease/session and one submitted turn. Accepted
result `49097529-5310-4ac3-af95-5bf9b91d19f4`, publication, finalization
and accounting v2 all settled. |
| Full workflow (`7a203274`) | **FAIL, preserved.** Queued
late-requirement run `5e61f38d-c7d1-4fc1-bcbf-bce9d46ce4eb` failed
`runner did not durably suspend before checkpoint` before outage 2.
Canonical 0/1 candidate failure, cleanup passed, evidence valid. C
retention was not exercised. Independent provider absence,
controllers/PG cleanup, EC2 termination and root-volume absence all
confirmed; closed receipt SHA-256
`676a3b15eb9937b6bf995c36fb8666c88964d509e5ceb9109fb02da0aa2bc909`. |
| Retirement and stable configuration (`39a4343`) | Real Runner +
Postgres RED reproduced the exact suspension failure and nine owner
rejections. `turn.stop` is now lifecycle checkpoint maintenance under
unchanged owner/result/generation fences. GREEN25/25 proves actual
persisted suspension, exact identity and completed stop/drain/suspend;
unaccepted, foreign, stale and new-work negatives remain rejected. Two
default-home fingerprint REDs become GREEN9/9; explicit mode changes
still invalidate. No global matching exemption or historical fingerprint
rewrite. |
| Fresh full Daytona warm cell (`39a4343`) | **FAIL, preserved.**
Launched 00:15:29 UTC with automatic retries disabled. Active adoption
passed: actual offline hold 300,000.848 ms; B ready 309,922.155 ms;
natural generation 2 at 311,821 ms; authenticated 317,989 ms; resumed
330,440 ms. Same run `3e126819-e786-4b3b-b923-c975cf4f5b79`, Runner
`4079138a-8d7c-44a4-8558-07a5411d1f55`, PID 668/start and
provider/session identities. Accepted result
`08e504af-4dec-48a8-bf05-bf0a32280559` and publication passed. Queued
run `31d168c9-7ab9-4700-abb6-fafb90912237` failed the same strict
suspension error before outage 2. Its row selected a new native
identity, but no new third provider process or invocation was observed.
Recovery-time configuration still reset only `adapterConfig`; native
provider, context and workspace subtrees were unchanged. Canonical 0/1
candidate failure, evidence valid, normal cleanup passed; all campaign
provider/PG/process resources independently absent. Closed campaign
receipt SHA-256
`5e7d6281c13c812f3a946667f97f3c7d339b5ad86a3a819bd185b2fa73bc4a19`;
EC2/SSH remain temporarily held for the concrete follow-up repair.
Original 60/300/420-second limits and strict queued/second-replacement
checks remain unchanged. Direct-process path; no new live prepared-task
claim. |
| Native retirement authority (`283e05ffaa`) | Exact `39a4343` facade
regression RED3→GREEN9. The successor now uses its existing production
coordinator claim and prompt renewal before strict retirement. A real
Runner/Postgres case starts in the actual native-observed/unclaimed
phase, claims through production code, then closes and durably suspends
the predecessor in 1.657 s. All 25 real-Postgres cases pass;
unclaimed/foreign writers remain rejected. Shared attachment staging
stays after retirement; Stop and denied claims neither close nor stage.
No new claim or SQL path was added. |
| Configuration continuity (`283e05ffaa`) | Real shared/project-primary
environment selection → configuration with four skill versions
reproduces `reset: true`, changed category exactly `adapterConfig`,
after a Postgres JSONB read. Pinned restoration had reordered the
generated preference while actual runtime skills stayed identical.
Replacing existing pinned rows in place preserves the original fresh
name/key order and fingerprint. The assembled regression passes, as do
three existing pinned-version/rename/alias cases and server typecheck.
Genuine model/skill-selection changes still invalidate. No
fingerprint-format change or broad compatibility exemption. |
| Final production repair (`283e05ffaa`) | Full recursive
typecheck/build and [normal
CI](https://github.com/paperclipai/paperclip/actions/runs/41151145106)
PASS: 48 jobs plus one expected skip. Fresh review 5/5, zero unresolved
threads. Live baseline, recovered run and queued continuation all
succeeded, each accepted/published/committed once with accounting v2
settled. Their native/provider identities and configuration fingerprint
match; both recovery and continuation report no reset, no changed
categories and task-session reuse. Active outage/authentication remains
within original timing. |
| Browser-dependent continuation (`283e05ffaa`, definition 6) | **Whole
cell FAIL, preserved.** After B was killed at 00:46:38.928 and its cache
discarded, C became ready in 9,151.410 ms. `openParent()` then hit a
30-second `page.goto`/DOMContentLoaded timeout before posting the final
request. No fourth native run or C continuation was exercised. Cause of
navigation timeout is unknown. C task had no execution lock, queued
comments, handoff or recovery blocker; all three prior runs were
committed/accounted. Normal cleanup passed; independent provider
absence, controller/PG cleanup, EC2 termination and exact root-volume
absence confirmed. Sanitized report bundle SHA-256
`2a3b841d62efb2ae30ef14f96a431ac4fa7fe3a782f1144831512f78edc65022`. |
| Native API continuation qualification (`9eb9ac6f9e`, definition 7) |
**FAIL, preserved.** The real post-C API request dispatched run
`c71fbb18-f979-4fe4-93ce-9c4be46dbf21`, which failed
`native_session_interrupted` / `native_session_recovery_failed` at
01:10:00.640 UTC. It selected the same normalized native identity,
Runner and checkpoint-provider identity as the three succeeded turns. No
C result was accepted; pending accounting remains explicit. Active
recovery passed: actual offline hold 300,001.098 ms, B ready 308,335.019
ms, natural generation 2 observed 311,818 ms, authenticated 315,540 ms,
resumed 316,612 ms. Queued continuation succeeded/accepted/published. B
was then killed/cache discarded at 01:09:34.500 and C ready in 8,783.803
ms. Original classifier `transient_infrastructure`, whole-case failure
and cleanup passed are unchanged; that classifier does not establish the
root cause. All owned provider/PG/process resources, EC2, root volume
and SSH agent independently absent. Closed receipt SHA-256
`7f21ac4a22efc07b849fa7e17866083b6127b3321af12671b4fc054ce57039a9`;
sanitized bundle
`71ffef14a30a553e008320a31840a6d6c0de85c1bfdb60f783fdb53a6aae812a`.
Exact backend detail is unavailable in approved structured evidence. |
| Current required checks (`9eb9ac6f9e`) | Recursive typecheck, standard
build and exact build stamp PASS. [Normal
CI](https://github.com/paperclipai/paperclip/actions/runs/41152908417)
PASS: 48 jobs plus one expected skip. Fresh Greptile 5/5, latest edited
summary checked, zero unresolved threads. Exact8/512/8,192 stream probes
again report zero recovery SQL/transactions/rows and settled-idle SQL;
seven control transactions/twelve changed rows each, with 36 separate
legitimate renewals in the longest case. CI success does not supersede
the failed live C gate. |

The completion supplement observed secondary request/liveness/checkpoint
transaction p99 increases of 23.0%/45.7%/15.6% in its single pair.
Renewal p99 stayed below 0.865 s, with 900 successful renewals per arm
and no lost leases. The named pool caps stayed 10+2+2. An aggregate
activity sample peaked at 15 non-observer entries without backend-type
classification, so no claim is made that all were client connections. No
sampled lock episodes does not establish zero lock waits.

Twelve pure reader/selector cases also pass with the new adjacent
receipt. This is not another executed process rollback. Development
reader `5cf7aead` can parse the recovery state, but its old run-detail
redactor can expose receipt IDs/outcome to an authorized run reader. The
first production release containing recovery readers, complete
attachment-identity handling and both private-field redactions is the
rollback floor. The implicit-home fix prevents new recovery-time
fingerprint drift; it does not rewrite previously stored fingerprints
from failed candidates. The development probe is not a published
supported rollback target.

Latest actual `0862062` Runner tests independently passed 8/512/8,192
text chunks with zero recovery SQL, transactions and changed rows, plus
zero settled-idle SQL. All three observed seven setup/control
transactions and twelve changed rows. The 8,192-chunk case separately
recorded 31 legitimate lease-renewal statements, with no lost lease.
These are component SQL observations, not a production CPU/WAL claim.
The new adoption and identity branches affect recovery preparation only.
The `64c0b746`, `7a203274` and exact `39a4343` CI independently passed
all three stream sizes with the same zero-SQL/idle result; each latest
8,192-chunk case recorded 36 separate renewal statements. Exact
`39a4343` Runner 2/2 passed 133 files / 2,317 tests plus two skips; its
separate native group passed 150 tests plus eight skips.

The first API fixture revision omitted the mandatory final screenshot;
this was caught before paid launch and allocated no provider/model work.
The correction captures the actual retained Chromium page with an
explicit unqualified-browser label, without changing the standard report
validator.

Automatic approval review rejected exporting raw private API/workflow
snapshots because of sensitive payloads and insufficient
destination-specific authorization. Sanitized reports and
bound/hash-only receipts are retained; raw snapshots were not copied
through another channel. This does not change the failed grade.

Repair characterization also preserves its failed attempts. An
unconditional staging relocation broke three existing same-scope
scripted cases; the final implementation defers staging only for an
actual superseded warm scope, and all nine order/race cases pass. One
baseline transform overlapped an edit and is explicitly invalid; the
actual immutable `39a4343` loader then produced the three genuine REDs.
The independent task-directory hypothesis produced a RED but was
excluded by the live shared-workspace evidence; no directory policy
change was landed. A shared-workspace fixture authorization omission was
corrected separately from the four-skill semantic RED.

Setup failures are retained separately from semantic outcomes. These
include an old host port after the owned Postgres fixture restarted and
a sandbox-denied TSX IPC pipe. The supported external-Postgres run
passed, and the final exact recursive typecheck passes with normal
process permissions. Seven stale declaration errors after the master
merge cleared after compiling the actual merged SDK/Runner TypeScript
sources. No declarations were edited by hand.

<details>
<summary>Earlier qualification measurements and failed attempts
(historical, before this repair)</summary>

**Historical blocked gate (before the repair below).** Final native
implementation is `abed921e12d543b62f57a56435419c0dafb0bc33`; current
branch head is `af9e2d157dcc349e55374ad186c9be2d6cb96bf9`. The two later
commits change only qualification fixtures, their matcher and
documentation; `server/` and `packages/` are unchanged. It includes
master through `fd008979f5794fda3d5f54151d36acd31d0de140`.

The live Daytona measurement proves five-minute active recovery,
once-only completion and accounting, but **fails retained-session
identity after the second replacement**. The saved checkpoint and
recovery metadata exist. The task-session pointer remains empty, and
ordinary admission creates new native/provider sessions. The exact
skipped publication boundary remains unproven. A useful saved-file
result alone does not satisfy retained-session continuation. This
application-path gap blocks merge independently of CI.

A separate new-master CI failure is owned by the storage workstream (fix
in #18357). No storage guard, session-identity oracle, lease/grace limit
or provider result was relaxed.

| Gate | Observed result and exact scope |
| --- | --- |
| Distinct source recovery and compatible rollback | PASS at A
`5cf7aead09a2d9c7e2f2929d761f535ef3c1d798` → B
`5ea45f8d17e33c9a62bd79982dcf0375b07733d0` → fresh B → A. Four
controller processes, natural 60-second lease expiry, absent native
projections before replacements, three succeeded/committed unique
results, one provider thread, unchanged Runner identity, and strict idle
cleanup. 177.782 seconds. |
| Immutable installed native component | PASS at installed A
`5cf7aead09a2d9c7e2f2929d761f535ef3c1d798` → installed B
`eaef0d56552c087aaa4fa68a8655282ffbd12667` → fresh B → A. Each
controller imports its contained compiled server and DB. Three unique
committed results, stable Runner/thread, no extra provider restart on
same-contract rollback, strict cleanup. 106.672 seconds. This is
compiled component proof, separate from full CLI-native application
acceptance. |
| Normal public CLI startup | PASS for B
`eaef0d56552c087aaa4fa68a8655282ffbd12667`, Node 24.22.1, darwin-arm64:
fresh external DB, 415 migrations, health ready, root HTML 200, company
POST 201 plus GET readback. The installed tree remained unchanged after
execution. |
| Five-minute component outage | Actual controller absence 300,168 ms.
Natural generation-2 claim at 407.196 seconds after crash, same provider
attempt and Runner, original run succeeded/committed. The larger
540-second case timed out before its retained follow-ups, so it is an
active-adoption pass, not a complete four-controller pass. The complete
short source/installed cases above independently cover follow-up and
rollback. |
| Drain/resume review regression | Fixed in
`226f03e736d1ee99fea1762ab32ea3a8a9241c20`. Five facade-level cases
pass: overdue normal/restart waits, future timer cancellation, another
facade resuming the original owner, and transient retry. Against exact
prior scheduler `5ea45f8d17e33c9a62bd79982dcf0375b07733d0`, four fail
and one passes. The later head changes documentation only. |
| Final corrected-fixture Daytona | **PARTIAL: active recovery PASS;
retained identity FAIL**, exact live source `0b6afc499f`. A was
SIGKILLed and native cache discarded; actual offline hold 300,000.375
ms. B was ready at 308,326.961 ms, naturally claimed generation 2 at
312,059 ms, authenticated at 315,996 ms and resumed processing at
316,519 ms, within the original 420-second boundary. The same run,
Runner PID/start, session, lease and event prefix survived; one turn
submitted. Original execution succeeded and settled accounting. After
completion, B was killed and its native cache discarded; C was ready in
9,077.779 ms. C executed the saved project and returned correct
`queue_r`, with all four runs succeeded/accounted. However, native and
true provider-session identities changed: the unchanged retained oracle
fails. No whole-workflow pass is claimed. |
| Prior matched-producer Daytona | FAILED at exact `abed921e12`. The
matching current-source Runner passed normal admission, completed the
first task and settled its accounting. During the active revision, A was
SIGKILLed and its native cache discarded. Actual offline hold was
300,000.727 ms; B was ready at 308,304 ms and naturally claimed
generation 2 at 309,651 ms. At about 318 seconds, the remote process
check reported `process_not_running` for the original admitted Runner.
No authenticated after-receipt or retained follow-up passed. The current
failure is preserved; no automatic retry, lease/grace relaxation, debt
edit or provider replay is used. Bounded forensic read found preserved
exact-bound state with no recoverable failure, a transport-reset
diagnostic and no terminal delivery; this supports external process loss
without proving the exact cause. The sandbox had a five-minute auto-stop
policy, conflicting with the required surviving-sandbox assumption.
Owned cleanup precedes the separate corrected-fixture case. |

**Live retained-session boundary.** Prior completed run `3806…` and C
follow-up `8adf1df3-6744-40bf-b35d-100451f29d9f` both have database
session snapshots and `nativeControllerRecovery`. Their tool
fingerprint, provider configuration, workspace descriptor,
runtime-context digest, driver and work mode match. There is no recorded
force-fresh/workspace-selection change, and this is an ordinary task
rather than a conversation-generation reset. The same issue/agent
task-session row has `session_params_json: null` and `last_run_id: null`
from baseline time. Both native normalized UUID and actual provider
session/thread hashes differ after C. Full application admission
therefore did not select the retained source. No fallback to file
execution or relaxed identity comparison is accepted as proof of
continuity.

**Independent cleanup completed.** Full current-account provider
inventory confirms no resources owned by either final fixture, with
exact-ID absence checks. Owned controllers and campaign Postgres are
stopped/removed. EC2 `i-01551c09af098dde5` is terminated, its
delete-on-termination root volume returned `InvalidVolume.NotFound` at
22:14:08 UTC, and the temporary SSH key/agent were removed. The
canonical failed report and immutable oracle input are retained. Closed
qualification receipt SHA-256:
`b4b5fefce287ebfdbf2cc2238efaad62d8ad485aed0e9c0628ae95dbc18a8575`.

**Original measurement and grader repair remain separate.** The C reply
contains the requested marker followed by a newline and the correct
output. The old workflow waited for one literal space, so its normal
receipt collection stalled; that original attempt was closed and its
canonical `cleanup_failure`/interrupted result is preserved. Commit
`af9e2d157d` repairs only this reply predicate, with 144 focused cases,
E2E typecheck, discovery and diff checks passing. Ordinary string
matching stays literal. The corrected predicate accepts the saved reply,
but the unchanged retained-identity oracle still fails. Pure
active-recovery grading of the captured measurement passes 7/7; this is
not a rewritten passing campaign.

The sandbox idle-window conflict was corrected only for this explicit
fixture (15 minutes). Actual baseline and later sandbox metadata confirm
that policy; the original active box was disposed before a post-gate
policy read, so its 15-minute setting is established by the normal
create/environment configuration rather than an after-read of that box.
Production native lifecycle and the 60/300/420-second constants remain
unchanged.

The development compatibility reader A is a genuine backport commit
based on `59ff89a18fe1312b5f0bb908439bbdb1237b0252`, with the required
idle-goal reader fixes. It is not a previously published release. Its
older executor differs from B. The rollback floor must include this
reader capability. The source component cases admitted the Linux ARM64
Runner packaged at `59ff89a18fe1312b5f0bb908439bbdb1237b0252`; the
installed component case admitted the `5cf7aead` package. Their Runner
bytes are identical: SHA-256
`b1f04caa1ce04e720dec7eb62ede170eb3621948c0849b8f305ea5c5116bced8`. Each
admitted artifact remained unchanged throughout its case.

[Final public package
build](https://github.com/paperclipai/paperclip/actions/runs/41121460635)
and [reader-floor
build](https://github.com/paperclipai/paperclip/actions/runs/41122170506)
both passed all four daemon builds, package assembly and both Darwin
clean consumers. Both Linux ARM consumers failed before provider work
with the same existing local Codex permission-profile error: bubblewrap
attempts `activity.fifo/.git` and reports “Not a directory.” This
matched baseline failure remains open; it is not a native remote
continuity pass. Full post-run tree and build-stamp revalidation also
passed after the compiled native case. The installed component trees are
A `c29114c1bf71c5af00f761aeb9e3d84ed3d3075b9f5600dee3ef2543eb2b6ec5` and
B `eda575505373a3bdc630fa4919862b359791fe3a7ef637961a25b73b38efe4b0`.

**Controlled PostgreSQL qualification passed.**
Baseline/candidate/candidate/baseline workloads used 300 controllers,
10,000 historical tasks, real snapshot/encrypted PRP writes and
unchanged pools. PostgreSQL and client were each limited to two CPUs and
1536 MiB on an isolated eight-vCPU Linux host.

| Workload | PG CPU per operation | WAL per operation | Database request
p99 |
| --- | ---: | ---: | ---: |
| Steady | +1.18% | +1.81% | +1.91% |
| Aligned burst | +3.40% | +2.56% | +3.81% |
| Two logical servers | +3.11% | +2.56% | +9.68% |

All arms passed absolute/correctness gates with unchanged control
transaction counts, no dropped operations and no owner loss. Overlap p99
has little margin below the relative threshold. It uses two clients in
one Node process, not two HTTP servers. [Closed measurements and
limitations](doc/plans/2026-10-30-native-controller-qualification-evidence.json)
and exact-source reproduction patches are retained. [Earlier
contended-host
failures](doc/plans/2026-10-30-native-controller-load-evidence.json)
remain unchanged. The production DB-claim probe claimed 300 owners in
2.84 seconds and restored/committed controls and snapshots in 8.74
seconds, with zero owner loss or settled-idle SQL; its provider
references were synthetic. The measured checkpoint/snapshot/renewal
paths retain the same persistence behavior after integration; later
accounting and business writes have separate owners.

Actual Runner stream tests at `da8c7f6e1837ddd896dfe83a7524812fee813487`
passed 8/512/8,192 chunks: zero recovery SQL, transactions and changed
rows during text intervals; zero settled-idle SQL. Each retained seven
control transactions and twelve changed records. Existing renewal SQL
was measured separately. The guard/scheduler fixes add no stream path,
pool or recurring idle scan.

The live fixture used current-source producer SHA-256
`f0000c90cb83880191479da639201e659aa6ce0fc7d67c859faa172ec977849e`, a
normal locked exact-head build with pinned Rust 1.97.1 in Bookworm.
Actual network-isolated, read-only ABI execution passed (GLIBC
requirement 2.34 against runtime 2.36). The immutable base image
remained
`ghcr.io/paperclipai/paperclip-daytona-runner@sha256:36069788f53c51f228764fa36180575443dfb5d1f84a342d7c0daceb28dc61cc`,
source `a0ef3ce7`. This was an unpublished development producer,
explicitly distinct from the base image and admitted before the fresh
fixture began. The earlier host build failed ABI preflight before
admission. The preceding old-producer fixture completed its initial task
but lacked the usage-basis marker required by current master; it
remained pending/unpriced and correctly paused. It was independently
cleaned without debt or budget changes. Two preceding local Linux setup
attempts OOM-killed before provider allocation, and their cleanup
passed. These attempts remain separate from the final recovery failure.

**Failures retained and resolved separately.** The earlier `98f05fc`
probe rejected a valid settled PRP v2 goal suffix; `eaef0d5` fixed that
reader and the fresh follow-up passed. Later component cleanup failures
were traced by a scoped exception observer to the fixture adapter
rejecting directory downloads. A bounded owned-directory transfer with
exact-byte/mode preflight corrected the fixture; source and installed
strict-cleanup cases then passed. No production guard was relaxed. The
initial local integrated control-port run hit its 30-second embedded
Postgres startup hook before executing 59 cases; 18 other focused cases
passed. A bounded rerun used a fresh owned external Postgres fixture,
applied normal migrations before Vitest, and passed all 59 cases with
the original timeouts unchanged. Its container and data were removed;
the failed attempt remains retained.

The additional opt-in full Product E2E Vitest run is not green: 5,313
passed, seven failed and three skipped. An actual `abed921e12` archive
with the same dependencies, Node and IPC permissions reproduces all
seven failures with the same reasons. Five are unchanged
workflow-policy/profile-pin assertions, including Pi profile version 37
versus the test pin 35. Two database suites failed during embedded
Postgres startup before their assertions; semaphore exhaustion is
confirmed in the observer log. The observer passes its supported
external-Postgres rerun with original timeouts and source unchanged. The
controller-database client-kill/postmaster assertions remain unexecuted
after `initdb` bootstrap failure; no external override is supported. The
unit launcher stopped before its Node-test phase, which was then run
independently and passed 181/181. The original failed full run is
preserved. These results remain distinct from the passing focused checks
and normal repository CI. The first local Product E2E typecheck also
encountered stale compiled Runner declarations; a genuine package-local
TypeScript compile refreshed them and the unchanged check passed,
without a dependency install or producer rebuild.

Earlier [Daytona campaign
41108162900](https://github.com/paperclipai/paperclip/actions/runs/41108162900)
failed at sandbox creation before any agent, with the underlying
provider error unavailable. Its [sanitized
report](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-41108162900-2/index.html)
remains a `cleanup_failure`. Both old creation names are absent in the
current authenticated account, but the old CI account identity was not
retained, so account equivalence is unproven. The subsequent exact
`eaef0d5` source Product E2E attempt passed image/agent setup and the
initial project, then held the controller offline for 300,003.7 ms. Its
Mac supervisor failed owned-process inspection before B readiness; no
adoption passed. Full current-company lease/label checks, provider
deletion, exact-ID 404s and complete inventory confirmed cleanup of that
attempt. Its local server and owned Postgres stopped. The prior AWS
campaigns and database qualification VM were terminated with root
volumes removed.

The old admitted test Runner lacks the newer usage-basis marker
introduced on master. The integrated component B turns retained
unpriced, incomplete accounting obligations with `costAccountingPending:
true` and no settled charge. The compatibility-reader A turn used its
legacy receipt interpretation but likewise retained pending accounting
and no settlement timestamp. This proves obligation preservation, not a
whole-run accounting migration. Runner/receiver release ordering remains
governed by the usage owner's contract.

At native implementation `abed921e12d543b62f57a56435419c0dafb0bc33`,
Greptile was 5/5 with zero unresolved threads and CI completed with 54
successful checks and five expected skips. At `0b6afc499f`, Greptile
again passed 5/5 with zero unresolved threads, but CI ended with 51
successful checks, five skips and three failures. Server 9/12 fails a
deterministic managed-skills maintenance assertion newly inherited from
master `198218bf` in merge `c80e00ad`; that test is absent from the PR
head, and the storage owner has the explicit-StorageService fix in
#18357. Runner 2/2 passed 2,283 unit cases but its runner received a
shutdown signal during the long stream probe; its cancelled step and
aggregate failure are preserved. No blind retry was used. Current
`af9e2d157d` checks are pending; the matcher-only change passes 144
focused cases and Product E2E typecheck. Earlier scheduling-sensitive CI
failures and the interrupted unsharded local test run remain recorded in
the dated plan. CI runs the repository's normal test partitions. Final
verification does not claim Railway rollout, uninterrupted HTTP service
or whole-webserver filesystem loss.

</details>

## Risks

- The task-pointer repair passes its assembled regression. The first
live repair exposed pre-acceptance ordering and the fresh review exposed
a replay lock-order issue; both are fixed and pass real Postgres tests
at `0862062`. The following live attempt exposed the
verified-running-versus-suspended preparation gate. Its narrow fix
passes 91 focused cases at `64c0b746`. The next live case exposed
synthetic attachment IDs; `7a203274` fixes that field selection and
passes real Runner authentication. The subsequent queued continuation
exposed strict retirement maintenance and a false default-home change;
`39a4343` fixes both with real Runner/Postgres and fingerprint
regressions. The `39a4343` live continuation failed again despite green
CI. `283e05ffaa` repairs the actual native-observed admission ordering
and reproduces/fixes the JSONB skill-order fingerprint drift. Both pass
targeted real-Postgres regressions and the live active plus queued
paths. The definition 6 post-C browser navigation timed out before
admission. Explicit definition 7 now verifies native continuation
through the ordinary comment API; its strict post-C native gate failed
after a real dispatch and remains historical failed evidence. The final
fc68584 repair now passes its fresh strict 49-check Linux/Daytona
campaign; the prior failed grades remain unchanged. Browser reconnection
is handed to its own workstream with the original failed evidence. No
prior failed campaign is reclassified as passing.
- Incorrect checkpoint/source binding or stale ownership could duplicate
external work. Missing evidence remains a hold; existing receipt and
finalization owners keep uncertain effects unresolved.
- Recovery must retain maintenance writes after accepted results without
allowing a stale business turn to write. Real lock-wait and generation
tests cover that boundary.
- The current two-connection paired burst profile fails its absolute
drain gate in both baseline and candidate, despite passing relative load
gates and all correctness checks. A causal capacity diagnostic selected
three slots; the final controlled cap-three profiles pass unchanged
thresholds. Full application replacement and two-server overlap capacity
remain separate. There is no new streaming writer, pool or recurring
idle scan.
- The remote sandbox and Runner must survive the recovery window.
Provider auto-stop is a separate lifetime bound from reconnect grace;
the explicit qualification fixture uses a longer idle window.
- Workspace and provider backup availability remain external
dependencies. This PR does not certify whole-webserver filesystem loss,
uninterrupted HTTP service or a Railway rollout.

## Model Used

Implementation and initial verification used OpenAI GPT-6 through Codex;
the initial hosted snapshot was not exposed. The follow-up qualification
used three OpenAI `gpt-6.1-sol` workers coordinated through Codex, with
repository tools, code execution, CI and scoped test infrastructure.
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 (focused and exact-source
application/cost checks pass; full forced CI passes; earlier local
embedded-PG setup failures remain recorded)
- [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 (exact fc68584 full CI and
auxiliary checks pass; forced complete test partitions)
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(exact fc68584 check and edited summary pass; all six threads resolved)
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 07:33:52 -05:00
DottaandPaperclip 322fa6b65c fix(ui): restore task document authoring and add persistence journey (#18356)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - Task documents keep versioned work beside each conversation.
> - The default chat interface could read general documents but hid
their editor.
> - People also need unfinished edits to survive a tab switch or reload.
> - This pull request restores the shared editor in Artifacts.
> - A portable browser journey checks exact saved content and revision
history.
> - The benefit is a usable document flow with independent deployment
checks.

## Linked Issues or Issue Description

**What happened?**

A person using the default task interface could read a general task
document but could not create or edit one. The existing editor was
available in Classic mode. A pending create could also leave newer text
as a new form after its editor unmounted, causing a conflict against the
person's own successful creation.

**Expected behavior**

A person can create and edit general documents through Artifacts.
Titles, bodies and revision history persist after reopening and
reloading the task. Unfinished text survives tab switches. A successful
create makes retained newer text an edit of that confirmed revision.
Later writes from another actor still cause a conflict.

**Steps to reproduce**

1. Open an ordinary task in the default chat interface, then open
Artifacts.
2. Try to create a general document. The previous interface has no
authoring control.
3. With authoring restored, submit a new document, keep typing, and
switch to Properties before the request finishes.
4. Reopen Artifacts. The previous draft path restores a new form despite
the successful create.

Related public work: #17598 adds document copy/download and #18157 adds
image galleries. The selected actual merged parent is
`f1d780838218f975064f38333946805e0ec103a5` from #18427. It includes the
stable profile-entry ordering repair and the exact recovery-fixture
prerequisite. The resulting PR diff contains 32 document and reporting
files.

## What Changed

- Reuse `IssueDocumentsSection` for general documents in default-chat
Artifacts. Keep Classic authoring in its existing task body. Ordinary
tasks, conversations and Coordinator mode share the same editor options
and signed-in permission wrapper.
- Preserve Plans, file-review documents, attachments, uploads and work
products. Hide duplicate general-document cards. Use the same
general-document key rules for visible rows, validation and refused
writes.
- Forward image uploads, mentions, references, author maps and feedback
to both editor mounts. Keep empty mention/project values stable while
queries load.
- Back up unfinished forms within their signed-in account, task and
editor scope. Preserve text entered before its key. Record a successful
create on its matching retained newer buffer, including after unmount or
an early reopen. Preserve newer title/body edits, real remote conflicts
and matching cancellation cleanup.
- Add the model-free `task-document-persistence` journey. Setup creates
only an owned empty backlog task. The browser creates and edits the
document; normal APIs independently check company, task, actor, exact
content and both revision records.
- Reopen the owned task through the explicit Backlog view, then reload
it. Require exact UI readback and zero native runs. Add only the Doc
registration, definition-hash inputs, report mapping and four closed
checks to the shared harness.
- Count explicit zero-run browser receipts after private journey
metadata is removed for publication. Preserve missing billing evidence,
positive usage and native/protocol accounting.
- Update browser assertions for the restored inline editor while
retaining exact download bytes, revision collisions, paused-state and
no-run checks. Update the feature map, usage docs and shared editor
stories.

## Verification

- Latest focused checks use official Node 24.22.2: 568 journey, catalog,
report, billing and attempt-accounting tests across 25 suites pass. All
four admitted journeys remain registered. The seven relevant UI suites
pass 529 tests, including the task-page container after the parent
merge. Maps, token gates, the PR-scope diff check and the owned
credential-pattern scan pass. The normal QA import preflight also passes
with an empty environment and network access blocked.
- Billing regression: before the repair, the explicit empty public
receipt counted one run, and two positive-usage receipts were discarded
by browser metadata. Those three cases fail before and pass after the
repair. Two additional red regressions cover aggregate usage beside an
empty run list. That ambiguous shape now keeps an unavailable receipt
and a minimum count of one. Missing receipts retain unavailable billing,
and native/protocol one-or-more run totals retain their measurements.
- The previous fresh CI run failed its unchanged snapshot-only recovery
fixture: one global sweep did not call its callback. The original
failure remains recorded. An isolated PGlite probe with all canonical
migrations exercises the real reconciler: it processes two earlier
sources, then reaches the owned third source on the next sweep. It
preserves source evidence, files and run IDs. This proves bounded
pagination, not full native snapshot repair.
- Local native recovery tests could not start PostgreSQL because the
host semaphore limit was reached. That run executed zero cases.
Canonical Linux CI later passed all 143 fixture cases, including the
original snapshot-only case and the new competing-candidate control. The
exact fixture repair is now inherited from #18427 and is absent from
this PR diff.
- The portable oracle rejects 19 stale, missing, foreign or incorrect
outcomes. Result validation also rejects model/provider metadata and
native runs for this case.
- Five real Artifacts-to-Properties unmount regressions fail before the
repair and pass after it. They cover both editor modes, reopening before
and after completion, later typing, and a foreign revision that must
still conflict. The edit-storage failure case also checks that Cancel
clears the promoted fallback copy.
- UI coverage includes default chat, Classic, conversations,
Coordinator, Plan rendering, document-card deduplication, reserved keys,
pending-query stability, permissions and rich editor options.
- Earlier real browser checks passed five upload cases and two
artifact-arrival cases. They retain exact CSV bytes, original/revised
content, collision, paused-state and no-run assertions. Current-head
normal CI runs the updated browser suites again.
- The branch merges only the selected actual parent
`f1d780838218f975064f38333946805e0ec103a5`. The merge has no conflicts
or manual resolution. The SQL service and recovery fixture match that
parent exactly. The own document editor, persistence flow, saved-state
oracle and billing repair retain their previously qualified source
blobs. Follow-up, clarification, question/resumption, screenshot helpers
and the Steering map are byte-identical to the merged parent. Existing
project/search/question/follow-up registrations remain present.
- Required document source blobs remain exact: Doc UI
`22e80663b053363e5f75e1432dd9043dc0e70243`, its unmount tests
`16f3f4ed0dc9b11aaff129e06e6cf2bbf4522713`, readiness helper
`800a747284db19b8484650b6759e8bd1f356839d`, and budget service
`3a15d489f0aa55c22e8f7fe6a6bc6a0e14e5914e`.
- Local typing is limited by borrowed declarations from another
checkout. They omit current `skill_test` and sandbox creation-operation
fields. No dependency declarations or repository config were changed.
The authoritative clean CI Typecheck + Release Registry gate passes on
exact head `2ffce29827ae170420d740940c1c069c7225a74c`.
- Full monorepo typecheck, tests and build were not run locally.
Borrowed build declarations from another checkout limit local typing.
Authoritative [clean
CI](https://github.com/paperclipai/paperclip/actions/runs/41171717008)
passes on exact head `82d15946c5844d3ae41c6ade62fa224053f20a9a`: 55
successful checks, 3 skipped and 1 neutral, with zero pending or failed
checks. Typecheck, build, Runner, server and browser lanes pass.
Greptile gives that same head a fresh 5/5. All 15 review threads are
resolved, with no further thread page. The PR is mergeable and clean.
- Failure history remains recorded. The earlier recovery failure was
repaired with a bounded, owned-source fixture. A later CI worker shut
down after 2,375 Runner unit tests passed. Its one authorized narrow
retry passed those tests and all five native integration suites. The
separate AgentConfig browser failure was reproduced and fixed by the
merged #18427 parent. These earlier passes do not replace current-head
CI.
- Final-source live qualification passed on exact harness and served
application `82d15946c5844d3ae41c6ade62fa224053f20a9a`. QA run
`41177696858` completed all four closed checks and all five phases with
zero native runs. Cleanup passed; the durable manifest is complete with
no pending evidence. The coordinator verified the original grade and
manifest.
- The [public qualification
report](https://pages.paperclip.ing/evals-qa-smoke-41177696858-1/)
records zero agent runs, empty run IDs and empty run usage. Pricing
remains unavailable and billing remains incomplete; the report does not
claim measured zero cost.
- The earlier harness `36c8d9ddd76d0b7ddb28a9a6c674d9e538f6df88` pass
against application `2ffce29827ae170420d740940c1c069c7225a74c` remains
historical evidence. It is separate from the final-source measurement
above.
- The selected parent brings profile-entry ordering, proactive chat, a
database migration, Runner updates, and task-page chat/read behavior.
Its new task-page container is included in the final application
measurement. The coordinator retains the original evidence and owns the
primary merge and daily-plan admission.

## Risks

Artifacts now mounts the existing shared editor. Its autosave, conflict,
revision, annotation and server access contracts remain in place. Tests
cover both interface modes, shared scopes, later remote writes and
unavailable edit storage. Plans and generated file-review documents keep
their existing flows. The PR adds no database schema or API change. The
shared billing repair requires explicit captured empty run IDs and an
unambiguous usage object containing only an empty run list for public
browser-only receipts. Other fields beside an empty list keep
conservative unavailable billing. Missing measurements remain
unavailable. Contradicting positive usage remains counted. The inherited
recovery fixture keeps the production sweep limit and its source,
readback and no-agent-work assertions.

The live journey must fail when authoring controls or saved outcomes are
absent. It must not create the expected document through setup APIs or
switch to another interface to pass. Final deployment verification must
retain the actual app and harness revisions separately.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 01:49:24 -05:00
DottaandPaperclip 59da15066a feat(runner): deliver native Kimi Code (#18391)
Deliver native Kimi Code setup, exact models, scoped credentials, verified packages and runtime packs. Preserve current upstream release attestations and restore verified same-run remote retry dispatch without weakening process ownership.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 22:26:15 -05:00
DottaandPaperclip 100b364264 Preserve selected Google services when setup resumes (#18048)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections control which external services an agent can use.
> - Google Workspace setup lets a person choose services and read or
write access.
> - A draft lost that choice after a declined or expired OAuth handoff.
> - Finish setup could then show all services with write access instead
of the saved narrow choice.
> - This pull request saves the exact draft choice without treating it
as granted access.
> - The benefit is safe setup recovery that preserves the person's
choice and existing account limits.

## Linked Issues or Issue Description

Refs #15545. The duplicate search found no open PR for Workspace draft
consent recovery. Related #18000 concerns satisfied gateway access
requests, not saved OAuth setup intent.

**What happened?**

A cold Workspace draft resumed with the new-account service defaults.
The selected request lived only in short-lived OAuth state. Denial
consumed that state. The picker ignored draft connections.

**Expected behavior**

Finish setup restores the same person's saved service choice. It does
not use another person's choice, a broad profile hint, or a credential
grant as draft intent. An old draft with no reliable choice asks the
person to choose services.

**Steps to reproduce**

1. Start a new Google Workspace connection. Select Gmail read-only. Turn
off Drive and Calendar.
2. Continue to Google, then decline authorization.
3. Close the setup page. Return through Finish setup.
4. Open the service picker. Before this fix, all three services can be
enabled with write access.

**Paperclip version or commit**

Reproduced in tests on master
`820c458465fa40137c81fe510f3e6dc573b4f895`.

**Deployment mode**

Authenticated and local source builds. The source regression uses real
PostgreSQL fixtures and the production React setup components. Live
provider acceptance of this repair is still pending deployment.

## What Changed

- Save validated, non-secret draft intent before managed or
customer-owned OAuth. Bind it to company, connection, actor, grant kind,
and subject.
- Restore that intent after denial, state expiry, and cold Finish setup.
Keep active reconnect bound to its saved grant. Do not change
new-account defaults.
- Preserve agent-to-human setup handoffs. Consume only the addressed
person's reviewed proposal. Keep other people's proposals.
- Lock and merge the current draft before saving intent. Return 409 if
its credential identity or method changed during setup.
- Preserve the latest saved choice across overlapping customer-owned
starts. Merge both current configuration records under short locks.
Reject stale client-binding changes. Keep each OAuth state's own
requested scopes.
- Add shared, service, handoff, picker, and cold-page regression tests.
Update the connector contract and existing feature plan.

- Route the default ungrouped test/release paths through six sequential
exact-cover chat partitions. Preserve remaining server/native coverage,
explicit grouped CI, selection-first execution and shared-database
paths.
- Correct the retention test driver so pending owned real I/O does not
advance logical deadlines. Pump zero-duration connection timers and add
a held-I/O regression; keep production scheduling and original timing
assertions unchanged.

The shared helper is needed by the server and picker to validate the
same narrow binding. It does not resolve credentials or grant access. No
production schema migration, new route, provider scope or deployment
configuration is added. The test-harness changes do not change
production timers.

## Verification

### Current candidate: source qualification passed; live acceptance
pending

- Current published candidate:
`82d13d4d698a5579378b5d506cb7a1f9cb64b5c8`, tree
`78d6a821ce53f481fe3e9991edce56f0acffb22f`. It combines the Workspace
repair with launcher commit `bf29c9` and retention-test commit `e25987`,
then integrates master `493e229d93ba7798e80152f4549e2e9177ce50ae`. The
integration brings 40 upstream commits across 713 files. One launcher
conflict keeps upstream validated CI selection and its selection-first
path, then applies six default chat partitions only without a selection.
The authored PR diff has 16 files, 833 additions and 100 deletions; it
adds no authored lockfile or `.github` changes. The public head is
confirmed at this revision. Fresh CI and review passed as recorded
below. Source qualification is complete using exact-tree full CI and the
local results below. The separate local whole command was interrupted by
host disk protection and is not called a pass. Live repaired-draft
acceptance remains pending deployment.
- Exact clean `82d13d4` passed one Node 24.19.0 builtin-only run: 41/41
cases (37 launcher and four CI-workflow cases), zero failures/skips.
HEAD, tree and relevant file hashes stayed unchanged and clean before,
at start and after. This proves launcher fixtures, not real chat
execution, current typecheck/build, the dependency-backed selection
graph, or full feature acceptance.
- The new default ungrouped whole command uses six sequential
exact-cover chat partitions, then the remaining server suites,
workspaces and serialized suites: 28 expected invocations. It preserves
all native suites, including upstream usage coverage. The plain
ungrouped release launch path also changes. Explicit grouped CI,
validated selection and shared-database execution stay unchanged.
Launcher hard RED had three expected body failures and two unchanged
passes; the repaired focused five and final 37 passed. A later 41-case
staged-merge pass is retained separately; the clean 82 run above is the
frozen proof.
- Fresh [CI run
41153113944](https://github.com/paperclipai/paperclip/actions/runs/41153113944)
completed successfully on October 31 at 01:14:53 UTC. Current head has
52 successful check runs, four conditional skips and no pending/failing
checks; legacy Snyk also passed. The skips are test-file selection, the
optional paired benchmark and two Storybook checks. The full
server/chat/workspace/serialized matrix, all eight e2e shards, normal
build, build-gap typecheck, Runner checks and final aggregate gates
passed. Build and all three chat job logs identify checkout
`e5e831fd3a8534d0d0f1e892118c0f8fbe12dd92`, merging this head into
`493e229d93`. Its Git tree is exactly
`78d6a821ce53f481fe3e9991edce56f0acffb22f`, identical to the clean
candidate. The six real chat partitions passed 314, 358, 273, 239, 321
and 311 cases: 1,816 total. Other cases shown as skipped in each
partition were selection exclusions, not extra passed cases. This is
current tree-equivalent CI proof, not a pass of the separate default
ungrouped local whole command.
- Fresh [Greptile
summary](https://github.com/paperclipai/paperclip/pull/18048#issuecomment-6473856992),
edited October 31 at 01:05:04 UTC, explicitly reviews exact head
`82d13d4` at 5/5 with no actionable code issue. Its exact-head check
passed. The prior overlapping-start discussion is resolved. This review
is source-only, not provider or live acceptance.
- Exact clean `82d13d4` passed full recursive typecheck and normal `pnpm
build` on the independent darwin/arm64 snapshot. Typecheck finished on
October 31 at 01:27:33 UTC; build finished at 01:28:33 UTC. Both exited
0. Normal native preparation and code signing passed. Source HEAD, tree
and tracked/untracked state stayed unchanged and clean. `pnpm
check:token-gates` also passed all token, palette and ClipLab checks on
this candidate. The earlier forced-clone `ENOSYS` preflight remains
recorded as setup failure, not an assertion result.
- The unchanged default `pnpm test:run` started at 01:51:33.796 UTC on
clean exact `82d13d4`. All six real chat partitions passed: 358, 314,
273, 239, 311 and 321 cases, or 1,816 actual cases. The original FIFO
and ambiguous-retry cases both passed under their unchanged 15-second
limits. General-server then reported 37 completed file rows with 5,438
passed cases and five default remote-continuity skips, including all 498
tool-access service cases and all 83 connection-route cases. At 02:39:44
UTC, the unchanged 5-GiB host-disk guard terminated the owned run. The
child ended with SIGTERM and the container/harness exited 143, with no
OOM or recorded assertion failure. Only seven of 28 RUN invocations
started. Retention had no completed local row. Later invocations did not
run. This whole local command is interrupted/incomplete, not passed.
- A coverage check found no default suite missing from current full PR
CI. The maintained launcher tests prove exact coverage for all 12 PR
server shards, chat and five native suites; all configured workspace
projects; and all nine serialized shards. The final Runner CI shard
executes the five native server suites. The 41 local launcher/workflow
cases cover six sequential chat children, per-child isolation, native
retention, fail-fast propagation and unchanged explicit
selection/shared-database paths. The actual six-chat run above exercises
that changed default path. The remaining unqualified local difference is
uninterrupted sequential whole-command composition and resource
accumulation, not omitted test selection. Current exact-tree full CI
supplies broad source-test qualification; no local whole-pass claim or
provider acceptance is inferred.
- A task-owned remote runner was considered to complete that separate
composition check. Its provider rejected the requested allocation with
per-sandbox limits of 8 GiB RAM and 10 GiB disk. No sandbox was admitted
and no remote tests ran. No tests, timeouts, assertions, database
synchronization, source or provider settings were changed to avoid the
capacity limit. Historical a0 failures remain below. No deployment or
live repaired-draft acceptance has run.

### Bounded follow-up on the prior source

- On a0, one finite phase-traced chat diagnostic executed exactly the
two failed cases. Both passed (1,374 and 1,767 ms); 1,814 other cases
were filtered, not passed. This did not reproduce a blocked await or
establish the original monolithic timeout cause. No assertion or
15-second limit changed.
- The retention diagnosis preserved an initial zero-body selector
failure, then corrected only the selector: one original case passed in
783 ms, with 42 filtered. Trace showed the old settling helper advancing
logical time while real I/O was active. A new held-I/O regression then
failed hard because the old helper advanced 1,000 ms. This proves a
test-driver defect, not the precise cause of the old 5,340 ms full-run
gap.
- The first manual-clock repair failed the complete 44-case file: 43
passed, one body hit 15 seconds and cleanup hit 30 seconds. Its planned
mutant did not run. Source then identified a fresh PostgreSQL
connection's zero-duration timer. The corrected driver pumps
zero-duration timers while initial readiness or tracked I/O is pending,
without advancing logical Date. That pre-integration file passed 44/44
with no skips. A separate scratch-only 5,000 ms normal-continuation
mutant failed the original hard `5000 < 3000` assertion; its expected
failure is not a test pass. The original page-count, fairness, expiry
and quiet assertions stayed intact. The authored repair does not change
the production worker. The merged master changes an older retention case
and dependencies; these pre-integration results are not a complete 82
retention or whole-suite pass.

### Historical qualification: SHA-bound, not 82 acceptance

- Historical a0 candidate: `a0f9089fc1ff466bf4e1eeddc5b1a910d09e380b`,
tree `b9d73713319dcd52b9eaa6053008b5190e43fdf1`. It adds the
overlapping-start repair to parent `6c18`, which already merged pinned
master `1511c92965325249ed6b52dd5be52eb6d736fbfa`. That candidate
changed 12 files. Its CI and review passed; its local full qualification
remained failed/incomplete.
- Greptile's previous `6c18` review found P1 [Latest service choice gets
lost](https://github.com/paperclipai/paperclip/pull/18048#discussion_r4425965828),
confidence 4/5. Two hard-assert regressions reproduced it on untouched
`6c18`: the already-bound path overwrote the later choice, and real
first-use client stamping also restored the old choice. Existing OAuth
states/grants were not widened, but a later setup could restore an older
request. The new repair covers both write boundaries without holding
locks over external work or copying another attempt's scopes.
- The complete affected service file passed 498 tests with no failures
or skips. All 31 required controls ran, including both unchanged RED
cases, 14 new client-drift cases, seven earlier identity guards,
reconnect/cold-resume cases and upstream transaction tests. The tested
three-file patch is byte-identical to this commit; the connector
contract update is separate. Independent scoped review found no
additional actionable issue. Fresh Greptile reviewed exact `a0f` at 5/5
with no actionable findings. The previous P1 thread is resolved.
- On exact `a0f`, the five shared/UI files passed 312 tests. An initial
complete connection-management run then failed: 74 passed, eight timed
out at the unchanged 15-second limit, and one AI-account verification
returned 422 instead of 201. The Google addressed-user handoff passed.
The container exited 1 without OOM and stopped before chat/token/whole
tests. This material failure remains retained and its cause
unclassified; the later controlled recovery below is not a causal
explanation.
- One diagnostic executed the first failed gateway case and the two AI
cases with temporary phase-only tracing. All three passed at 8.516,
5.511 and 3.523 seconds; 80 other cases were filtered. Original hard
assertions and timeouts stayed unchanged. No timeout or suspected late
provider cleanup reproduced, so the complete-file failure remains
unresolved. Vitest exited 0; the harness exited 1 because its trace
parser missed ANSI prefixes. All 203 events were recovered from retained
logs without rerunning tests. Instrumentation was removed. This is not
acceptance.
- Historical a0 CI
[41097596364](https://github.com/paperclipai/paperclip/actions/runs/41097596364)
completed successfully: 52 successful checks, two expected Storybook
skips and no failed/pending checks. Legacy Snyk passed. All 48 CI jobs
passed, including all 1,816 chat cases and explicit passing lines for
the original 20 local failures. [Server
11/12](https://github.com/paperclipai/paperclip/actions/runs/41097596364/job/124207469276)
explicitly passed the complete 83-case connection file in 129.49
seconds, including all nine local failure titles. The actual checkout
was synthetic merge `06851da6eb969d63e1c7dc9f7c95f08d09fa4ff1`,
combining `a0f` with `aa58fa107389e8b9ae5949f7ad815943dfd94292`. This is
not standalone local `a0f` qualification and does not erase the nine
local route failures.
- Linux admission uses Node 24.22.2, pnpm 9.15.4 and Rust 1.97.1. Frozen
offline install, exact native hashes and real migrated PostgreSQL 18.1
passed. Native/protocol/build/lock inputs are identical between `6c18`
and `a0f`; validated cache reuse retains the actual `6c18` native-build
provenance. The selected packaged release binary is not called a fresh
`a0f` build. Database synchronization settings stayed on. This admission
alone does not explain the route failures.
- A fresh Mac snapshot of exact `a0f` passed frozen install, workspace
prerequisites, full sequential recursive typecheck and normal `pnpm
build`, both on their first attempt. Typecheck completed at 17:43:05
UTC, build at 17:44:43 UTC; both exited 0 with clean tracked/untracked
source. Pinned Node 24.19, pnpm 9.15.4, Rust 1.97.1, package concurrency
one, Cargo jobs one and a 12 GiB V8 heap ceiling were retained.
Largest-process maximum RSS was 7,668,154,368 bytes for typecheck and
10,038,837,248 bytes for build, not aggregate tree peaks. The first
build correctly withheld its freshness stamp because 125 ignored, pinned
Copilot assets appeared during preparation; exact path/hash analysis
explained this. The normal build then recorded a genuine stamp and
reused Cargo outputs in 1.18 seconds. No manual stamp, source workaround
or gate retry. This is darwin/arm64 static/build proof, not Linux
packaging/runtime or full tests.
- The historical a0 candidate's token checker passed all four gates
across 1,410 files, run directly with pinned Node 24 against the script
behind `pnpm check:token-gates`.
- The single controlled complete-file comparison passed: baseline `6c18`
83/83 in 287.07 seconds, then candidate `a0f` 83/83 in 293.03 seconds,
with zero skips. All nine earlier failure titles passed on both. Both
child/container exits were 0, no OOM/interruption; source and
native/resolver/PostgreSQL guards matched. This ran only after all owned
Mac compilation ended, with fresh processes/databases and identical
four-CPU-quota/6-GiB/overlay inputs. No filtering, instrumentation,
assertion/timeout/source changes or retry loop. This establishes
standalone complete-file recovery, not the cause of the earlier eight
timeouts/AI 422.
- The first unchanged full `pnpm test:run` on exact clean `a0f` ran from
October 30 at 18:01:43 UTC to 21:06:19 UTC. It failed naturally with
test and container exit 1, without OOM. General-server reported 1,257
passed, one failed and seven skipped files; 28,633 passed, one failed
and 103 skipped tests. Only the first of 22 invocations ran. The later
four groups and 21 invocations did not run. The sole failure was the
unchanged chat-shard CLI meta-test: its nested projectless pnpm lookup
hit the offline network guard. This was a failed full gate, not Google
provider acceptance.
- A finite environment pair reproduced that one meta-test failure, then
passed the same unchanged case after supported `corepack prepare
pnpm@9.15.4 --activate` as the existing non-root node user. The cached
pnpm payload was identical. Only the missing node-user last-known-good
record changed. Core source, dependencies, lockfile, fixtures,
assertions, timers and offline guards stayed unchanged. This isolates
the nested collection defect; it does not explain the earlier route
failures or complete the full gate.
- The corrected unchanged full command ran from October 30 at
21:29:03.500 UTC to October 31 at 00:02:44.207 UTC on the same exact
clean `a0f`. It failed naturally with exit 1, signal null and no OOM.
Source stayed clean before, at start and after. It retained two visible
CPUs/quota, 6 GiB, private IPC, normal overlay, matching native inputs,
synchronized real PostgreSQL 18.1, and the default five groups/22
invocations. Only the first general-server invocation ran; the other 21
did not run. General-server reported 1,265 files: 1,256 passed, two
failed and seven skipped. It reported 28,737 tests: 28,631 passed, three
failed and 103 skipped. The two chat cases emitted `Test timed out in
15000ms` at `chat-channels.integration.test.ts:77310` and `:81790`, with
durations of 15,045 and 15,058 ms. These were the durable pre-run FIFO
notice and ambiguous GitHub text restart/retry cases. The retention case
emitted `expected 5340 to be less than 3000` at
`skill-version-retention.test.ts:593`. Its real duration was 1,727 ms;
5,340 ms was the recorded fake-time directory-page gap, not a deadline
timeout. The timeout stacks do not identify the blocked internal await.
The cause of these failures remains unclassified. Inside this same
failed run, the complete 83-case connection file and 498-case service
file passed. The former Corepack meta-case also passed in 6,396 ms.
These component passes do not waive the failed/incomplete full gate. No
rerun, cancellation, timeout/assertion change or full-pass claim. A
later fresh two-case phase trace passed both chat cases; it did not
reproduce or establish the original timeout cause. At that checkpoint,
the PR stayed draft.
- Prior `6c18` targeted checks passed 930 tests across eight files and
token gates. Its selected queue group passed all 53 cases, including the
original 20 failures and 12 new named controls. Backlog cases took 10.49
and 8.45 seconds under the unchanged 15-second limit. Another 1,763 chat
cases were intentionally filtered. This is historical targeted recovery,
not a full pass or proof of the new repair. No timeout or assertion was
relaxed.
- Prior `6c18` full local qualification failed during serial typecheck:
server TypeScript was killed with code 137. Docker confirmed OOM in the
6 GiB container; full tests and build never started. The failure is
retained. The new Mac resource plan avoids repeating that undersized run
and does not change the shared Docker VM.
- Prior CI
[41089793558](https://github.com/paperclipai/paperclip/actions/runs/41089793558)
completed successfully for synthetic merge
`a73bffcfa3ede051961bcabcfa576c703d10c932` (`6c18` plus
`abc270ee4c03e13b4d6eaad156a41b4ebed4bb0a`). All 48 CI jobs passed; all
1,816 chat cases passed, including explicit log lines for the original
20. Check runs were 51 success, two expected skips and one Greptile
failure; legacy Snyk passed. These results do not qualify `a0f` or erase
its local route failures.
- Red proof on the unmodified master baseline: cold picker and Finish
setup restore broad defaults; managed and customer-owned drafts lack
saved intent. The stale setup tests also fail before the lock guard.
- Live staging baseline `b25f3e2af8e77d882cd22d36ca55640e6468e46f` also
reproduces the ordinary failure: select Gmail read-only only, cancel at
Google, reload the connector catalog, then Finish setup. All three
groups return enabled at read/write. Authorization was declined; no new
Google access was granted. This is baseline failure evidence, not a
deployed-fix pass.
- Historical affected suites: 800 tests passed before the final lock
guard. The final focused service and handoff cases passed 126 tests
after that guard. These are not results for the integrated candidate.
- Historical `pnpm -r typecheck` and final lock-guard server typecheck
passed. The historical a0 candidate passed the full recursive gate
separately, as recorded above.
- `pnpm build`: passed again on the final lock-guard source in commit
`1c31cde0ed199fbf4e41b7649590554f7886dfc2`.
- Historical `pnpm check:token-gates` passed; the historical a0
candidate's direct checker pass is recorded above.
- `pnpm test:run` on macOS failed on the frozen commit. It exited 1
after 9,432.41 seconds. General server results: 1,195 files passed, 10
failed, eight skipped; 26,706 tests passed, one timed out, 157 skipped.
Nine setup hooks timed out while starting embedded PostgreSQL. The
retained log records host-wide semaphore exhaustion (`semget`), not disk
exhaustion. One unchanged publication-text performance case also timed
out. Its cause is not established. Later workspace and serialized groups
did not run. This is a failed and incomplete local gate.
- The independent full-source Linux run also failed and was incomplete
on the same frozen commit. Native and real-database admission passed.
Chat integration reported 20 failures in 1,593 tests. Tool-access passed
all 479 tests. Native-session-executor passed all 965 tests. Docker
interrupted the run after about 48 minutes on October 29. The container
exited 143 and was not OOM-killed. The run produced no final group
totals or detailed assertion summary. Shell trap metadata reports zero,
but this is not a valid test-pass result. Source and evidence remain
unchanged. The focused diagnosis below retains those failures; their
cause is not assumed from the interruption. Neither historical local
full run passed.
- A fresh focused replay on the frozen source then executed exactly
those 20 case bodies. All 20 failed; this was not a setup-hook failure.
The two backlog cases reached the unchanged 15-second timeout. The 18
FIFO cases failed on missing notices or receipt rows. All 18 FIFO cases
passed when run alone in a fresh process and database. This supports an
order interaction, not a complete cause or baseline conclusion. A
separate two-backlog control used RAM-backed temporary storage and real
PostgreSQL with synchronization settings on. One backlog case passed in
10.65 seconds; the other still timed out at 15 seconds. No source,
assertion or timeout was changed. The full local gate remains open.
- Earlier mixed-revision run: it began before the final guard and
imported older source before collecting later regression cases. It
failed those new cases with that older cached module. This run is
retained, not counted as candidate acceptance. The fresh focused run
passed all seven stale-setup cases. No case was skipped to hide a
failure.
- Historical remote gates for `1c31` were terminal and clean: 53
successful contexts and two expected Storybook skips. Main CI
[40720536514](https://github.com/paperclipai/paperclip/actions/runs/40720536514)
passed. Greptile reviewed exact head
`1c31cde0ed199fbf4e41b7649590554f7886dfc2` at 5/5 with no actionable
findings; the separate review job also passed, and there were no inline
review comments. These results do not qualify `6c18`.
- CI source qualification: the chat jobs checked out synthetic merge
`ef36746b3d2ec52ba5727dcbe4da265a03421fe4`, which merges the PR into
`7d75ae0569e41786640cf09647ae8849411d2f22`. All 20 locally failing case
names have explicit passing CI log lines. These passes do not establish
standalone local acceptance of `1c31`. The merge adds two upstream Teams
tests, so it collects 1,595 chat cases instead of 1,593. Neither
backlog/FIFO assertions nor their timeouts changed.
- Independent source review found an earlier credential-identity race.
The guard and seven deterministic cases resolve that finding. A later
integration review missed the separate overlapping-start race. Both RED
failures and that review miss are retained. The narrow follow-up repair
passed 498 service cases, independent source review and fresh remote
CI/5-of-5 review; full local qualification remains incomplete.
- Source qualification is ready for merge. Live repaired-draft recovery,
delivery and Google approval are not established by these results. The
local whole command remains explicitly incomplete.

## Risks

- Historical drafts without a matching intent now need an explicit
service choice. This is deliberate and prevents silent broadening.
- A concurrent credential or method edit now returns 409. Reloading lets
the person review the changed setup.
- Overlapping starts keep separate requested scope sets. Updating draft
intent does not relabel an earlier OAuth state's consent request.
- Saved intent is not consent. Provider-reported scopes and current
action policies still control discovery and dispatch.
- No migration is needed. No existing token or grant is rewritten by
saving draft intent.

- Default ungrouped launch paths now execute six chat children in
sequence and 28 whole-command invocations. Exact coverage, local
launcher contracts and all six real default chat partitions passed. A
complete uninterrupted local whole-command run remains unqualified
because of host capacity.
- The retention test-clock repair depends on owned-I/O and zero-duration
connection-timer progress. The controlled regression, sensitivity mutant
and current exact-tree CI protect the original assertion. It did not
reach a completed row in the interrupted local whole run.

## Model Used

OpenAI Codex, described by the runtime as GPT-5 based. The exact runtime
model ID and context-window size are not exposed to this task. Used
reasoning, code execution, browser verification, and independent
delegated review.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used, including the runtime metadata
limit
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the bug report template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket or instance identifier
- [x] I have run tests locally and they pass — exact clean 82 passed 41
launcher/workflow cases and all 1,816 real default chat cases, full
recursive typecheck, normal build and token gates. Full exact-tree PR CI
passed. The separate local whole `pnpm test:run` was interrupted by disk
protection and remains incomplete; it is not claimed as a local whole
pass.
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green — current exact-head checks
passed; the verified CI checkout tree equals clean 82. The separate
interrupted local whole command is disclosed above.
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
fresh exact-82 summary and check passed; the earlier finding is
resolved. This is source review, not acceptance.
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 22:02:58 -05:00
DottaandPaperclip 909e29dd07 fix(ui): show agent-created subtasks inline in the task feed (#18320)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task feed shows agent messages, documents, and artifacts.
> - An agent can create a subtask or a separate follow-up task during
that work.
> - The reader must open the Tasks tab to find the new task.
> - This pull request adds a linked task card to the source feed at
creation time.
> - The card shows the current title, task number, and status.
> - The reader can inspect delegated work without searching a second
panel.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Task creation visibility in the source task feed. Related work: #13823
added ancestor navigation in the Tasks panel.

**Current behavior**

Agent-created child tasks appear in the Tasks tab. The main feed has no
persistent link card for those tasks.

**Proposed behavior**

Show each agent-created direct child or source-linked follow-up task
once in the feed. Keep the card at creation time when status changes.
Keep existing chat handoff and accepted suggestion cards without
duplicates.

**Reason and benefit**

Readers can see which work an agent created and open that task from the
conversation.

**Breaking changes**

None. This change uses existing authorized task reads. It does not add
API or database fields.

## What Changed

- Pass the existing child and source-task reads from task detail to the
feed.
- Add a task card with a link, wrapping title, task number, and status
badge. Use existing design tokens.
- Suppress repeated cards and tasks already shown by accepted
suggestions or chat handoffs.
- Show task-read failures with Retry. Keep the conversation readable
during those failures.
- Add feed and page regression cases plus desktop, multiple-task, dark,
and mobile stories. Update the product description and delegation
recipe.
- Keep task selection and rendering in the task feed module. Existing
issue APIs continue to own access checks and company scope.

## Verification

- Passed: 224 focused tests with `pnpm exec vitest run
ui/src/components/TaskChatThread.task-creation-order.test.tsx
ui/src/pages/IssueDetail.test.tsx
ui/src/components/task-detail/TaskDetailTasksPanel.test.tsx
--maxWorkers=1`.
- Passed: `pnpm --filter @paperclipai/ui typecheck`.
- Passed: `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and
`node scripts/storybook-catalog.mjs`.
- Cases cover creation order, current status, links, company filtering,
direct children versus grandchildren, duplicate suppression, and read
failure with retry.
- Passed: browser render and link assertions for desktop, multiple
tasks, dark theme, and mobile at 390px. All four story play phases
finished. No page errors or horizontal overflow occurred. Screenshots
use fixture task data and the production task feed. They do not prove
server persistence or agent execution.
- Passed: `pnpm --filter @paperclipai/ui build` after the concurrent
memory failure.
- The mobile preview frame needed spacing to contain the feed scrollbar
gutter. Fixed the frame and repeated the browser checks.
- Addressed the first Greptile finding: source-linked follow-ups now
load with Streamlined UI off. A regression test covers that setting.
- Full local build and typecheck cannot complete because Cargo is
absent. The first concurrent UI build and UI typecheck were killed by
the workspace memory limit. Both UI commands passed when run separately.
The full local test run was stopped to fit that limit. PR CI must supply
the full-suite verdict.

## Risks

- Low risk. Delayed task reads can insert an older card into a loaded
feed. Stable task IDs preserve the card during status updates.
- New cards use the same access-checked task data as the Tasks panel. No
task mutation or permission change is added.

## Model Used

- OpenAI Codex, GPT-6. The runtime does not expose a more specific model
ID or context size. Used reasoning, tool calls, code edits, tests, and
browser automation.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] 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-30 21:42:24 -05:00
DottaandPaperclip 8ff812cdde feat(chat): deliver proactive task messages to agent chats (#18374)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat gives each person a persistent conversation with each
agent.
> - Tasks and routines produce results outside that conversation.
> - Those runs need a safe way to bring a requested result back to the
person.
> - The server must select the agent's own chat and check the source
task's access rules.
> - This pull request adds proactive chat messages and unread
indicators.
> - People can see the result, open its source task, and reply in the
same chat.

## Linked Issues or Issue Description

**Subsystem affected**

Server, native runner tools, shared contracts, database, and UI.

**Problem or motivation**

An agent can report progress on a task or comment on an authorized task.
It cannot send a routine result to its own standing chat with the
responsible person. A morning review routine therefore cannot leave a
visible digest in that person's chat.

**Proposed solution**

Add `send_chat_message({body, idempotencyKey})` and `POST
/api/agents/me/chat/messages`. The server selects the company, agent,
and responsible person from the active run. It saves an attributed
comment and audit record in one transaction. The chat shows a
source-task link and per-person unread state.

**Alternatives considered**

A destination parameter on a generic comment tool would expose
unnecessary routing authority. A new delivery worker would add another
durable delivery path. This change uses a dedicated tool and the
existing comment and live-event paths.

**Roadmap alignment**

This extends the experimental Agent Chat capability in `ROADMAP.md`. The
existing `enableAgentChat` setting controls it. Related public work:
Refs #13282, Refs #13283, and Refs #14408. Searches for proactive chat
and unread chat found no duplicate PR.

## What Changed

- Add a focused messaging service shared by the native tool and HTTP
route. It checks current run ownership, execution mode, recipient
membership, task access, and task privacy.
- Reuse the canonical company/agent/person conversation. Save the
comment and audit record together. Keep task completion and chat
execution separate from delivery.
- Add source-task provenance and source-scoped retry keys. Identical
retries return the saved receipt. Changed content returns a conflict.
- Enforce the conversation's fixed agent at the shared comment-write
boundary. Keep normal reply cancellation and session checks.
- Add chat unread state, accessible agent dots, aggregate Chat
indicators, and visible-message read cutoffs. Refresh through existing
live events.
- Add the request-key constraint, native tool contracts, documentation,
capability maps, stories, and regression coverage.

## Verification

- Local delivery/security proof: all 38 proactive-message cases pass.
Eight credential-scope regressions and four quota regressions fail
against the prior source. The repaired delivery and canonical
cross-issue cap suites pass all 49 cases; all 31 OpenAPI tests, server
typecheck, and capability-map checks pass. The shared per-run cap covers
native and HTTP sends, mixed ordinary mutations, concurrent last-slot
contention, and retry/recovery without double charging.
- Credential tests preserve the authenticated person and authorizer;
reject bridge/test credentials and persisted skill-test runs after
task-mode changes; and recheck API-key revocation, scope, and
responsible person after destination locking. The earlier
delivery/native-authority suites passed all 74 cases before the four
quota additions.
- Four PostgreSQL contention cases cover native and HTTP sends plus
retries during a native chat mutation. All four deadlock against the
earlier source and pass with destination-before-source/run locking.
Recovery and human-reply delivery enqueue only the human comment; a
proactive digest never wakes the chat agent.
- Passed 108 companion conversation, native-authority, and OpenAPI
tests; 112 runner catalog/workflow-report tests; 47 completion-delivery
tests; and 25 project-handoff tests. Focused runner tests cover native
tool availability without generic API tools.
- All 327 affected UI tests, UI typecheck, token gates, and catalog
checks pass. The read hook retries at most three times, respects server
retry delay, coalesces only seen cutoffs, recovers on reconnect, and
cancels on scope changes.
- Real browser journeys with a deterministic process agent verify
routine-to-chat delivery, first-chat creation, unread state across
reload, the source link, secondary chat navigation, and a follow-up
reply referring to the digest. This does not qualify live GitHub
retrieval or model output quality.
- The Storybook showcase uses production components with deterministic
network fixtures. Rendered interactions pass for the landing, ordinary
read success, transient read recovery, and persistent failure after
bounded retries. Both Chat navigation variants update from two unread
chats to one while only Kodi's dot clears. Mobile and light variants
were reviewed. The existing Coordinator Recents label contrast finding
is unchanged; no Linux visual baseline archive exists.
- Current master's independent sandbox migration retains 0418.
Regenerated the feature migration as 0419 from the combined schema and
retained exactly the newest five snapshots; numbering/safety, replay,
and schema-drift checks pass.
- Workspace typecheck and build passed before PR preparation; canonical
server/UI typechecks passed again on the combined tree. Migration
`0419_slippery_impossible_man.sql` passes safety and schema drift checks
on disposable PostgreSQL, including interrupted index repair, concurrent
migrators, one-time owner read-state backfill, preserved receipts, and
two SQL replays. A default five-second local snapshot comparison timed
out; a diagnostic 30-second run passed without drift.
- Earlier failures are retained in the record: full local `pnpm
test:run` and broad shards encountered embedded-PostgreSQL startup,
timing, and provider-recovery failures. Thirteen selected
external-channel cases pass in isolation on the original and changed
sources; an unordered comment-row assertion now explicitly orders both
reads. The earlier route registry, native tool count, runner catalog,
and accessible Chat badge-name failures were fixed and passed full
remote CI on `920b3bb7db`.
- Repeated managed-skill server8 failures came from CI's newer synthetic
merge: its Cloud guard correctly rejected the old local-disk fixture.
Master independently repaired the fixture in #18385; this branch keeps
that repair unchanged. All 57 managed-skill and Cloud prerequisite cases
pass on the combined tree, and that fixture has no remaining PR diff.
- Current reviewed head `dc16f314739a6d977bed21cb1446d0e80a541578`:
Greptile 5/5 with no findings, Superagent security assessment passed,
advisory Paperclip Review 5/5 with no findings, and zero open review
threads. All 55 current-head check runs pass, with five expected skips
and the advisory review neutral at 5/5; Snyk also passes. No checks are
pending or failing. Protected squash auto-merge is enabled and is
waiting for required code-owner approval. A normal exact-head merge was
refused by the base-branch policy; no admin bypass was used. The
previous head's Superagent quota finding is fixed and covered above.

## Risks

- Chat remains company-visible. Delivery rejects a source task with
private-task, project, or ancestor restrictions.
- Read state uses a comment timestamp cutoff. The server retains
database precision and never moves a read receipt backward.
- The new unique constraint changes comment query planning. An existing
regression now uses an explicit row order. The migration builds the
unique index concurrently, then takes a brief table lock to attach it.
It uses the existing top-level migration and interrupted-index recovery
path.
- The upgrade backfills missing chat-owner read-state rows at the latest
existing agent comment. Existing read receipts remain intact. New chats
can still be unread before the human participates.
- Quota observation commits atomically with delivery. A rejected send
rolls back its attempted denial audit row and any first-chat creation;
the canonical warning remains in server logs, and previously spent quota
remains enforced. Identical/conflicting retries and receipt recovery
spend no extra slot.
- This version delivers in-app only. It adds no external-channel, push,
or email delivery.
- Local full-suite acceptance remains limited by the failures recorded
above. The feature stays behind `enableAgentChat`.

## Model Used

OpenAI Codex. PR preparation and CI work used `gpt-6.1-sol` with tool
use and code execution. The earlier implementation also used Codex, but
its exact model ID was not recorded in the visible session. The
context-window size was not provided.

## 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 focused tests locally and they pass; the broad local
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-30 21:39:07 -05:00
DottaandPaperclip 7114582c63 fix(ci): track repository inputs across test projects (#18398)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - PR CI selects affected tests before allocating parallel runners.
> - Recent audits retained about 96% of test files despite narrow
changes.
> - Unchanged consumer packages kept full coverage, and source scans
confused data fields and message text with runtime loaders.
> - File reads need explicit edges that imports alone cannot provide.
> - This change follows consumer graphs and known file inputs while
retaining unknown effects.
> - The AWS CODEOWNERS gate stays in front of runner allocation.

## Linked Issues or Issue Description

Refs #18376 and #18362. Narrow source changes still selected most tests
because consumer packages kept full coverage and known file reads were
treated as arbitrary input. Expected behavior is to retain affected
import/file consumers and unknown inputs, then partition only the
selected files.

The shared storage failure found during the audit was fixed upstream in
#18357. The candidate merge ran all 18 managed-skill storage tests
successfully in [Linux
qualification](https://github.com/paperclipai/paperclip/actions/runs/41140209697/job/124352365547).
This branch includes that upstream commit; no additional storage
implementation or permanent diagnostic job is included.

## What Changed

- Assess every Vitest project in the coarse plan, including unchanged
consumer workspaces.
- Add dependency edges for statically resolved module-relative
filesystem reads and directory listings. Keep unknown paths, writes,
escaped APIs, mutable path objects and untracked inputs conservative.
- Distinguish data keys, erased types and message strings from runtime
globals, loaders and mock bypasses. Retain destructured globals, aliased
object reads and mocked filesystem/path resolution.
- Normalize `fs` and `node:fs` before recording coverage so a known read
cannot hide an unknown one.
- Review the Drizzle SQL/schema entry points by hashes of their complete
import closures. CommonJS/dynamic loaders reject the fingerprint;
drivers and migration readers remain opaque, and dependency updates
revoke the review.
- Record file input edges and per-test retention reasons in selection
audit artifacts.
- Add cross-workspace, mixed-import, symlink retargeting, setup-input
and dependency-review regression cases. Object-valued URL constants are
explicitly opaque with and without mutation. Update the developer guide.
- Preserve the AWS CODEOWNERS authorization gate, runner-group
restrictions and existing lane ownership.

## Verification

- Final head `eedad362e84d6b68f0f048c92db6032e45622c46` passed [complete
Actions
CI](https://github.com/paperclipai/paperclip/actions/runs/41144233520)
on attempt 1. Overall status: 57 successful checks, three intended
skips, and one neutral Paperclip review. Both Greptile and Paperclip
rated this head 5/5; zero unresolved review threads.
- All 17 local selector tests passed: `node --test
scripts/ci/test-selection*.test.mjs`. Final [Linux
qualification](https://github.com/paperclipai/paperclip/actions/runs/41144233203/job/124365428832)
passed all 18 selector/impact tests without skips, plus real workspace
selection and cache/routing checks.
- Same-tree local comparison against the previous selector at
`d331d8481a`: Inbox changes selected 466 rather than 700 files (33%
fewer); auth middleware changes selected 2,141 rather than 2,788 files
(23% fewer). The sampled plans retained the same 2 and 24 jobs under
existing weighted budgets. Final Linux qualification selected 466 files
for Inbox and 1,949 for auth/config-test changes; platform-dependent
graphs differ, so these are not a Linux before/after comparison.
Chat/native Runner lanes retain their existing ownership and are
excluded from these counts.
- Local `pnpm -r typecheck`, `pnpm build` and `git diff --check` passed.
The complete local `pnpm test:run` was attempted and stopped after
repeated embedded PostgreSQL startup failures; initdb reported exhausted
macOS semaphore capacity. Full Linux CI passed on the final combined
tree.
- The storage regression was corrected upstream in #18357. [Focused
Linux
verification](https://github.com/paperclipai/paperclip/actions/runs/41140209697/job/124352365547)
ran all 18 managed-skill tests successfully, with no skips; the final
full CI run also passed its server lane.

## Risks

- Unknown effects must retain their consumers. Regression cases cover
mixed builtin spellings, dynamic paths, escaped/mocked APIs, global
aliases, reviewed dependency changes and cross-package file reads.
- Graph analysis now visits unchanged consumers. Its added work must be
included in rollout latency measurements; fewer test files do not by
themselves prove shorter end-to-end PR time.
- The weighted shard budget deliberately remains unchanged. These
samples reduce file execution without reducing allocated jobs.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository inspection,
code execution and GitHub tools. The exact serving variant and context
window are not exposed in this session. No subagents were used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 21:37:39 -05:00
Devin FoleyandPaperclip 87ae20ae65 fix(server): reconcile failed sandbox cleanup with signed absence (#18407)
Reconcile failed ephemeral Cloud leases through a signed cleanup-only absence observation when local historical inspection is unavailable. Preserve failure outcomes, exact resource bindings, retention and row-version fences; grant no run-continuation authority.

All 54 current-head checks/statuses passed. Greptile is 5/5, Medium, with no findings or unresolved threads. The 38 focused tests pass; both new reconciliation cases fail without the fallback. Isolated baseline and branch idle suites each pass all 225 cases. The original broader local teardown timeout is retained in the PR, and the full local run remains in progress.

Cloud protocol support is already serving in staging. Exact candidate composition and hosted provider sleep/wake qualification follow this merge. Production has not been changed.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 17:04:04 -07:00
Devin FoleyandPaperclip 105a67b52c Reuse signed master images for npm canaries (#18404)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Release workflows publish npm packages and multi-platform images.
> - A master push can finish its image before the npm canary dispatch
starts.
> - The dispatch currently builds that same source again on two runners.
> - This PR verifies and reuses the signed master image by digest.
> - Missing images retain the native build path. Channel promotion still
follows npm.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The Docker workflow dispatched after npm canary publication.

**Current behavior**

Every canary dispatch builds both architectures, even when master has
already published the same source. This consumes runner capacity and
delays the image channel update.

**Proposed behavior**

Resolve the full-SHA master image. Verify its platform index, digest and
signed source identity. Retag that immutable digest. Build normally when
the image does not exist.

**Reason and benefit**

Remove duplicate image builds while keeping missing-image recovery and
the current npm channel check. A recent duplicate used about 25
runner-minutes. The saving depends on whether the master image exists.

## What Changed

- Add a canary-only reuse job before the native matrix.
- Require signed provenance from the canonical Docker workflow on master
at the exact source and signer commit. Read the proof from GHCR.
- Reuse the validated digest or build both platforms when the full-SHA
image is absent. Stop on registry and verification errors.
- Keep the serialized npm dist-tag promotion after either path. Keep
other build lanes independent.
- Add failure tests, register them in CI and update release
documentation.

## Verification

- Passed 603 tests: `node --test '.github/scripts/tests/*.test.mjs'
scripts/standard-image-contract.test.mjs
scripts/reuse-canary-image.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs
scripts/cloud-source-verification.test.mjs`.
- Passed `actionlint -shellcheck='' .github/workflows/docker.yml
.github/workflows/pr-trusted.yml` and `git diff --check`.
- Full actionlint reports the same six existing shellcheck findings as
the unchanged master workflow. No new findings.
- A published master image passed the exact provenance command. This was
a read-only check. No images were retagged.
- Gitleaks and manual diff inspection found no secrets or private
references.
- Attempted `pnpm -r typecheck`, `pnpm test:run` and `pnpm build`. They
cannot start because this isolated checkout has no installed
dependencies (`tsc` and `tsx` are absent). Repository CI passed on
`3c46f0152d4db94a7f393bc79f466aa6c2c745e2` after the documented
browser-test rerun. All checks are complete. The original failure and
prior baseline occurrence remain recorded in the PR comments; its root
cause remains unknown.

## Risks

- The image can appear just before its attestation. Verification then
fails closed. Rerun after the master producer completes.
- Reuse preserves the first build's resolved dependencies and tool
versions. It intentionally does not rebuild the same source to refresh
floating inputs.
- A skipped or unfinished master image still needs a full build. No
speedup is claimed for that path.
- End-to-end reuse and runner savings require observation after merge.
No live publication was performed.

## Model Used

OpenAI `gpt-6.1-sol`, through the Codex harness in T3 Code, with xhigh
reasoning effort and shell/code tools. The context window size is 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-30 16:54:04 -07:00
Nicky Leach 9e904ee519 perf(server): overlap independent heartbeat preparation reads (#18372) 2026-10-30 16:49:20 -07:00
DottaandPaperclip 1353a232f2 test(e2e): add a portable active follow-up journey (#18345)
## Thinking Path

> - Paperclip lets people direct agents while their work is active.
> - Product E2E checks must prove that saved user input reaches the
intended work.
> - The existing active chat story depends on a file in a local agent
workspace.
> - That setup cannot qualify an attached deployment with remote agent
execution.
> - This change adds one shared active follow-up journey through the
normal task UI and API.
> - Independent native operation, saved input, final reply, and cleanup
checks make the result inspectable across targets.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Product E2E coverage for a user follow-up sent while a native agent is
working.

**Current behavior**

The classic chat story holds work open with a local file. The shared
deployment-targeted harness has no active follow-up journey. A running
heartbeat alone cannot prove that work was active when input arrived.

**Proposed behavior**

Run one bounded command through the real native provider. Observe its
active execution before and after one follow-up is saved. Require one
final reply with the late requirement, correct task and agent identity,
an empty input queue, and visible readback after reload. Use the same
story on managed and attached targets.

## What Changed

- Add a shared `followup-while-running` journey with normal task
creation and reply submission.
- Require a bound native turn and pending shell execution at the input
boundary. Retain a closed receipt with source identity and a row hash.
- Accept one steered work run or one normal successor (1–2 native runs).
Preserve every other journey's declared run contract.
- Reuse the saved native final reply observer, run binding checks, usage
collection, target lifecycle and private evidence path.
- Accept canonical builtin/process execution events independent of
provider tool display names; calibrate against real OpenCode, Codex and
ACP mappers. Reject Paperclip semantic tool names across native
wrappers/prefixes and unnamed or ambiguous builtin calls.
- Recognize only the observed legacy PRP v1
builtin/bash/unknown/readOnly=false command shape and fail promptly when
owned work finishes before a live boundary can be observed.
- Ready the task page/composer before the observed command boundary, use
a bounded 90-second command, and preserve active-after-persistence
proof.
- Add adversarial oracle and retained-result calibration. Register the
journey, include its sources in the definition hash, and document its
coverage.
- Keep six real browser document-readiness checks and verify
shared-deadline behavior with a deterministic clock/state test that
rejects timeout-reset mutations.

## Verification

Exact current head `e72e20ad111bd94728d38606015d1fdac3c92929` passed
[full CI run
41142552195](https://github.com/paperclipai/paperclip/actions/runs/41142552195):
all 49 workflow jobs reached accepted terminal results, including
typecheck, build, every test lane and aggregate verify. All 59 reported
checks are terminal: 55 success, three expected skips and one neutral
5/5 Paperclip review. Snyk passed. [Fresh Greptile
review](https://github.com/paperclipai/paperclip/pull/18345#issuecomment-6528913235)
explicitly names this exact head and gives 5/5. No review threads remain
open. The PR is mergeable.

These source gates do not establish a live QA pass at this head. Fresh
protected QA at this exact source and the separately recorded deployed
application/runtime remains required before primary merge and daily
admission.

Historical live QA staging **PASS** on qualified commit
`af9e091b15b5e24b6b2cc1b424523430cc2ab024`: 6/6 checks, all five phases
including cleanup, two native work runs, and the configured
model/environment check passed. The [sanitized qualification
report](https://pages.paperclip.ing/evals-qa-smoke-41122620146-1/)
records that exact measurement.

Final integration head `e72e20ad111bd94728d38606015d1fdac3c92929` merges
exact actual squash `18b1637b6371a6a6adade857e2a73654ee626fef` from
[#18254](https://github.com/paperclipai/paperclip/pull/18254) into
previous head `e54d64743964b1a19d165537bebbe62c50389a23`. The merge had
no conflicts. All 18 files in this PR's change set, the complete 45-file
shared journey directory, and six shared native/evidence helpers retain
their exact previous-head Git blobs: 59 scoped files in total. The
production clarification helper remains blob
`800a747284db19b8484650b6759e8bd1f356839d`. Follow-up 1–2 runs, question
1–3 runs, older exact counts, owned native event checks,
active-before/after persistence proof, cleanup/accounting and feature
mappings remain unchanged.

Source integration head `e55d74491f5bcd99c1455e9ace02bd7ad7319fae`
integrates exact actual squash
`8595efc20bda3ce20a9fbbf34a5d156a6fcf6d57` from
[#18385](https://github.com/paperclipai/paperclip/pull/18385). The merge
had no conflicts. All 17 files in this PR's change set and six shared
native/evidence helpers retain their exact Git blobs from previous head
`162e341cda5b627639b486b4019a1675bb018ea2`. This preserves the follow-up
and question readiness checks, feature mappings, six closed follow-up
check IDs, immutable before/after active-operation proof, follow-up 1–2
runs, question 1–3 runs and older exact counts.

Previously reviewed head `e54d64743964b1a19d165537bebbe62c50389a23` adds
a separate test-only reliability repair on top of that source
integration. It replaces one scheduler-sensitive browser case with a
deterministic Vitest clock and locator-state model that calls the actual
production helper. The six other real Chromium checks remain
byte-for-byte unchanged and pass **6/6**. Focused unit suites pass
**51/51**, including the deterministic deadline case. This is six
browser checks plus focused unit coverage, not seven browser checks.

The model makes the panel ready at 100 ms, the supplied answer ready at
600 ms, and full valid content ready at 1,300 ms. It requires rejection
at the shared 1,000 ms deadline and records immutable rejection state
before simulating a 10-second scheduler stall. Both restarted-timeout
mutations fail: resetting all waits wrongly resolves at 1,300 ms;
resetting matcher timeouts while keeping the final real deadline guard
rejects only at 1,300 ms with valid content present. The genuine helper
rejects at 1,000 ms with the answer still incomplete. The production
helper is unchanged, Git blob
`800a747284db19b8484650b6759e8bd1f356839d`. That two-file test-only
patch changed no journey, application, run, accounting, model or runtime
behavior. Its six-browser/51-unit results are prior-head evidence; the
complete patch is unchanged in the new integration.

The final source also retains the actual merged question-primary squash
`d9354bbfc35ef74333e90e596ce21dc8e59149b9` from
[#18346](https://github.com/paperclipai/paperclip/pull/18346). Later
commits `409117451da260a03fc28a3107c7808ecbe68f8f` and
`ea3e7b1d1bed562351fcf4722c7175001b987b59` bound question document
readiness to one campaign deadline and test that waits cannot restart
it. Commit `162e341cda5b627639b486b4019a1675bb018ea2` adds
question/follow-up report feature mappings and coverage. These files are
unchanged by the final merge.

The imported upstream source has real application changes:
[#18334](https://github.com/paperclipai/paperclip/pull/18334) makes
managed skill content durable and extends native skill-test contracts;
[#18350](https://github.com/paperclipai/paperclip/pull/18350) requires
managed Cloud shared storage and bootstrap prerequisites. #18385 updates
TestOps job metadata and repairs their combined maintenance fixture. The
new merge additionally imports
[#18383](https://github.com/paperclipai/paperclip/pull/18383) at
`81ecaf0654fe79a2a2dbda6588f033e39ee610e4`, which bounds failed
lifecycle verification;
[#18357](https://github.com/paperclipai/paperclip/pull/18357) at
`45a3a92e6dc52d20923b9aa34a22fee2ec5443f9`, which persists
sandbox-creation ownership and updates cleanup/adapter/plugin contracts;
and #18254 at `18b1637b6371a6a6adade857e2a73654ee626fef`, which accepts
a valid late Antigravity authorization URL while native authentication
drains. This PR's diff against exact upstream
`18b1637b6371a6a6adade857e2a73654ee626fef` contains only journey tests,
report coverage and documentation. Harness source and deployed
application/runtime identity are separate inputs. This source
integration does not deploy the imported application changes or claim
the QA target runs this application revision.

This final SHA has not been measured by the historical run above:
**fresh QA at this exact final head is required before primary merge**,
followed by normal TestOps verification/admission. Fresh exact-head CI
and review have passed as recorded above. The live measurement must
record the actual separately deployed QA application/runtime identity.

Seven whole-file blobs remain identical to the qualified SHA. All paths
are relative to `tests/runner-e2e/`:

| Journey/helper | Unchanged Git blob |
| --- | --- |
| `product-journeys/active-followup-evidence.ts` |
`83a5d9fab52abb9849a40e83eca6b6a9c29bf587` |
| `product-journeys/active-followup.test.ts` |
`728160c610c18292d2cf06d4a87d25a8719f1734` |
| `native-task-reply.ts` | `59d11f1a178dad9db3da8fa2342ff93643cb9922` |
| `native-event-envelope.ts` |
`305b0b456c59c511ee328e529ad574c0583075a0` |
| `run-observations.ts` | `08c8ad184a821a7cd536926b3d7e3d1156a1e3da` |
| `user-actions.ts` | `e9611348dc41e17899367dab2e3b36d3d1be9480` |
| `stop-redirect-flow.ts` | `4580bd605a425bc72511e02d988492acbec8d60e` |

The follow-up preservation comparison against historical `af9` has three
explicit exceptions; no whole-file identity is claimed for them. The
separately documented question readiness and report additions above also
require final-source verification:

1. `product-journeys/agent-flows.ts` adds `question-answer-resume` to
the `AgentJourney` type exclusion, alongside follow-up. Its remaining
contents and runtime helper bodies are byte-for-byte unchanged.
Qualified blob `a0afaa968c1d854476159fef21de7b6dd50a4a98`; final blob
`0cc797c0ae594e7769338e63a80c4f67e29e4a54`.
2. The common run-count helper is centralized in `success-contract.ts`
and re-exported by the catalog. It accepts follow-up **1–2**,
clarification **1–3**, and each older paid journey's exact count. The
follow-up catalog entry, maximum of two runs, six required checks,
native dispatch, collection and retained-run contract remain
byte-for-byte unchanged. The helper's text differs; its preserved count
semantics are verified explicitly.
3. `product-journeys/active-followup-flow.ts` changes exactly one
composer readiness assertion from Playwright's implicit five-second
default to an explicit 30-second timeout, matching `submitTaskReply` for
attached targets. Prompts, actions, native evidence, before/after
persistence proof and grading otherwise compare byte-for-byte unchanged.
Qualified blob `64392329198a1a4d9828e32834d4507e175216e6`; final blob
`2746b5ba89e2af26b4097ba7897913186786ac5d`. This correction is why a
fresh final-head QA run is required.

- **310 focused tests passed at current final head
`e72e20ad111bd94728d38606015d1fdac3c92929`**: 286
journey/evidence/catalog/report/shared-deadline tests in 14 files and 24
native authentication/real-child stream-order tests in two files. Both
invocations used Node24 and one Vitest worker. The earlier `e55`
integration also passed 365 focused tests, including 40 Cloud
configuration and 40 TestOps metadata cases; those results remain
prior-source evidence.
- **157 explicit count assertions passed again at the current final
head**, including both interactive ranges, older exact counts,
invalid/fractional/non-number values and catalog/contract export
identity. The maximum bounds and six closed follow-up check IDs also
matched.
- Maps and diff checks passed. The official QA runtime-import preflight
passed on Node24 at the current final head without network access. It
uses a dummy adapter and no credentials. It does not prove target
connectivity, sign-in, model readiness or deployed application/runtime
identity. Those require the normal protected QA run. No model/provider
work or optional Runner release was dispatched.
- Current local runtime dependencies use ignored isolated
workspace-source views. No shared dependencies or compilers were
changed. A previous local typecheck attempt hit stale reused Runner
declarations. No full repository typecheck, test run or build was
repeated locally; the successful exact-head full CI run above now
supplies these gates.
- CI on previous head `162e341cda5b627639b486b4019a1675bb018ea2` failed
the Cloud/local maintenance fixture in [server shard
9](https://github.com/paperclipai/paperclip/actions/runs/41133716802/job/124331643100),
plus dependent verify. The actual tested merge combined that head with
master `198218bf554877fe3b7a83742eefb3b8f12392c6`. A Cloud child
selected local-disk storage and hit the new shared-storage policy. This
was a deterministic upstream fixture mismatch; no unchanged failed-job
retry was used.
- The actual #18385 repair configures a valid Cloud child, verifies
local bytes independently, checks the expected provider mismatch and
retains exact stored-config readback. Its own final head
`b76d5dd40d7711f1b5f6b6316b1114c0aae02d57` passed 59 checks, including
[server shard
9](https://github.com/paperclipai/paperclip/actions/runs/41133876636/job/124331450635).
That prior result supports the repair; it does not replace this final
head's fresh CI. Separate repair candidate #18392 and its
source/evidence are retained as superseded history.
- A local attempt to run the database fixture could not start PostgreSQL
because the host exhausted macOS semaphores. A first setup attempt also
failed package resolution before test execution. Skipped database cases
and these setup failures are not passes. No kernel settings, shared
processes or databases were changed.
- The complete previous-head CI run
[41138618869](https://github.com/paperclipai/paperclip/actions/runs/41138618869)
finished with one underlying failure: [Runner Vitest shard
1](https://github.com/paperclipai/paperclip/actions/runs/41138618869/job/124347859445)
expected native Antigravity login success but observed failure at
`antigravity-auth.test.ts:101`. The lane had one failed test, 1,994
passing tests and eight skipped tests. Aggregate verify failed only
because of this lane. All other 57 checks were accepted, including
build, typecheck, all server/browser suites, Runner shard 2, Snyk and
exact-head 5/5 reviews. No unchanged retry was requested.
- The independently reviewed #18254 repair removes an invalid cross-pipe
ordering assumption: a valid URL on stderr can arrive after the
authenticate response on stdout during drain. Its real-child regression
forces both orders. The current final source imports that actual squash;
the 24 focused authentication cases pass here. Fresh full CI and
exact-head review have now passed for this source, as recorded above.
The earlier failed result is not relabeled.
- The original live compatibility failure is retained: an older PRP v1
pack labeled builtin `bash` as operation `unknown`, causing the observer
to miss the command and never send the follow-up. Its exact shape was
reproduced red before repair. Generic unknown operations, semantic
tools, wrappers, read-only work and foreign provenance remain rejected.
The historical qualified pass used the repaired oracle; no failed result
was relabeled.
- Earlier CI on `6fad965d69` hit an unchanged heartbeat test's
three-second adapter-call wait; its original failure and one narrow
rerun remain recorded. The qualified SHA subsequently passed CI. An
earlier report-catalog subprocess failure is retained. The final focused
Node24 run now includes that suite and passes after the documented
report feature mappings.

## Risks

The fixture asks the native agent to run one bounded `sleep 90` command.
The observer must see actual active native execution; a fast or
noncompliant turn fails rather than passing from elapsed time. A
completed result requires one or two bounded native work runs, source
attribution, configured model/environment, and collection. Unknown
provider prices stay unknown. This change does not alter production
execution or grant new access.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and code execution. The host
does not expose an exact underlying model version 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 available 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; existing
follow-up execution fixes do not provide this deployment-targeted test
- [x] I have described the issue in-PR following the enhancement
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket or instance-derived details
- [x] I have run the new focused tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented 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 merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 18:37:17 -05:00