Commit Graph
442 Commits
Author SHA1 Message Date
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 47f81e850b fix(testops): verify unexpanded result job runs (#18462)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat feature evaluations send their results to TestOps.
> - The final reader checks the result against its current GitHub run.
> - A real result omitted the nested job object and had no presentation
links.
> - The reader rejected that passed result after a successful upload.
> - This change joins the embedded job-run ID to the separate job-run
response.
> - The reader keeps the source, case, status, and attachment checks.

## Linked Issues or Issue Description

Refs #18394 and #18322.

**What happened?**

The native chat test and cleanup passed. TestOps stored a passed result
and three attachments. The final read-only step failed with
`chat_testops_upload_mismatch`. The result response had a job-run ID,
launch ID, and current GitHub run URL. It did not include the nested job
object. Its presentation links were empty.

**Expected behavior**

The reader must accept that response when the separate job-run response
proves the exact job, launch, and current GitHub run. It must reject
conflicting identity or source data.

**Steps to reproduce**

1. Return a valid result with an unexpanded job run and empty links.
2. Return the matching full job run from the existing job-run endpoint.
3. Call `verifyChatUpload`. The old reader rejects the result.

**Paperclip version or commit**

Observed on c2971badde. The fix starts
from ab51cabbbd.

**Deployment mode**

GitHub Actions and AWS. This defect is in the TestOps report reader.

## What Changed

- Join the exact embedded job-run ID to the separately checked job-run
response.
- Accept empty presentation links. Reject conflicting known run and
commit links when present.
- Reject conflicting embedded job fields.
- Add regressions for the observed response and wrong job, run, launch,
and source data.

## Verification

- Three new tests fail against the parent reader.
- `node --test tests/runner-e2e/chat-feature-testops-api.test.mjs`: 47
passed.
- `node --test tests/runner-e2e/testops-chat-reporter.test.mjs`: 14
passed.
- Both changed files pass `node --check`. `git diff --check` passes.
- Local checks used Node 26.4. Normal CI must check the workflow
runtime.
- Full local typecheck, build, app, database, SDK, and provider runs
were not run. This two-file MJS fix uses pure tests and mocks.
- Normal CI
[41205375203](https://github.com/paperclipai/paperclip/actions/runs/41205375203),
attempt 1, passed on c7b5bf3238. Both required checks passed. Greptile
is 5/5. The optional automated coverage note has a recorded disposition
and is resolved.
- The original feature verdict, backend pass, and failed final reader
step remain separate. This change does not regrade that run.

## Risks

- Empty presentation links do not prove a server commit link. Source
identity comes from the trusted current GitHub context, selection, and
bound export.
- The separate job-run response remains required. All case, status,
attachment, and deadline checks remain active.
- The new reader has not yet run against the live service. CI and a
later authorized run must qualify delivery.

## Model Used

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

## Checklist

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 08:18:15 -05:00
DottaandPaperclip f2db909393 fix(ui): retain startup autosave through session recovery (#18412)
Reviewed and verified at a8783f8ace.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 07:51:09 -05:00
DottaandPaperclip d5766e4074 perf(chat): scope task questions and batch inbox queue checks (#18422)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Standing chats show recent messages and current task questions.
> - Recent-message pagination bounds history work, but it does not bound
question work.
> - The question read built the full company attention feed before it
selected the chat's tasks.
> - Each feed read also checked seeded queue membership with one insert
per item.
> - This pull request scopes question collection in the attention owner
and batches queue membership checks.
> - Chats keep their current question cards and initial layout while
doing less work.

## Linked Issues or Issue Description

Follow-up to #18358 and #18323. Related work: #18312.

**What happened?**

A hosted standing chat remained slow after recent-message pagination
shipped. On commit `4eaa435bf4`, an embedded-browser reload made the
conversation usable at about 8.6 seconds. Recent comments finished at
about 1.9 seconds. The pending-question request held the initial reveal
until about 8.4 seconds. That request called the complete company
attention feed and then filtered its results. The separate badge summary
also did broad work.

**Expected behavior**

Chat question cost should depend on the relevant tasks. Reading an
existing queue must not require a separate insert for every member.
Current access and decision policy must remain in force.

**Steps to reproduce**

1. Create a standing chat with questions on tasks assigned to its agent.
2. Add many unrelated tasks and pending questions to the company.
3. Open the chat from a fresh application cache.
4. Compare recent-comment arrival with the pending-question response and
content reveal.

**Paperclip version or commit**

Baseline: `909e29dd071b1aeeb24c2933af049da90a6066d3`. Its affected
services match the observed hosted revision `4eaa435bf4`.

## What Changed

- Add an internal task-question projection to the attention service.
Filter pending interactions by company, task IDs and question kind
before card enrichment.
- Keep the same access, audience, dismissal, queue, snooze, retention,
archive and training-example logic. Ranks are local to the returned
question list.
- Use the projection from the conversation receipt service. Keep current
chat audience and session checks there.
- Batch seeded membership inserts in groups of 500. Keep the queue lock,
conflict protection, audit events and activity logging for each new
membership. Existing members produce no new audit records.
- Add real PostgreSQL regression cases and a reproducible paired
benchmark. No schema migration or UI reveal change is needed.

## Verification

- `pnpm -r typecheck` passed. The final server typecheck also passed
after the queue change.
- `pnpm build` passed.
- Real PostgreSQL service coverage: 57 attention and chat-handoff tests
passed. Seven queue-route tests passed, including concurrent reads,
mixed existing/new items, duplicates, disabled seeds and audit
preservation.
- Red/green proof: the unrelated-attention regression fails with the
baseline conversation implementation and passes with the scoped read.
- `node scripts/check-module-boundaries.mjs` and `git diff --check`
passed.
- Full `pnpm test:run` was attempted and stopped with exit 130 after
embedded PostgreSQL startup failures and 17 failures in the untouched
native-session executor suite. It is not a local pass. The focused
Docker/PostgreSQL results above completed before Docker Desktop became
unavailable. A direct native PostgreSQL probe identified the host
semaphore limit (`could not create semaphores: No space left on
device`). No shared kernel settings or other test clusters were changed.
[Full
CI](https://github.com/paperclipai/paperclip/actions/runs/41162314995)
passed on `2809f096b3fb2c01b44a96a1b82a27809c9359df`, including all
eight browser shards. Final status: 55 successful checks/statuses, three
skipped and one neutral. Greptile is 5/5 with no findings or unresolved
threads. The fresh local browser retest is blocked because Docker
Desktop cannot start and native PostgreSQL cannot allocate semaphores.
The original hosted reproduction above is complete; no candidate browser
pass is claimed.

Local service benchmark: PostgreSQL 17.11, two relevant tasks, five
alternating pairs per scenario, after warmup. These are local service
timings, not a claim about deployed latency.

| Fixture | Read | Baseline median (range) | Candidate median (range) |
SQL calls |
| --- | --- | --- | --- | --- |
| 1,000 unrelated tasks/questions | Chat questions | 670 ms (632–1,905)
| 12 ms (11–15) | 1,076 → 22 |
| 1,000 unrelated tasks/questions | Company badge summary | 641 ms
(622–717) | 167 ms (161–171) | 1,068 → 69 |
| Small company | Chat questions | 38 ms (37–52) | 13 ms (12–16) | 52 →
22 |
| Small company | Company badge summary | 34 ms (33–39) | 34 ms (32–40)
| 44 → 43 |

All question fields and ordering matched, except rank is relative to the
scoped list. Summary fields matched except the generation timestamp. The
interaction plan changed from 1,002 selected rows to two rows through
the existing company/issue/status index. The benchmark loads baseline
attention, conversation and queue modules together so the queue change
cannot contaminate the baseline.

```sh
pnpm --filter @paperclipai/server exec tsx ../scripts/benchmark-chat-questions.ts \
  --baseline-ref=909e29dd07 --unrelated=1000
```

## Risks

- Scoped and complete feeds must share policy. This change reuses the
same attention collection and finalization path and tests dismissals,
named audiences, snoozing, archives and private access.
- Batched inserts must audit only new members. The concurrent PostgreSQL
test checks unique membership and one event/activity record per new item
across batch boundaries.
- Full inbox summaries still collect the company feed. The small-company
summary timing is unchanged. Other chat requests and transcript
hydration can still contribute to hosted latency.
- The first reveal still waits for question cards to preserve layout.
This follow-up has not been deployed, so its hosted effect remains
unverified.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` 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:37:47 -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 8c9dd1e444 test(runner): qualify Kimi Code lifecycle and recovery (#18029)
Add the Kimi lifecycle and recovery qualification harness. Preserve original grades and cleanup evidence, strict native ownership audits, bounded startup and cleanup, and early rejection of unsupported local fault execution before credentials or resources.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 22:54:37 -05:00
DottaandPaperclip b866fa4bdc feat(runner): add pinned Kimi Code native runtime (#18028)
Add the pinned Kimi Code runtime, native instruction and model admission, scoped credentials, and pending-candidate recovery contracts. Retain current master release attestations and provider-pack compatibility.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 21:58:12 -05:00
DottaandPaperclip d06c5e0eff fix(evals): preserve opaque TestOps parameters (#18394)
## Thinking Path

> - Paperclip verifies real agent work through Product E2E tests.
> - The fixed Chat feature workflow uses TestOps to select and report
one case.
> - TestOps exposes job parameters as ID/value pairs.
> - The schema does not establish that those IDs identify global
environment variables.
> - The reader used that unsupported relationship to infer parameter
names.
> - This pull request keeps IDs opaque, preserves the strict allowed
values, and records closed read diagnostics.

## Linked Issues or Issue Description

Refs: #18322, #18375, #18385.

**What happened?**
A zero-model bootstrap returned HTTP 404 during context readback. The
exact failed GET was not retained and remains unknown. Schema review
also found no established relationship between job-parameter IDs and
global environment-variable IDs, although the reader queried that
namespace to label parameters.

**Expected behavior**
Read only the existing job-run, launch, and job records. Preserve the
job's exact permitted ID/value vector without inventing parameter names.
Record which fixed GET class failed, its positive resource ID, state,
and available HTTP status without raw responses or URLs.

**Steps to reproduce**
Use the actual API helpers with a job-parameter ID that has no global
environment-variable definition. The new pure controls reject an
unexpected definition lookup and verify the opaque vector and
diagnostics without a backend or model call.

**Paperclip version or commit**
This change starts from `8595efc20bda3ce20a9fbbf34a5d156a6fcf6d57` after
#18385.

**Deployment mode**
GitHub Actions metadata setup in the protected TestOps reporting
environment.

## What Changed

- Remove the unsupported global environment-variable lookup from
job-parameter handling.
- Preserve an exact positive ID and `refs/heads/master` value. Use the
fixed workflow's existing `evaluate` default.
- Treat an operation parameter as such only when its ID matches the
protected configured ID and its value is allowed. Keep rejecting empty,
duplicate, conflicting, or unknown vectors before writes.
- Project only an opaque ID with a fixed-default-ref kind and value, or
an unresolved kind with the value withheld.
- Add closed diagnostics for the existing job-run, launch, and job GETs.
A successful call keeps HTTP status null because the API abstraction
does not expose the status.
- Sync one reporter-test assertion and document opaque IDs. Reporter
runtime and workflow source are unchanged.

## Verification

- Four new actual-helper controls fail on the parent.
- `node --test tests/runner-e2e/chat-feature-testops-api.test.mjs
tests/runner-e2e/testops-chat-reporter.test.mjs`: 58 affected
pure/mock/FS controls pass on Node 26.4.0.
- Three MJS syntax checks and `git diff --check` pass. TypeScript noEmit
was not run for this MJS/documentation change.
- Two intermediate exact-projection assertion failures were retained
before the assertions were synced to the new diagnostic contract.
- [Normal Node 24
CI](https://github.com/paperclipai/paperclip/actions/runs/41137009579)
passes on exact head `3c256fb8f7559093c5fb063170e26c01b6e8a0a4`: 48 jobs
passed and one skipped. Both required `ci / e2e` and `ci / verify` pass.
- Greptile reviewed this exact head at 5/5 with no actionable findings
or unresolved threads. At this verification cut, the optional
Contributor trust check was still in progress; it is not an effective
required status context.
- No actual CLI, API, provider, model, app, database, build, install, or
additional bootstrap was run to validate this change locally.

## Risks

The original HTTP 404 route remains unknown. Removing an unsupported
schema assumption does not prove that it caused that failure. The live
job mapping and dispatch remain unqualified. The strict source, actor,
selection, run-number, nonce, once-only send, private custody, case,
model, grader, and clock checks are unchanged. Unknown metadata still
stops. This PR adds no endpoint, workflow mode, permission, credential
path, or passing result.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) with reasoning, code editing, tool
use, and pure test review. The runtime does not expose the exact
context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 21:41:05 -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
github-actions[bot]andlockfile-bot 4eaa435bf4 chore(lockfile): refresh pnpm-lock.yaml (#18414)
## Thinking Path

> - Paperclip uses a dependency lock for reproducible builds.
> - Dependency changes on master need matching lock entries.
> - Paid eval reports also pin a reviewed offline correction.
> - Reports must install before paid model work starts.
> - This automated PR keeps the lock and report proof together.

## Linked Issues or Issue Description

**What happened?**

Dependency manifests on master changed after the last committed lock
refresh.

**Expected behavior**

Frozen installs must match those manifests. Eval reports must retain
matching offline lock proof.

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

- Refresh the dependency lock from the manifests on master.
- Include the matching offline report correction and hashes.

## Verification

- Pinned pnpm resolution completed with lifecycle scripts disabled.
- The report proof refresh accepted the reviewed committed baseline.
- The workflow rejected changes outside the lock and report proof files.

## Risks

The lockfile bot merges this PR without CI or review when every added
package version is at least 3 days old on npm. Otherwise the PR waits
for a maintainer, and the daily refresh tries again. The bot merges only
the exact commit this workflow generated from manifests already reviewed
on master. Unknown report lock baselines remain blocked. This update
changes no permissions or paid enable gates.

## Model Used

None — generated by pnpm and the deterministic report-lock updater.

## Checklist

- [x] Thinking path and problem description included
- [x] Generated lock and matching report proof included
- [x] Release-age gate decides between bot merge and maintainer review

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-10-31 01:23:29 +00: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
DottaandPaperclip 8595efc20b fix(evals): support official TestOps job metadata (#18385)
## Thinking Path

> - Paperclip manages AI agents and verifies real work through Product
E2E tests.
> - The fixed Chat feature workflow uses TestOps to select and report
one backlog case.
> - Official registration exposes a workflow-query URL and a Branch
parameter.
> - The existing reader accepts only workflow-file or numeric URLs, and
the admin launcher requires an operation parameter.
> - These assumptions reject valid official metadata before the feature
can run.
> - This pull request supports the exact observed form while preserving
source, selection, and once-only execution checks.

## Linked Issues or Issue Description

Refs: #18322, #18375.

**What happened?**
The second zero-model bootstrap stopped with a generic job-mismatch
code. Ordinary TestOps UI inspection then showed an official
workflow-query URL outside the accepted literals and a Branch-only job.
The exact first failed predicate in that bootstrap remains unknown.

**Expected behavior**
Accept that exact fixed-workflow URL. Preserve the existing master
Branch value when the job has no operation parameter. Keep rejecting
foreign URLs, unknown parameters, wrong branches, and conflicting
operation IDs before mutation.

**Steps to reproduce**
Pass the official query URL and Branch-only metadata through the
existing bootstrap, selection, and admin-launch owners. The new pure
controls exercise those actual helpers without a CLI, backend, or model
call.

**Paperclip version or commit**
This change starts from `0e15c92073a09e50df99190a37f69a86286b989b` after
#18375.

**Deployment mode**
GitHub Actions and the protected TestOps reporting environment.

## What Changed

- Share one exact URL predicate across bootstrap, evaluation selection,
and admin preparation. Add only the observed official workflow-query
literal.
- Support Branch-only, operation-only, and Branch-plus-operation jobs
with strict definition IDs, names, values, and duplicate checks.
- Preserve the exact master Branch value. Set an existing operation
parameter to `evaluate`; otherwise use the fixed workflow's existing
default.
- Use the same checked parameter vector for job and plan writes and
their readbacks.
- Report distinct fixed bootstrap predicate codes without response
values.
- Document when the protected operation-parameter ID is required.
- Align one existing Cloud-maintenance test with the inherited
managed-Cloud S3 policy. Preserve the same-version local-storage proof
in the parent, use valid synthetic Cloud settings in the child, and
check the expected provider mismatch without S3 requests. Retain the
no-seed and unchanged persisted-row assertions.

## Verification

- URL controls: three failures on the parent; all pass with the
correction.
- Branch controls: two failures and one correct rejection on the
predecessor; all pass with the correction.
- `node --test tests/runner-e2e/chat-feature-testops-api.test.mjs`: 40
owning pure/mock controls pass on Node 26.4.0.
- Two MJS syntax checks and `git diff --check` pass. TypeScript noEmit
was not run for this MJS/documentation change.
- The first [normal CI
run](https://github.com/paperclipai/paperclip/actions/runs/41131094974)
failed only in the managed-skill Cloud fixture and its dependent
verification gate: 46 jobs passed, two failed, and one skipped. The
tested merge included a new upstream policy that rejects the test's
local-disk Cloud configuration. The exact caught runtime exception
remains unknown.
- Three pure controls using the actual policy validator pass: the old
invalid Cloud fixture rejects, the new synthetic S3 fixture admits, and
an invalid master key rejects. An initial tsx wrapper IPC permission
error executed zero controls and remains a separate setup failure.
- The PostgreSQL/maintenance-child test was not run locally. On new-head
AWS CI, `managed-skill-content.test.ts` passed all 17 tests in server
shard 9.
- [Normal
CI](https://github.com/paperclipai/paperclip/actions/runs/41133876636)
is green on exact head `b76d5dd40d7711f1b5f6b6316b1114c0aae02d57`: 48
jobs passed and one skipped. Both required `ci / e2e` and `ci / verify`
pass.
- Greptile reviewed this exact head at 5/5 with no actionable findings
or unresolved review threads.
- No actual CLI, backend, model, provider, app, database, build, or
bootstrap was run to validate this correction locally.

## Risks

The exact original bootstrap predicate is still unknown. This fixes a
demonstrated metadata false negative and preserves the prior failed run.
Actual backend parameter types and integration dispatch still need
verification. Unknown metadata stops before the once marker and writes.
This PR changes no workflow, credential, case, model, grader, clock, or
private-evidence policy. It does not claim a passing feature result.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) with reasoning, code editing, tool
use, and pure test review. The runtime does not expose the exact
context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 17:04:59 -05:00
DottaandPaperclip 0e15c92073 feat(skills): make managed content independent of web-server disk (#18334)
## Thinking Path

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

## Linked Issues or Issue Description

**Subsystem affected**

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

**Problem or motivation**

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

**Proposed solution**

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

**Alternatives considered**

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

**Roadmap alignment**

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser use. The exact backend model ID and
context-window size are not exposed in this session. No subagents were
used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 16:18:27 -05:00
DottaandPaperclip d9354bbfc3 Add a portable agent question and answer resumption journey (#18346)
## Thinking Path

> - Paperclip helps people manage agent work and keep human decisions
attached to tasks.
> - Product E2E journeys verify the browser, native agent, saved state,
and cleanup.
> - The classic suite already checks a choice question followed by a
text question.
> - Deployment-targeted journeys need the same behavior on an attached
instance.
> - Production questions can use provider input, the dedicated semantic
tool, or the authenticated native API fallback.
> - The basic journey must verify the original card and native
continuation for each supported path.
> - This pull request shares the scenario and browser actions, adds
strict API receipt evidence, and verifies the saved document after
reload.
> - Separate tool-documentation qualification and the original failed
measurements keep their existing scope and outcomes.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

It adds portable coverage for answering agent questions and resuming the
same task on an attached deployment.

**Current behavior**

The classic suite has the two-question scenario. The portable catalog
does not expose it. Its shared native-path grader recognizes provider
and dedicated semantic receipts, but rejects a valid completed native
API creation receipt.

**Proposed behavior**

Expose `question-answer-resume` as a deployment-targeted journey. Answer
one choice question and one text question in the browser. Require
server-owned creation evidence, unchanged forms, exact board answers,
bound continuation, an agent-authored task document, and readback after
reload.

**Reason and benefit**

The same story can qualify local and hosted targets through their normal
provider setup and cleanup. It catches lost answers, duplicate or
foreign work, premature output, and stale documents.

## What Changed

- Register the journey with a three-run maximum and positive model
allowance. Accept one to three attributed work runs at both collection
and retained-result boundaries.
- Share the existing two-question scenario, browser answer actions, and
behavioral grader. Keep separate tool-documentation grading unchanged.
- Recognize a completed native API creation receipt only when its HTTP
201 result retains the original pending card, exact
task/company/agent/source run, idempotency key, and full normalized
form. Require the receipt to remain unchanged after the answer and
through the final checkpoint. Missing, pending, foreign, or altered
proof still fails.
- Check signed-in board ownership, each native continuation, no
premature or extra output, document authorship, and the saved revision
after reload.
- Wait for the authenticated product region before screenshots. Recheck
origin and path after readiness. Bound readiness and capture by the
campaign deadline.
- Add closed stage-specific errors, catalog coverage, sanitized receipt
calibration, and documentation. Include the provider-form and
browser-question presentation helpers in the definition fingerprint.

## Verification

- Fresh QA staging qualification passed at
`7f7de8be286a436010a48af89aba1727b4451493`: all 11 required checks
passed, cleanup passed, and all three native runs used the configured QA
target and model. The [sanitized run
report](https://pages.paperclip.ing/evals-qa-smoke-41121966520-1/)
records the measured pass. This is one successful qualification, not a
reliability claim.
- Final integration head `ae0d9d289831c770a413658d3520fb1dc8ad60e3`
contains the one main merge through
`fd008979f5794fda3d5f54151d36acd31d0de140` and an exact cherry-pick of
the four-file qualified search fix
`4edd10804e2b42941aa2038e90c362c13a0b98dc` from #18370. Patch identity
matches. It preserves the project and search registrations and atomic
search readback. The question live qualification ran at the earlier SHA
above; the final integration head has separate local and CI
verification.
- Eighteen question journey, helper, and test file blobs are identical
between the qualified and integration SHAs. This includes clarification
flow and evidence, question grader and browser helper, the sanitized
receipt fixture, screenshot helper, provider-form helper, browser
question presentation, continuation scenario/readiness/flow, shared
agent validation, and user actions. The question run-count contract and
dispatch branch are also unchanged. Reviewers can compare those paths
directly between the two commits.
- All 622 selected Product E2E, catalog, question-resumption,
necessary-question, report, and readiness tests pass after the main
merge. After the exact search delta, all 145 narrow
question/search/project/contract tests and all nine real Chromium search
regressions pass. Map checks, combined credential-free preview, source
fingerprints, and the earlier workspace-link preflight pass. The local
TypeScript attempt reports stale Runner declaration errors for
`onAccountingEvent` in unchanged native-session code; fresh official CI
provides the clean-build type gate. The three search source/test blobs
match the qualified search merge, and the three project source blobs are
unchanged.
- An in-memory probe executes the actual launcher fingerprint
expression. Each project, search, and question implementation input
changes the digest. Separate red probes first reproduced the omitted
provider-form and browser presentation helpers; both pass after their
source inputs are added.
- The sanitized retained native API response-shape regression fails
before the grading correction and passes afterward. Negative controls
reject missing, pending, foreign, changed, spoofed, or wrongly bound
receipts, answers, continuation, model, environment, and document
evidence. All nine provider/semantic/API path combinations pass
calibration.
- The real local Chromium screenshot probe fails before the readiness
repair and passes afterward. Login redirects and sign-in pages at task
URLs remain excluded with no screenshot files.
- The two original attached failures remain retained: the first stopped
at early screenshot capture; the second stopped before answering at the
former API provenance gate. An earlier sandbox run also retained one
report subprocess failure; the full selected tests then passed with
local subprocess IPC access.
- The prior integration CI had an unchanged canary mock `EADDRINUSE`
failure. That history is retained; its documented retry is owned by the
coordinator. No application API, schema, production UI, model, runtime
policy, credential, or deployment configuration change is included.
Final integration head ae0d9d2898 passed
all 58 CI checks, the external Snyk status, and fresh Greptile 5/5 with
no unresolved findings. This clean CI includes the official TypeScript
and build gates. Recurring selection follows merge and a separate normal
TestOps job verification.

## Risks

An API result must prove native creation; form shape and run count
cannot establish it. The grader checks the server receipt, exact scope,
unchanged card and receipt, real board answers, and bound native
continuation. The shared answer helper still serves classic journeys.
The screenshot wait affects attached journeys and remains limited to the
authenticated product region and campaign deadline. One live QA pass
establishes the measured journey outcome at the qualified SHA. It does
not establish reliability across models or deployments. The integration
SHA preserves its journey and helper blobs, while shared registry
changes receive fresh CI and review.

## Model Used

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 16:18:21 -05:00
DottaandPaperclip a1845b3b64 fix(evals): capture TestOps registration after watch (#18375)
## Thinking Path

> - Paperclip manages AI agents and verifies their work through Product
E2E tests.
> - The fixed Chat feature workflow prepares a TestOps case and plan
before any model run.
> - Its first zero-result bootstrap completed, but the watched child did
not receive the generated job-run ID.
> - The official watch log contained a job-run ID, so the missing child
variable did not prove that registration was absent.
> - This pull request reads official context after watch and validates
the linked backend records.
> - The workflow retains closed registration metadata and stops on
unknown or foreign context.

## Linked Issues or Issue Description

Refs: #18322.

**What happened?**
The successful zero-result bootstrap retained
`official_job_run_id_missing` from its watched child. It could not prove
the backend job and workflow binding needed for the next setup step.

**Expected behavior**
After successful watch, read the generated context, validate its current
GitHub run and fixed workflow, and retain only closed IDs and parameter
metadata.

**Steps to reproduce**
Run the fixed workflow's `bootstrap` operation on master. Inspect its
setup artifact after watch completes. No evaluation or synthetic passing
result is needed.

**Paperclip version or commit**
The original bootstrap used merged #18322. This follow-up starts from
`76fde891ccc29283b3f5c8dcdce089c5b3d937d1`.

**Deployment mode**
GitHub Actions metadata-only setup in the protected reporting
environment.

## What Changed

- Run an internal context reader after successful bootstrap watch in the
same protected step.
- Parse only numeric official job-run and launch IDs in memory. Do not
log or save raw command output.
- Validate current-run, project, launch, job, workflow, and bounded
parameter metadata before writing an exclusive registration receipt.
- Retain the two known registration receipt paths with the existing
setup artifact.
- Preserve the original inside-watch receipt, case reconciliation,
provider isolation, and evaluation limits.

## Verification

- `node --test tests/runner-e2e/chat-feature-testops-api.test.mjs
tests/runner-e2e/testops-chat-reporter.test.mjs`: 48 pure/mock/FS
controls pass (36 prior and 12 new). The actual local Node version was
26.4.0. Normal Node 24 CI remains required.
- Four MJS syntax checks and `git diff --check` pass. No TypeScript
noEmit claim is made for this MJS-only helper change.
- Actionlint passes for the changed workflow.
- Normal [GitHub Actions
CI](https://github.com/paperclipai/paperclip/actions/runs/41123894542)
passes on exact head `58396de10f0c49294b0bbc0f4709c29990d57d53`: 48 jobs
succeeded and one skipped. Both required `ci / e2e` and `ci / verify`
pass.
- Greptile reviewed that exact head at 5/5 with no actionable findings
or unresolved review threads.
- No local CLI, provider, model, app, database, or build qualification
was run. No replacement bootstrap or paid evaluation was dispatched.

## Risks

The official context or backend DTO shape can differ from the supported
format. The reader then stops with a closed failure receipt. Pure tests
do not qualify the remote CLI or backend. The original zero-result
bootstrap and its missing child-context observation remain part of the
history. The case's actual outcome remains unmeasured.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) with reasoning, code editing, tool
use, and pure test review. The runtime does not expose the exact
context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 16:07:04 -05:00
DottaandPaperclip 4edd10804e fix(evals): batch task search result readback across renders (#18370)
## Thinking Path

> - Paperclip lets people manage AI agents and saved work.
> - Product journeys check user actions against saved state.
> - The task search journey compares the exact visible task identities.
> - A search can replace rows while the harness reads an old indexed
locator.
> - The attribute read can then time out after the correct results
appear.
> - This pull request reads the visible links together and preserves
strict result checks.

## Linked Issues or Issue Description

Refs #18355.

**What happened?**

An attached Cloud attempt passed the task search journey. A later
attempt on the same harness and app revision failed at search-result
readback. Its owned screenshot showed the correct target and completed
control. Authentication, collection, and cleanup passed. The failure
remains recorded and the journey has not been admitted to the daily
plan.

The reader called `all()`, then awaited `isVisible()` and
`getAttribute()` for each indexed locator. When a search replaced the
old collection between those reads, the next attribute read waited for
an index that no longer existed.

**Expected behavior**

Read the matching visible links together. Compare the complete identity
set against the owned target and controls. A render transition must not
consume the whole poll deadline on a stale row index.

**Steps to reproduce**

1. Render three task links in the task collection.
2. Let the reader observe the third link as visible.
3. Replace the collection with the two correct search matches before its
attribute read.
4. The old reader times out waiting for `nth(2)`, even though the two
correct rows are present.

## What Changed

- Read visible link attributes in one batch. Discard a detached snapshot
and retry within the existing poll deadline.
- Keep the exact identity comparison, duplicate detection, control
exclusion, saved-content checks, and zero-run checks.
- Add a real Chromium render-transition regression and invalid-result
cases. Extend the stateful flow test for a detached snapshot.
- Document the readback boundary. No app UI, target configuration, or
cleanup behavior changes.

## Verification

- Review follow-up: the existing journey wait helper is now exercised
with the real Playwright poll. Its first read evaluates the actual
reader callback on detached browser DOM nodes and returns no evidence.
The second read contains an extra owned control. Only the third, exact
pair succeeds. The test observes all three reads. The 30-second deadline
and grading behavior are unchanged.
- Rebased onto current master, including the merged project journey.
Credential-free discovery confirms exactly one `project-task-context`
and one `task-search-filter` entry.
- Latest rebased checks passed: all nine Chromium search regressions,
all 381 Product journey unit tests, runner typecheck, discovery, maps,
and diff checks. Exact head 183c3e1d19
passed all 58 CI checks, external Snyk status, and fresh Greptile 5/5
with no unresolved findings.

- Red: the real Chromium transition test failed on the old reader with
`locator.getAttribute: Timeout 150ms exceeded`, waiting for `nth(2)`.
The short timeout bounds only this regression fixture.
- Green: all nine credential-free Chromium search tests passed. They
cover the transition, duplicate/extra/unknown/wrong destinations,
visible-link scope, and status-label behavior.
- All 131 focused search/oracle/contract/campaign tests passed.
- Runner typecheck passed: `node node_modules/typescript/bin/tsc -p
tests/runner-e2e/tsconfig.json`.
- `node scripts/check-maps.mjs` and `git diff --check` passed.
- Fresh QA staging acceptance passed at this exact head: all five
checks, authentication/setup/journey/collection/cleanup phases, and zero
agent runs. The [measured QA
report](https://pages.paperclip.ing/evals-qa-smoke-41124961876-1/)
preserves current source and measurement provenance. Daily admission
follows merge and a normal TestOps job verification; the earlier failure
remains recorded.

## Risks

- The fix uses the existing Playwright visible-element predicate and
task-link selector. A future UI selector change can still fail the
journey.
- A detached snapshot returns no evidence. It cannot satisfy a nonempty
expected result set. The original poll deadline stays in place; there is
no added journey retry.
- Browser fixtures prove the readback mechanism. They do not replace the
required live Cloud pass.

## Model Used

OpenAI Codex, GPT-6 family. The host does not expose an exact model
version or context limit. Used repository tools, TypeScript checks, and
fresh local Chromium contexts.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 15:51:28 -05:00
DottaandPaperclip 6dcf4160dd perf(chat): load recent messages and page history on scroll (#18358)
## Thinking Path

> - Paperclip lets people manage work done by agents.
> - A standing agent chat can hold months of conversation.
> - The chat route forced full-history mode, bypassing compact task
loading.
> - A cold visit fetched lifetime run summaries and hydrated historical
transcripts.
> - This PR starts with 20 recent messages and loads earlier pages on
upward scroll.
> - It preserves the reader's position, current questions, and draft
while history grows.

## Linked Issues or Issue Description

**What happened?**

Standing agent chats forced full-history loading. A long conversation
fetched full activity and run history before it became readable. Earlier
comments also used an explicit load control.

**Expected behavior**

Open a small recent conversation quickly. Load older messages when the
reader scrolls upward. Show an inline loading state. Keep the visible
message and composer mounted through paging, live updates, and Back
navigation.

**Steps to reproduce**

1. Open a standing agent chat with hundreds of messages and completed
runs.
2. Use a fresh browser query cache.
3. Observe full activity and run reads plus transcript requests for
historical runs.
4. Compare the recent window and upward paging after this change.

Related work: #18312 and #18323 restored compact task and collection
loading. #14848 added reopening of visited agent chats. A GitHub search
found no open PR for this chat-history optimization.

## What Changed

- Return 20 contiguous recent comments for standing chats, with a stable
oldest cursor. Keep the existing compact task exchange contract. Use the
existing company/issue/time index for cursor reads.
- Keep chats compact even if their task view previously expanded
history. Retain observed messages through live catch-up and cache-backed
return visits.
- Keep fetched history pages, acknowledged sends, and the observed
recent cursor separate. Reconcile live replies without losing history
after a send or deleted cursor.
- Hydrate metadata only for newly revealed message/run IDs; preserve
prior batches while paging. Slow-send recovery refreshes the recent
window. Receipts failures have an independent retry.
- Hydrate run summaries only for loaded messages and the latest turn.
Validate batches of at most 100 run IDs and keep the existing
issue/company access rules.
- Reuse hydrated terminal native streams when only history membership
changes. Preserve retry, resume, mode changes, reconnect recovery, and
interrupted recovery reads.
- Load older messages, decision receipts, and task handoffs through
upward scrolling. Support wheel, touch, and keyboard input. Keep pending
questions visible.
- Reserve a status slot while loading. Preserve a logical message anchor
and the mounted composer. Pause failed page reads until an inline Retry.
- Add database, route, controller, and scroll regressions, plus an
opt-in production-build browser rig for long chats on desktop and
mobile. Update design and feature/access documentation.

## Verification

- The real PostgreSQL cold-open suite passes all 12 tests, including
contiguous pages with equal timestamps, complete history, company
denial, and scoped run IDs.
- Activity route and OpenAPI suites pass 53 tests. The route run allowed
local cold-import overhead; CI retains the repository's normal timeouts.
- Three new paging regressions fail against the unchanged source. The
candidate's focused paging/window suite passes 26 tests. Broader UI
verification is recorded below when complete.
- Desktop and mobile browser acceptance covers recent-only startup,
per-frame reveal geometry, delayed and failed older pages, stable
reading anchors and drafts, Back, older comment links, and one persisted
live reply.
- Full workspace typecheck and build passed locally. The final UI source
also passes its typecheck and production build.
- Affected UI suites pass: 212 controller/history/paging tests, 352
thread/scroller tests, 26 native-stream tests, plus metadata batching
and live-cache hydration coverage. The issue mutation/access route suite
passes 179 tests.
- All 22 final desktop/mobile browser journeys pass, including delayed
image growth. The isolated second-page request proof also passes six
repeated desktop/mobile runs. A separate 6,000-message, 3,000-run
fixture passes cold-open and delayed-paging checks on both screen sizes,
still opening 20 messages and loading one 50-message page.
- Final matched production timings use baseline `aa58fa1073`
(`index-BaRiMbxd.js`) and candidate UI source `f9a26b9783`
(`index-DPWTbsFF.js`, identical application source at final head
`bf71ffd5af`). Chromium 151.0.7922.34, 1440×900, 4× CPU throttle, no
added network latency, browser HTTP cache disabled, fresh application
cache for each cold visit. Both variants block service workers and use
the same warm local API server and immutable 600-message/300-run
fixture. Only document HTML is intercepted for both variants; API
requests are real. The common API revision is `109981f8c1`; subsequent
commits change only UI and tests.

| Usable conversation | Baseline median (range) | Candidate median
(range) |
| --- | --- | --- |
| Cold direct URL | 6.57 s (5.69–7.45) | 3.07 s (2.50–3.28) |
| Warm in-app return | 3.76 s (3.54–4.76) | 0.67 s (0.58–1.46) |
| Back return | 2.53 s (2.12–4.20) | 0.51 s (0.47–1.18) |

Five pairs alternate order. Every paired difference favors the candidate
for all three journeys. Readiness requires a revealed, fully visible
latest reply above the composer and an editable composer. Return timing
starts after the Tasks route renders. Cold API requests fall from
953–954 to 71; API wire bytes fall from 517–559 KB to about 49 KB.
Separate CPU profiles and request waterfalls confirm the removal of
lifetime event hydration and are excluded from the five timing pairs.
Both variants have the same expected missing optional plan document
(404) and no browser exceptions. Control recent-window API reads have
medians of 37 ms / 32 ms, with shared-host outliers up to 376 ms.

The 6,000-message recent-window SQL uses
`issue_comments_company_issue_created_at_idx` (22 index rows read for a
21-row probe). Geometry assertions retain a 2-pixel tolerance for the
reading anchor and first-reveal layout. These are local synthetic
measurements, not deployed staging latency. Earlier timing probes are
excluded because they did not isolate service workers or composer
clearance. Final head `bf71ffd5afb5684ba9105a3127f617e7adf5139c` has 55
successful checks, three optional skips and one neutral result, with no
failures or pending checks. Greptile is 5/5 with no open review
findings.

### Failure record

Early local attempts exposed an unconditional scroller wrapper that
changed the old task layout, and automatic retries on chat page
failures. Both were corrected. The original task scroller structure
stays in place. Metadata request assertions wait for initial connection
recovery to settle, then verify only the new page’s reads;
retry/resume/reconnect revalidation remains intentional.

The initial review caught a send-before-scroll cache defect; its
controller regression failed before the fix. Later rapid-paging checks
caught scroll readiness being gated by metadata after the first reveal;
readiness now stays enabled once revealed. Live replies use the separate
acknowledged-message cache, then catch up from the server cursor.

Visual review exposed a pagination wrapper bypassing existing composer
clearance. The body is again a direct scroller child; cold-open browser
checks require the full latest reply above the composer. A
resize-observer regression failed before the fix and now passes.
Controlled delayed inline images prove both pinned following and a
stable reading anchor on desktop/mobile.

The first performance fixture lacked valid native event envelopes and
caused missing-log fallbacks. It is excluded from latency claims. The
final fixture uses saved native assistant events and conversation
session generations. The live test uses a temporary fixture-agent key,
attributes the reply to an existing synthetic run, and revokes the key.
It starts no model or agent process.

Local database attempts failed during a Docker shutdown. The retained
disposable database was restored and its suite passed. Early fixture
errors included a missing conversation identity field and session
generation. Mobile test setup also selected an offscreen sidebar link
and reused queued human input. Optional announcements could intercept
input; the fixture now dismisses them before the journeys. The scroll
observer now waits for the delivered wheel event and settled animation
frames, including when the viewport is already at the top. A
concurrently running live test briefly changed another probe’s row
count; the final acceptance and timing runs were sequential on separate
fixtures. The final rig uses the visible mobile navigation and a saved
agent reply. Anchor observation waits for the user's scroll to settle
before measuring the effect of live updates.

The full local `pnpm test:run` attempt hit repeated embedded PostgreSQL
initialization failures and failures in untouched native-session
executor suites; it was stopped after the repeated environment failures.
The targeted real-PostgreSQL suite passed, and final-head CI is required
before handoff. The first CI run also caught an exact mock expectation
missing the added company scope; the expectation is updated and its
179-test suite passes. The final-head first CI attempt also stalled an
assigned child task in the existing plan-approval scenario, then hit a
heartbeat-run row lock timeout during fixture cleanup. The failed shard
and aggregate check passed on an unchanged rerun of the same commit.
Scenario assertions and timeouts were unchanged. The failure and rerun
are retained in [CI run
41116120430](https://github.com/paperclipai/paperclip/actions/runs/41116120430).

## Risks

- Historical transcript diagnostics no longer load on a cold chat open.
Saved messages and conversation events remain available; diagnostic run
views keep their full records.
- Cursor paging must not omit comments with equal timestamps. Database
tests cover timestamp/UUID ordering and the complete set.
- Prepended or late content can move the reader. Browser checks cover
retained row identity, viewport offsets, mounted drafts, and Back.
Previously loaded pages stay in the query cache for its existing
lifetime.
- Local synthetic evidence does not establish deployed staging latency.
This PR does not merge or deploy the change.

## Model Used

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 15:12:24 -05:00
DottaandPaperclip 9e1735ec17 test(evals): add a fixed TestOps AWS chat feature route (#18322)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect their saved work.
> - Chat feature evaluations test a real request against saved tasks,
audit records, links and reload behavior.
> - The current suite has Codex and OpenCode cells but no dedicated
runnable DeepSeek 1017 backlog plan in TestOps.
> - TestOps must select the real case before the workflow can access a
model key.
> - This PR adds one fixed, default-branch AWS route for native OpenCode
and DeepSeek 1017.
> - The route keeps original evidence private and sends only a verified
result and approved screenshots to TestOps.

## Linked Issues or Issue Description

**Subsystem affected**

Product E2E evaluation definitions and GitHub Actions delivery.

**Problem or motivation**

A dedicated TestOps plan cannot run the existing backlog chat journey
with native OpenCode. A result must prove saved work and cleanup rather
than report that a model call completed.

**Proposed solution**

Add one OpenCode backlog cell and one fixed public workflow. TestOps
selection validation runs in a token-isolated job before builds or
inference. The workflow retains private originals and reports the bound
outcome to the selected TestOps case.

**Alternatives considered**

A private-repository wrapper would need a new cross-repository GitHub
write credential. The new route uses the existing TestOps GitHub
integration instead. Existing manual candidate approval paths remain
separate.

**Roadmap alignment**

This extends the existing feature evaluation infrastructure. It changes
no production feature, global runtime default or model default.

Current main #18319 supplies the v2 grader, delegation queue accounting
and final screenshot capture; these improvements are preserved. Related
product work: #16814 and #17126 concern backlog handling. This PR
changes neither product implementation and does not claim those changes
are required.

## What Changed

- Add exactly one native OpenCode backlog cell with DeepSeek 1017 under
the separate `runner-opencode-deepseek-1017` profile. Preserve all four
existing Codex and production OpenCode cells and their models.
- Add a default-branch-only workflow with fixed evaluation, zero-result
registration and one plan-launch modes. Require GitHub actor checks and
authenticated singleton selection before inference.
- Add a separate shipped-main evidence authority. Reuse the existing
strict private storage, scanners, inventories and scoped AWS sessions.
- Bind sanitized results, generated JUnit and producer-approved
screenshots to the exact source, run, attempt and case. Keep failed
grades and cleanup failures failed.
- Add TestOps API, CLI and result adapters with pure controls and normal
unit-test wiring. Keep the reporting token out of the evaluated process.
- Verify the current server case result and attachment metadata after
upload, without masking an earlier failed upload or evaluation.
- Apply only the existing reviewed lock correction, verify unchanged
tracked dependency inputs and bind the lock receipt across the
compiled-output handoff before frozen installation.
- Bind the initial administrator launch to one approved workflow run
number and live GitHub source/actor metadata before TestOps
authentication. Use bounded REST case reconciliation and only the
reviewed existing GitHub integration.
- Make two existing CI tests observe their intended state
deterministically: a fake clock for copy-feedback lifetime and a
completed-pass barrier for retry-cancellation batches. Production
behavior and the original assertions remain unchanged.

The two test-only fixes are intentionally included because their
observation boundaries blocked this delivery’s required normal CI. They
preserve every original assertion and change no production behavior. The
original failed runs remain recorded, and the exact causes of those
observations remain unknown.

## Verification

- 157 focused profile, catalog, oracle, filesystem admission, export,
private-path and workflow controls passed on the current-main
composition. The existing stock OpenCode models and the new exact
DeepSeek 1017 selection are checked separately.
- 44 API, CLI, filesystem and post-upload readback controls passed,
including foreign selection, changed hashes, unsafe files, failed
outcomes, expired readback and no-resend behavior.
- The new exact private session and trace layout controls produced four
genuine parent failures and pass with the selected-path extension. The
frozen 244-case candidate approval registry remains unchanged.
- The lock guard has seven filesystem controls plus seven existing
canonical-owner controls. The unrestricted old workflow failed its
actual policy calibration; the corrected frozen-install route passed.
- Eval-owning TypeScript checks, workflow lint and Git whitespace checks
passed. The separate UI test correction was checked with the focused
jsdom unit suite. The server test barrier has pure wrapper and real
scheduler controls; its DB-backed route was not run locally. No
additional local typecheck/build was run for these test-only changes.
- Full native builds, provider execution, app/database behavior and
TestOps registration are reserved for GitHub Actions/AWS. They have not
run locally.
- The initial normal CI run failed the new-workflow policy allowlist and
a heartbeat scheduling assertion. The policy fix has an actual parent
red/current green control and rejects five unsafe route variants.
Heartbeat source is unchanged and its failure cause remains unknown. The
original run is retained.
- The launch-fence actual caller fails against the published parent and
passes the five own-run contradiction controls before authentication.
- The prior `a5aa359d` normal CI completed successfully. The complete
`f9e1f289` run passed all leaf jobs except an existing copy-feedback UI
assertion, plus its dependent verification gate. The four owning UI
files were unchanged from the earlier passing head and actual tested
merge; the exact scheduling cause remains unknown.
- The correction changes only that test to actual React `act` and a
scoped fake clock. All eight component tests pass; early-hide and
never-clear source variants each fail the intended lifetime assertion.
Production clipboard/card behavior is unchanged.
- The `2f27f3fc` run passed the corrected UI shard and every leaf job
except the existing retry-cancellation intermediate-count assertion,
plus its dependent verification gate. The seven relevant owners match
the earlier passing run and historical source comparison; the exact CI
scheduling cause remains unknown.
- The test-only barrier observes a persisted completed worker pass
before asserting the unchanged 20-item cap and two-company fairness,
then releases it for the original 29-item drain and 180-second idle
check. Two extracted-wrapper controls and three actual scheduler
controls pass. The real DB-backed test awaits AWS qualification.
- On `836e80ac`, both repaired test shards passed in AWS. The original
attempt retained a separate E2E cleanup HTTP 500 from a PostgreSQL lock
timeout and one runner shutdown. No production repair or precise
contention/shutdown cause is claimed.
- Exactly one targeted retry of E2E shard 3 and its aggregate gate
passed in attempt 2; exactly one recovery of the interrupted server
shard and its verification gate passed in attempt 3. Other passed jobs
were carried forward. The final normal run is successful. No
whole-workflow retry or evaluation/model retry was launched.
- Both literal required checks (`ci / verify` and `ci / e2e`) are
successful on the exact final source `836e80ac`. Greptile is 5/5 and no
review threads remain open. Actual TestOps registration and the
OpenCode/DeepSeek feature result remain unqualified until their separate
executions.

## Risks

- Actual zero-result registration, tenant API shapes and
public-repository dispatch access must be checked before the first
evaluation. Missing or ambiguous metadata stops the route.
- The real OpenCode/DeepSeek backlog result and Allure outcome remain
unqualified until that run. No passing result is seeded.
- One human query, one accounted work run, 120-second turn, 420-second
attempt, 300-second settled-state bound and zero retries remain
unchanged. Setup usage is outside work accounting and stays unknown.
- The reporting token was configured through the separately reviewed
protected credential bootstrap. It is unavailable to AWS evaluation
jobs.
- Metadata reconciliation is capped at ten pages, 1,000 cases and four
parallel detail reads. Missing or inconsistent metadata stops before
inference. The initial administrator launch counter must be created once
after registration; it does not restrict normal TestOps Run actions.
- Existing manual workflows, historical evaluation grades and candidate
approval records remain unchanged. The original CI failures are
preserved; the test corrections do not establish retrospective causes.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) with reasoning and tool use. The
runtime did not expose its context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 15:08:16 -05:00
Dotta a4308b9791 test(e2e): add browser project and task context journey (#18353)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People group tasks into projects and use those projects to keep work
in context.
> - Deployment journeys already test task creation and assignment.
> - They do not yet prove that a new project and its task keep the same
saved relationship after reload.
> - This pull request adds an explicit browser journey for that gap.
> - Independent API reads and visible task properties must agree on the
exact records and selected settings.
> - The journey uses no model runs. Each deployment must pass before a
daily plan can include it.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The deployment-targeted Product E2E suite can now check project creation
and task context through the production dialogs.

**Current behavior**

The suite covers standalone task creation and assignment. It does not
prove that a newly created project contains the task selected in the
composer, or that the relation survives reload.

**Proposed behavior**

Select `project-task-context`. Create a unique project and a
self-assigned task with that project selected. Reopen the project, open
its task, and reload. Require exact saved company, project, title,
prompt, user assignment and standard work mode. Require no agent runs
before or after reload.

**Reason and benefit**

The same journey can qualify different deployments. It catches lost
project links and incorrect saved context without a model call or a
separate QA-only test implementation.

## What Changed

- Add the browser flow and an independent saved-state oracle with
positive and negative cases.
- Scope project and task navigation to unique links in the main content
so sidebar links cannot bypass list coverage.
- Bind reopened routes to saved project and task references. Verify the
main project heading and visible task content instead of a hidden
duplicate sidebar label. Keep browser failures as closed stage codes.
- Register the journey, its closed success checks, and its source files
in the definition hash. Default model-matrix selections stay unchanged.
- Associate qualification-report coverage with project lifecycle,
project task context and task creation. Reject retained browser-only
passes containing run IDs, provider/model metadata or native/legacy
execution.
- Add `project` to the existing durable ownership resource contract. A
target provider remains responsible for cleanup of its own project
fixtures.
- Update discovery expectations, the deployment journey guide and the
projects feature map.

## Verification

- Focused runner tests: 110 passed across the new oracle, discovery,
journey contracts and existing report subprocess checks. The first
sandboxed attempt blocked the existing report subprocess IPC socket; the
same selection passed with local IPC enabled.
- Late review regression checks: both report association and unexpected
browser-only model work reproduced as failing tests before the fix. The
final contract, saved-state oracle and report catalog selection passed
all 72 tests. Runner typecheck passed again after these changes.
- Browser readback: the old project-name selector failed in Chromium
when a hidden sidebar label preceded the production project heading. All
six browser regression cases now pass, including missing rows, wrong
project/task destinations and a wrong project property. The fixture uses
the production heading and task-row overlay conventions. Credential-free
Node 24 imports pass.
- Current-master integration: 208 focused catalog, project/search,
campaign and reporting tests passed. All nine project/search browser
regressions passed. Runner typecheck, map checks and Node 24 imports for
both journeys passed. The combined catalog, dispatch, source hashes,
success checks, browser-only guard and feature associations retain both
selections.
- The first deployment qualification created both owned records but
failed during later readback with a generic browser code.
Authentication, setup, collection and cleanup passed. That failed grade
is retained. The corrected source subsequently passed a fresh attached
QA campaign; the original failure remains preserved.
- New oracle alone: 7 tests passed after the final catalog mapping
change.
- `node scripts/check-maps.mjs` — passed; structural checks only.
- Credential-free `--suite product-journeys --list` — passed and lists
this browser journey.
- `node node_modules/typescript/bin/tsc -p
tests/runner-e2e/tsconfig.json` — passed after building required plugin,
runner and eval-kernel declarations. The initial fresh-checkout check
failed because those declarations were not built.
- All current-head CI gates passed, including repository typecheck,
tests, build and browser checks. Greptile reviewed the exact head at 5/5
with no unresolved findings. Fresh attached QA passed at
`f19557c9eebde14c2def37195d6b154c23eb9690`: [sanitized
report](https://pages.paperclip.ing/evals-qa-smoke-41119722363-1/). All
five independent checks and authentication, setup, journey, collection
and cleanup passed; zero agent runs started.

## Risks

- This adds an opt-in test and changes no production behavior or schema.
UI control changes can fail the journey.
- The target provider must support durable `project` ownership before it
can run this case. Project cleanup must settle owned tasks, reject
foreign linked tasks and archive the project while preserving history.
- Source registration alone does not include the candidate in any saved
daily plan. A fresh pass against that deployment is required first.

## Model Used

- OpenAI Codex, GPT-6 family, with code inspection and tool execution.
The host does not expose the exact underlying model 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 (no duplicate journey found)
- [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-30 15:07:21 -05:00
DottaandPaperclip a0e3ac62a7 test(evals): add reusable task search and filter journey (#18355)
## Thinking Path

> - Paperclip lets people manage AI agents and their work.
> - The task list lets people find saved work and open its context.
> - Product journeys can exercise the same task UI on local and Cloud
targets.
> - The shared suite lacks a search and status-filter journey with
control tasks.
> - This pull request adds that journey with exact task identity checks.
> - The benefit is reusable evidence that search, filters, and task
navigation work together.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Product E2E coverage for task search, status filters, and saved task
navigation.

**Current behavior**

The shared journey suite covers task creation and assignment. It does
not prove that a search excludes an unrelated task, that a status filter
excludes a matching completed task, or that the selected task retains
its saved content.

**Proposed behavior**

An explicit `task-search-filter` selection creates three owned tasks. It
searches through the production task list, applies Backlog, and opens
the exact target. It verifies reload and Back navigation, saved task
fields, and zero agent runs for all three tasks.

**Reason and benefit**

The same journey can run against a managed local stack or an attached
Cloud target. Independent assertions reject missing evidence and
plausible wrong results. Deployment qualification and daily-plan
admission remain separate gates.

**Breaking changes**

None. Existing journey selections keep their behavior.

Related work: #16979 fixes status filtering before pagination. #15403
covers saved task views. This journey tests the existing search/filter
interaction and does not add a new UI or saved-view feature.

## What Changed

- Add a zero-run browser journey with one target and two owned controls.
- Compare exact visible task identities after search, filtering, reload,
and Back navigation.
- Verify saved company, owner, title, description, status, and zero
agent runs through the public API.
- Register dispatch, source hashing, closed success checks, and browser
reporting validation.
- Add adversarial oracle tests and a campaign dispatch test. Document
the selection and its feature-map scope.
- Exercise the real browser flow with a stateful UI/API port across
Coordinator, combined Tasks, and legacy shells. Inject missing
ownership, wrong destinations, lost filters, changed saved context, and
unexpected native work.
- Use the combined Tasks shell's named Backlog view for reload
persistence, as required by its existing view-preset contract. Preserve
the successful polled result snapshot and link the case to feature
coverage.

## Verification

- First attached Cloud attempt failed during Backlog selection. Its
cleanup passed and it started no model work. The original failed result
is preserved; the corrected candidate passed a fresh attached campaign
below.
- Local Chromium reproduces the cause: the legacy StatusIcon and text
label produce the accessible checkbox name `BacklogBacklog`, so the
prior exact `Backlog` lookup finds no status control.
- The selector now stays inside the Status group and accepts the
explicit and duplicated names. Three real Chromium regressions pass,
including a separate assignee called Backlog.
- Latest focused journey checks: 130 passed. Runner typecheck and map
checks passed. Unexpected browser/API failures retain only closed
source-owned stage codes. Screenshot privacy guards and all exact
identity, content, filter, and zero-run checks are unchanged.
- Fresh attached Cloud qualification passed at
`e3dfc0ae37e8ac74e9a07ca24421ea6c96f9bcfc`: [sanitized
report](https://pages.paperclip.ing/evals-qa-smoke-41114233380-1/). All
five independent search/filter/reload/reopen/no-agent checks and all
five phases, including cleanup, passed. The browser journey started zero
agent runs.

- Runner typecheck passed: `node node_modules/typescript/bin/tsc -p
tests/runner-e2e/tsconfig.json`.
- Focused oracle, contract, and campaign tests passed: 101 unique tests.
The campaign suite was rerun after its new dispatch test: 30 passed.
- Direct browser-flow tests passed: 23 tests. These call the real
`taskSearchFilter` function through a stateful UI/API port. They do not
establish live browser or Cloud qualification.
- Latest focused search, oracle, catalog, and report checks passed: 127
tests across five files.
- Full runner Vitest completed with 5,204 passes, two skips, and three
failures outside this change. Two local embedded PostgreSQL fixtures
failed at bootstrap. The Pi controls test expects profile version 35
while the unchanged base declares 37. These failures remain recorded;
the PR does not change those fixtures or pins.
- The remaining Node support suite passed separately: 137 tests. The
standard unit launcher stops before these tests after a Vitest failure.
- Credential-free discovery passed: `node --import
./cli/node_modules/tsx/dist/loader.mjs tests/runner-e2e/launch.ts
--suite product-journeys --list`.
- `node scripts/check-maps.mjs` passed. `git diff --check` passed.
- All 58 current-head check runs are green, the additional security
status passed, Greptile reviewed this exact head at 5/5, and no review
threads remain unresolved. Typecheck, test, build, browser CI, and fresh
attached Cloud acceptance passed. Daily-plan admission follows merge.

## Risks

- Task-list control labels and link structure can change. Such drift
fails the journey and needs an update.
- The journey creates three board-assigned tasks. It records ownership
before creation and records each returned ID immediately. The existing
target provider owns cleanup.
- Local assertion tests do not prove that a deployed Cloud target
passes. The target owner must record a fresh live pass before admission
to a daily plan.

## Model Used

OpenAI Codex, GPT-6 family. The host does not expose an exact model
version or context limit. Used repository search, TypeScript tools, and
tests.

## 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 14:26:53 -05:00
github-actions[bot]andlockfile-bot ade402c75f chore(lockfile): refresh pnpm-lock.yaml (#18360)
## Thinking Path

> - Paperclip uses a dependency lock for reproducible builds.
> - Dependency changes on master need matching lock entries.
> - Paid eval reports also pin a reviewed offline correction.
> - Reports must install before paid model work starts.
> - This automated PR keeps the lock and report proof together.

## Linked Issues or Issue Description

**What happened?**

Dependency manifests on master changed after the last committed lock
refresh.

**Expected behavior**

Frozen installs must match those manifests. Eval reports must retain
matching offline lock proof.

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

- Refresh the dependency lock from the manifests on master.
- Include the matching offline report correction and hashes.

## Verification

- Pinned pnpm resolution completed with lifecycle scripts disabled.
- The report proof refresh accepted the reviewed committed baseline.
- The workflow rejected changes outside the lock and report proof files.

## Risks

The lockfile bot merges this PR without CI or review when every added
package version is at least 3 days old on npm. Otherwise the PR waits
for a maintainer, and the daily refresh tries again. The bot merges only
the exact commit this workflow generated from manifests already reviewed
on master. Unknown report lock baselines remain blocked. This update
changes no permissions or paid enable gates.

## Model Used

None — generated by pnpm and the deterministic report-lock updater.

## Checklist

- [x] Thinking path and problem description included
- [x] Generated lock and matching report proof included
- [x] Release-age gate decides between bot merge and maintainer review

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-10-30 18:17:19 +00:00
DottaandPaperclip aa58fa1073 perf(ui): restore fast Coordinator task and inbox loading (#18323)
## Thinking Path

> - Paperclip lets people manage work done by agents.
> - Tasks, Inbox, and Needs You must stay usable as work history grows.
> - The Coordinator views bypassed some existing collection
optimizations.
> - Navigation fetched complete decision cards for a count, and Tasks
mounted every loaded row.
> - This PR uses the canonical attention rules for small count and
task-ID responses. It also restores bounded rendering and the optimized
Inbox selection.
> - The benefit is less data and less initial rendering work without a
second definition of pending work.

## Linked Issues or Issue Description

**What happened?**

Coordinator navigation fetched the full attention feed on every cold
collection visit. Tasks rendered the entire loaded collection.
Coordinator could also select the old Inbox loader when Streamlined UI
was off.

**Expected behavior**

Fetch only the projection needed by each surface. Start with a bounded
set of rows. Keep complete task membership, accurate counts, current
permissions, and stable loaded rows.

**Steps to reproduce**

1. Enable Coordinator and open Tasks or Inbox with an empty browser
query cache.
2. Observe a complete attention-card download for the navigation badge.
3. Open a large task list and observe that every loaded row mounts at
once.
4. Disable Streamlined UI while keeping Coordinator enabled, then open
Mine and observe three overlapping compact task reads.

Related work: #17756, #3744, #17983, and #18312.

## What Changed

- Add board-only attention count and complete task-ID projections. Reuse
canonical company, privacy, addressee, deduplication, dismissal, snooze,
and archive rules. Skip card bodies, plan/image reads, and presentation
roster lookup.
- Share the small count read across desktop and mobile navigation. Reuse
the page-owned response on Needs You and Needs attention. Keep the
newest known count through navigation, including zero.
- Use the task-ID index for Needs attention and keep task row hydration
in batches of at most 100.
- Render 100 task rows initially, across the whole expanded tree. Reveal
150 more at a time through scrolling or a button. Keep existing rows
through refresh and append. Defer offscreen leaf layout with shared
tokens.
- Keep Coordinator on the optimized Inbox when Streamlined UI is off.
Use index reads for expanded project recents.
- Add real-database, component, and production-build browser regression
checks. Update the access and feature maps.

## Verification

- All required CI checks pass on
`1c68ac8957490a6c8585ba0939355f536c8120bf`: typecheck, build,
server/workspace tests, serialized database suites, and eight E2E
shards. Greptile is **5/5**, with its row-retention finding fixed and
the review thread resolved. Storybook checks were intentionally skipped;
Paperclip Review completed neutral.
- Workspace typecheck and production build passed locally. The final
rebased source also passed UI typecheck and production build. Token
gates and map checks passed.
- The attention service suite passed all 34 tests on disposable
PostgreSQL. Final targeted checks cover compact projections,
complete-set counts, quality approvals, snoozes, private tasks, and
board/company access. Database response capture confirms compact
projections do not read plans or images. All 31 OpenAPI tests passed
after registering both endpoint contracts.
- Six production-build browser journeys passed: desktop, mobile,
Coordinator Inbox with Streamlined UI off, Needs You, Needs attention,
and an older server page followed by task open/Back. They verify the
initial 100-row budget, scrolling, retained DOM identity/height, one
owner per attention read, complete task membership, 220 retained rows on
Back, and less than 2 px of return-position difference.
- The row-budget and Inbox regressions fail against original source and
pass with this change. The final three affected UI suites passed 40
tests, and the broader Inbox/IssuesList suites passed 101 tests
serially.

### Controlled production-build comparison

Baseline `b31ec0a2dc079e32272a8f618425fe92b68bbaec` versus PR head
`1c68ac8957490a6c8585ba0939355f536c8120bf`. Isolated baseline asset
`index-CS9uPxMx.js`; candidate asset `index-BxJeTQ30.js`. Both UI builds
used the same warm disposable API server and database, with 220 tasks
and 110 pending board approvals. Chromium **151.0.7922.34**, 1440 × 900
viewport, **4× CPU throttle**, loopback with no added network latency,
alternating baseline/candidate order. Cold cases use a new browser
context with network cache disabled; warm cases navigate within the same
context. Other host workloads are uncontrolled.

Readiness requires the destination collection's first visible task row,
then two animation frames. Inbox readiness waits for its canonical Mine
route so previous-page rows cannot satisfy the measurement. Five paired
samples per case; cold Inbox has a second five-pair confirmation wave
because the first result was slower. Times below are **milliseconds**;
parentheses show min–max. Paired savings are the median of individual
before-minus-after pairs, not the difference between medians.

| Journey | Pairs | Baseline median (range) | Candidate median (range) |
Median paired saving | Faster pairs |
| --- | ---: | ---: | ---: | ---: | ---: |
| Cold Tasks | 5 | 2752 (2542–3025) | 2300 (2275–2524) | 328 | 5/5 |
| Cold Inbox | 10 | 2536 (2283–2927) | 2582 (2117–2856) | 37 | 5/10 |
| Warm Tasks navigation | 5 | 2054 (1826–2479) | 1448 (1419–1548) | 635
| 5/5 |
| Warm Inbox navigation | 5 | 2020 (1485–2254) | 1568 (1289–1848) | 350
| 5/5 |
| Task → Back to Tasks | 5 | 1747 (1609–1948) | 1327 (1238–1355) | 472 |
5/5 |

Cold Tasks, warm Tasks, warm Inbox, and Back improved in every measured
pair. **Cold Inbox latency is inconclusive:** the two waves pointed in
opposite directions, with the candidate faster in 5/10 pairs. This PR
claims less badge work there, not a proven cold Inbox latency
improvement.

The canonical badge response shrank from **200,039 to 359 decoded
bytes** (encoded HTTP transfer: **8,125 to 598 bytes**). The compact
response also skips card payloads, plans, images, and presentation-only
roster work. These are measured mechanism reductions, separate from
end-to-end latency. Needs You still owns its full card feed; Needs
attention owns its complete task-ID projection. Reproduction setup and
assertions are in `tests/perf/collections/README.md`.

<details>
<summary>Individual paired readiness measurements (ms)</summary>

| Journey | Pair | Baseline | Candidate |
| --- | ---: | ---: | ---: |
| Cold Tasks | 1 | 3025 | 2283 |
| Cold Tasks | 2 | 2542 | 2275 |
| Cold Tasks | 3 | 2752 | 2424 |
| Cold Tasks | 4 | 2783 | 2300 |
| Cold Tasks | 5 | 2641 | 2524 |
| Cold Inbox | 1 | 2927 | 2702 |
| Cold Inbox | 2 | 2422 | 2629 |
| Cold Inbox | 3 | 2409 | 2606 |
| Cold Inbox | 4 | 2621 | 2769 |
| Cold Inbox | 5 | 2539 | 2856 |
| Cold Inbox | 6 | 2283 | 2117 |
| Cold Inbox | 7 | 2466 | 2558 |
| Cold Inbox | 8 | 2674 | 2286 |
| Cold Inbox | 9 | 2696 | 2389 |
| Cold Inbox | 10 | 2533 | 2183 |
| Warm Tasks navigation | 1 | 2479 | 1423 |
| Warm Tasks navigation | 2 | 2228 | 1548 |
| Warm Tasks navigation | 3 | 2054 | 1419 |
| Warm Tasks navigation | 4 | 1826 | 1448 |
| Warm Tasks navigation | 5 | 1954 | 1518 |
| Warm Inbox navigation | 1 | 2020 | 1661 |
| Warm Inbox navigation | 2 | 2198 | 1848 |
| Warm Inbox navigation | 3 | 1733 | 1497 |
| Warm Inbox navigation | 4 | 2254 | 1568 |
| Warm Inbox navigation | 5 | 1485 | 1289 |
| Task → Back to Tasks | 1 | 1721 | 1330 |
| Task → Back to Tasks | 2 | 1747 | 1275 |
| Task → Back to Tasks | 3 | 1948 | 1355 |
| Task → Back to Tasks | 4 | 1609 | 1327 |
| Task → Back to Tasks | 5 | 1790 | 1238 |

</details>

### Failed attempts and limits

- The local full repository command hit embedded PostgreSQL startup
failures and 16 failures in the untouched native session executor suite;
it was stopped. The full local suite is not claimed green. CI on the
final revision provides the broad test result.
- A concurrent local UI run hit timing failures under host contention.
Inbox/IssuesList subsequently passed all 101 tests serially. No tests
were weakened to address these timeouts.
- CI caught two integration gaps introduced during this work: missing
OpenAPI entries for the new endpoints, and an attention fixture
incompatible with the routine filters added on master. Both were fixed;
the affected 31 OpenAPI and 40 UI tests pass.
- The final revision's first CI attempt failed two untouched tests:
scheduled-retry batch cancellation and the tool-access audience/archive
race. Both failed jobs passed when rerun without changing the revision.
Their original failed attempts remain visible in [the workflow
history](https://github.com/paperclipai/paperclip/actions/runs/41083379875).
- Browser evidence uses synthetic disposable data. This PR is not
deployed staging or production verification.

## Risks

- New attention sources must preserve canonical eligibility. Both
projections call the existing collector, so they share its permissions
and complete-set behavior.
- The count and task-ID caches must not stand in for full decision
cards. Each projection has its own key under the existing attention
invalidation prefix.
- A row budget can omit descendants if applied per parent. The tests
cover one global budget across a large expanded tree, refresh, append,
reset, and incremental loading.
- Local browser evidence uses synthetic data and is not staging
deployment proof.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact backend model deployment 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 (affected suites; broad-run
limitations are listed 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 11:58:53 -05:00
Nicky LeachandClaude Opus 5.5 abc270ee4c fix(runner): attest upstream releases and bind ACPX uniformly for every harness (#18325)
## Thinking Path

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

## Linked Issues or Issue Description

Refs #18237, #18212, #17972.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:10:50 -07:00
DottaandPaperclip 1511c92965 fix(evals): account for superseded delegation wakes (#18319)
## Thinking Path

> - Paperclip lets people ask agents to delegate work and return the
result.
> - The chat feature eval checks task creation, worker execution, saved
output, and delivery to the source chat.
> - A task can first belong to the CEO and then move to Morgan.
> - Paperclip correctly cancels the old assignment wake before it
starts.
> - The eval treats that queue record as a failed provider run and stops
before Morgan works.
> - This change accounts for that record separately and preserves the
complete outcome checks.
> - The report also keeps partial check results when an attempt fails.

## Linked Issues or Issue Description

**What happened?**

The delegation journey stopped on an unstarted queue record with
`issue_assignee_changed`. The CEO had created a task, assigned Morgan,
saved the brief, and returned a task link. The test stopped before
worker execution. Its report showed no individual checks even though the
saved observation contained partial results. [Original public
measurement](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/chat-progress-39e-112-latest-121-measurements-with-screenshots-40649033672/?view=case&case=chat-features.delegate-announcement).

**Expected behavior**

Keep the obsolete queue record and its events. Continue observing the
intended worker. Pass only after three successful native work runs, a
current Morgan-authored announcement, a completed task, automatic
source-chat delivery, and browser readback.

**Steps to reproduce**

1. Ask the CEO to have Morgan write and save a launch announcement, then
return it to chat.
2. Create the task under the CEO, then assign Morgan before the queued
CEO run starts.
3. Observe the cancelled old assignment. The previous eval aborts at
that point.

**Paperclip version or commit**

Based on `6da112ab40d7b3cc0bcb79e08ddbb9b915a268a4` from
`origin/master`.

**Deployment mode**

Disposable Product E2E fixtures. The live check uses the trusted
default-branch workflow and AWS fleet.

Related contribution: #17794 introduced these two journeys. The open-PR
search found no separate fix for this queue-accounting defect.

## What Changed

- Recognize only explicit dispatch-gate reassignment cancellations with
a null start time and no native issue. Verify the company, prior CEO
owner, and target task now assigned to Morgan before excluding that
record from work-run counts.
- Keep every queue record in the full observation and final ledger.
Retain its events with an explicit reason for the absent provider log.
- Let the feature flow own its complete saved-state and browser oracle.
Return only actual work runs to the common provider checks.
- Record saved-state checks on failures as well as successes. Capture
the required `final-state.png` after the feature-specific browser
readback.
- Add two explicit local OpenCode cells alongside the two existing Codex
subscription cells. Use the current production-qualified model. The
earlier linked campaign used a different model, so this is a new
measurement.
- Advance the grader and suite versions. Keep the original request,
output requirements, 120-second run cap, five-minute observation bound,
budgets, and single-attempt policy.

## Verification

- Red/green regressions cover queue accounting, missing-log collection,
partial checks on evidence failure, and the required final screenshot.
Flow tests invoke the actual polling callbacks: restoring the original
callback reproduces both early-stop errors. Started cancellations still
fail.
- All 87 focused flow/grading/queue tests pass. Catalog/report checks
and the 137 additional Node checks pass. Eval typechecking passes on
final commit `0a6e11408c4470683417e6bf7965c73cec2a9a60`.
- All current CI tests/builds pass. Greptile is 5/5 on the final commit,
with no unresolved review threads.
- The final commit adds only flow test coverage. Its registered
definition digest equals live target
`e4e0be875ee12c134fe8dd2ce15a88bfcbb100ef`:
`ac6bba21d4b9cb86088be5d00df6442af90268186d6e94c9bea7d611d0488563`.
- Replaying the original saved observation still fails for missing
Morgan execution and delivery. Its stale queue record no longer counts
as provider work.

| Operation | Selected coverage | Observed result |
| --- | --- | --- |
|
[41071710105](https://github.com/paperclipai/paperclip/actions/runs/41071710105),
`b8dff816` | Backlog and delegation | Refused at the exact
private-retention gate before fixtures or providers. Preserved without
feature coverage. |
|
[41073708150](https://github.com/paperclipai/paperclip/actions/runs/41073708150),
`39be9e45` | Backlog and delegation | Both passed their full
product/browser oracles. Retained grades correctly fail missing
`final-state.png`; the feature flow had saved the image under another
name. Fixed in `e4e0be87`. Each original archive remains private and
intact; later workflow concurrency superseded only the report
aggregation. |
|
[41076854978](https://github.com/paperclipai/paperclip/actions/runs/41076854978),
`e4e0be87` | Backlog and delegation | Backlog passed in 92.576 seconds,
with a 47.388-second native run, complete required artifacts and passed
cleanup. Delegation was interrupted by a runner-host shutdown at
15:19:23 UTC; all later evidence-upload steps were skipped. Its private
archive is absent, so behavior, usage and cost remain unverified. |
|
[41080065077](https://github.com/paperclipai/paperclip/actions/runs/41080065077),
`0a6e1140` | Delegation only | Passed on the final commit in 240.786
seconds. All 14 product checks plus browser readback passed; exact
private identity, current worker output, Done state, correlated
source-chat reply, required screenshot and cleanup verified. The three
native runs took 42–60 seconds each. Passing control was not repeated.
One-cell workflow and report enforcement passed. |

The completed delegation in `41073708150` passed all 14 product checks
plus browser readback in 222.593 seconds. Morgan saved the current
two-sentence announcement, the task reached Done, and the CEO
automatically delivered that saved text to the original chat. Its three
successful native runs took 49.117, 40.060 and 39.107 seconds. The
failed required screenshot remains a failed result in that measurement.

All live operations use explicit IDs, concurrency one, no automatic
retries, the unchanged 120-second per-run cap, and scoped private
evidence retention bound to the exact workflow, target, original run,
selector and launcher digest. These narrow measurements do not qualify
the full catalog or establish repeated-run reliability.

The broad local support suite passed 5,139 tests, with two skipped. Two
database tests hit exhausted host semaphore capacity after the installed
Postgres package's missing library symlinks were repaired. Their recheck
reported `could not create semaphores: No space left on device`. No host
IPC resources or kernel settings were changed. The corresponding full CI
tests passed on a fresh host.

## Risks

- A broad cancellation exception could hide failed work. This exception
requires the dispatch gate's exact receipt, a null start time, the
expected company and prior owner, and the actual reassigned task.
Started and unproved cancellations still fail. Backlog creation permits
no task wake.
- New manual OpenCode cells can spend provider money only when
explicitly selected. Default scheduled selection is unchanged.
- This changes eval interpretation and evidence collection. It does not
change product scheduling or task ownership.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 10:40:00 -05:00
DottaandPaperclip 5a7a6b32ba fix(ui): restore compact Coordinator task loading and responder continuity (#18312)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People open tasks from their personal workspace and send replies to
agents.
> - Cold task opens should load recent conversation before older
history.
> - Classic settings could expand history before the Coordinator
preference arrived.
> - Coordinator lists also read full tasks, and response startup used
the previous assignee.
> - This pull request restores compact reads and keeps the selected
responder visible through runtime discovery.
> - People can read and reply without waiting for unrelated history or
losing response feedback.

## Linked Issues or Issue Description

Related: #17593, #17751, #17756, #17885, #17983, and #18092.

**What happened?**

A cold task could select Classic full history while its personal
workspace preference was pending. The full-history choice stayed cached
after Coordinator became active. Coordinator Tasks used full task reads.
Needs attention fetched one enriched task per pending task.

Sending to a newly selected agent could show no responder, show the
previous assignee, or clear feedback when assignment changed. Legacy
runtime discovery then replaced the startup identity with a generic
activity line.

**Expected behavior**

Wait for the workspace preference before selecting Classic history. Show
the task instruction and recent conversation with **More messages** for
older content. Read collection indexes and fetch diagnostics for visible
rows. Keep the selected responder mounted from Send through saved input
and runtime startup.

**Steps to reproduce**

1. Enable Classic task UI and Coordinator. Delay the personal workspace
preference on a cold task open.
2. Open Coordinator Tasks or its Needs attention view with many pending
tasks.
3. Open a task assigned to a person. Select another agent in the
composer and send a message.
4. Let the message save before runtime reads return. Then allow a legacy
run to appear.

## What Changed

- Wait for task interface settings before persisting Classic history
expansion.
- Use lightweight indexes for Coordinator Tasks. Resolve pending task
IDs in batches of at most 100. Keep search and participant filters on
the server. Enrich at most 50 visible rows through the existing hook
without replacing list membership or order.
- Preserve an error when a pending task cannot load, instead of showing
a false all-clear.
- Register board cards for row enrichment. Observe newly mounted cards
after column expansion or pagination, and track visibility by element so
hidden list rows cannot clear visible board cards with the same task ID.
- Track the recipient of each submitted message through reassignment. A
later draft's recipient does not change the response already starting.
- Share a stable response header across startup, native runtime, and
legacy runtime rendering. Keep the existing transcript renderers.
- Add regression tests, production-browser checks, design guidance, and
feature-map notes.

## Verification

- Red/green: delayed Coordinator preference started a full comments read
before the fix. It now retains compact history and still expands on
request.
- Red/green: sends from human or other-agent assignment showed no
identity or the wrong identity. Both now retain the selected responder
through assignment, acknowledgement, later draft selection, and
native/legacy startup.
- In a 105-task Needs attention fixture, the previous code made 105
enriched detail requests. The fixed code makes two bounded index
requests.
- All 659 final affected tests pass across task detail, thread, runner
turn, history window, Inbox, board, row enrichment, and Coordinator
collection suites.
- Review follow-up: the production board lost its next-step badge before
card registration. The regression now passes, along with column
pagination. The focused 82-test enrichment run and 371-test
header/thread run also pass.
- All 12 compact-startup browser checks pass against the production UI
and an isolated PostgreSQL container. They cover delayed preferences,
list navigation, saved-card geometry, document/comment anchors, history
expansion, draft retention, retry, and actual legacy process startup.
The final deterministic process case recorded 118 frames with zero
missing or replaced responder identities. It does not call a model
provider.
- Full workspace build and typecheck pass. Final UI build and typecheck
pass after the shared-header change. Token gates, map checks, module
boundaries, and diff checks pass.
- The full UI rerun before the board review follow-up passed all 10,034
tests across 844 files. The 659 affected tests pass after that
follow-up. The first full UI run passed 10,030 tests and timed out in
one unchanged IssuesList large-tree test. Its two variants pass in an
isolated rerun and in the full rerun. Those later passes establish
recovery; the earlier timeout's cause remains unproven.
- The full `pnpm test:run` attempt was stopped after repeated embedded
PostgreSQL initialization failures in server fixtures. No complete local
server-suite pass is claimed. Browser verification recovered with a
disposable container database.
- A later avatar browser rerun reused the previous same-title task and
its cancelled run through the existing 48-hour title deduplication. That
fixture never reached fresh runtime startup. The test now uses a unique
title and checks its initial assignment/status; a full 12-case rerun and
a second avatar run on the same instance pass. The failed trace is
retained locally.
- Final commit `7a18372da3` has 55 successful checks, two intentionally
skipped Storybook checks, and one neutral Paperclip Review. All required
verification gates are green. Greptile is 5/5 with no actionable
findings or open review threads. The advisory Paperclip review paused
without a complete assessment; no passing Paperclip assessment is
claimed.
- These checks establish bounded reads and stable rendering. No reliable
staging latency benchmark or staging deployment is claimed.

## Risks

- Collection projections omit task bodies. Detail navigation must retain
its normal core/full task reads. Search remains server-side.
- Startup feedback must end on rejection, unavailable agents, terminal
outcomes, or a visible run. Existing cases cover those transitions.
- The shared header changes the legacy live-turn layout to retain
identity beside its existing status line.
- No migration, mutation permission, provider protocol, or execution
authority change.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving deployment ID and
context-window size are not exposed in this session. The model used
reasoning, code editing, shell tools, automated Chromium checks, and
manual browser inspection.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (focused suites and browser
checks; full-suite limitations 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 09:03:03 -05:00
DottaandPaperclip ac4f13d205 fix(e2e): report committed child blockers promptly (#18306)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Product E2E checks the ordinary onboarding conversation and its
delivered work.
> - A native run can finish successfully while its task remains blocked
for a human.
> - The onboarding journey kept waiting for such a child until the
campaign deadline.
> - This pull request reports the committed child blocker when no owned
work remains pending.
> - The journey still requires the same independent checks before it can
pass.

## Linked Issues or Issue Description

**What happened?**

An approved child can stop with a committed current-track blocker owned
by the board. Its native run succeeds, but the child task stays blocked.
The onboarding journey reports a deadline failure instead of the
observed child blocker.

**Expected behavior**

Report `onboarding_child_task_blocked` when the latest child run commits
that blocker at the child's current status version. Keep waiting for
parent dependencies and pending native or workspace recovery.

**Steps to reproduce**

Use the existing onboarding fixture with an approved blocked child. Give
its latest native run a succeeded status, committed finalization,
blocked work disposition, and the matching task status version. The old
journey waits until its deadline. The new journey fails at that settled
blocker without downloading or accepting any delivery.

Related public context: #18298. Public issue and PR searches found no
duplicate blocked-child harness fix. This change reports the failure
boundary; it does not repair artifact delivery.

## What Changed

- Check the owned child's board blocker after the existing run and
recovery checks.
- Require a unique latest producer, native committed results, and the
current task status version.
- Preserve parent dependency waits and all artifact, document, download,
link, scope, and budget checks.
- Add a behavioral regression and controls for active work, native
recovery, workspace replacement, stale versions, newer producers, and
agent-owned blockers.
- Document the distinct failure code and the existing control-plane
writers for its metadata.

## Verification

- The new behavioral regression failed on the old code with
`onboarding_first_task_deadline`; 147 controls passed.
- The current head passed all 148 onboarding tests, including the valid
agent-owner object control.
- The initial implementation passed 305 tests across all 10 Product E2E
files. The later update changes only writer links and the owner control;
its 148 focused tests and harness typecheck also pass.
- `pnpm test:e2e:runner:typecheck` passed after building the isolated
checkout's workspace declarations.
- `git diff --check` passed.
- All required CI checks passed on
`1b3bd04d193fc98d0d9f2eb3b826a4ef4bdb6dea`, including full tests and
build. They were not repeated locally. Greptile reviewed that exact head
at 5/5.
- The full Cloud journey remains unverified by these source and CI
checks. This change does not claim that the underlying artifact delivery
issue is fixed.

## Risks

The early failure depends on the public task and run projections.
Missing, stale, or ambiguous producer metadata keeps the existing
bounded wait. A pending recovery or newer producer prevents the old
blocker from ending the journey. No success requirement changes.

## Model Used

OpenAI Codex, exact model ID `gpt-6.1-sol`, reasoning effort `ultra`.
The model used source inspection, code editing, and local test tools.
The runtime did not expose its context window size. Root supplied the
model and effort metadata for this agent session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 08:26:14 -05:00
DottaandPaperclip 0c70cedce9 Wait for the saved Studio file before editing a skill (#18305)
## Thinking Path

> - Paperclip lets people manage AI agents and use their saved work.
> - Product E2E journeys check these user paths in classic and Cloud
environments.
> - The shared Skill Studio helper edits a skill created by an agent.
> - Studio can mount the editor before its saved file finishes loading.
> - Typing into that empty draft can replace or lose content when the
file arrives.
> - This change waits for the existing saved body before it starts the
edit.
> - Browser regressions check delayed loading and refusal to edit an
unloaded file.

## Linked Issues or Issue Description

Refs #18222 for the shared Product E2E journeys. No duplicate hydration
fix was found.

**What happened?**

The shared Studio helper started typing as soon as the editor control
was visible. A delayed file query could replace that draft. The helper
could then lose the original content or fail to save its complete
marker.

**Expected behavior**

The helper must load the original file before editing it. It must
preserve that content, save the new marker, reload, and read the result
from the task card.

**Steps to reproduce**

Run the controlled Studio browser fixture with a 1.5-second file load.
The old helper saves the marker without the original `Verify checks.`
body. With no file load, it still sends input events to the empty
editor.

## What Changed

- Wait for the original saved body before typing in the shared Studio
helper.
- Add browser checks for immediate load, delayed load, and an
unavailable file.
- Include these checks in the credential-free browser support suite.
- Document the saved-file readiness requirement.

## Verification

- Against the old helper, both new failure cases fail: the delayed case
loses the original body, and the unloaded case sends 13 input events.
- With the change, all three browser checks pass. They verify the saved
original body and marker, reload, task-card readback, and zero input or
save calls for an unloaded file.
- `node node_modules/typescript/bin/tsc -p
tests/runner-e2e/tsconfig.json --noEmit` passes.
- `git diff --check` passes. Full repository CI passes in
[41058312896](https://github.com/paperclipai/paperclip/actions/runs/41058312896),
including typecheck, tests, build and all eight E2E shards. Greptile
reviewed this exact head at 5/5 with no open threads. No live acceptance
result is claimed by these controlled fixtures.

## Risks

This adds a readiness assertion to an existing test helper. Both callers
already use the same skill fixture and verify `Verify checks.` in the
task card. An unavailable file now fails before an edit can occur. The
change does not alter application behavior, model instructions, grading,
or deadlines.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning 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 version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the 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 id
- [x] I have run tests locally and they pass
- [x] I have added 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 reviewer comments before merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 08:05:04 -05:00
DottaandPaperclip cd5f930558 Add shareable image galleries to task documents (#18157)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/247/changes/paperclip/247
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task documents hold plans, reports, and image evidence.
> - Task attachments already have an image gallery.
> - Inline document images had no gallery navigation or image links.
> - This change gives each document a gallery that uses the existing
modal.
> - People can review the image sequence and share a link to one image.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Image review in task documents, including the side panel and Classic
interface.

**Current behavior**

Inline document images do not open a gallery. People cannot move through
them with arrow keys or share a link to one image.

**Proposed behavior**

Select an image to open the gallery. Use arrow keys or Previous and
Next. The URL records its one-based position, for example
`#document-report&image=2`. Reloading that URL opens the selected image.
Revision links keep their exact saved content.

**Reason and benefit**

People can inspect a document's image evidence in reading order and
share the exact view.

No matching issue was found. The latest 300 open PR titles were checked
for related document gallery work.

## What Changed

- Add a document renderer that collects rendered images in reading
order, including reference-style and repeated images.
- Reuse the gallery modal with optional index-change and focus-return
controls.
- Keep the document owner in the saved tab identity when people switch
between local and other-task documents.
- Match explicit current-task document owners with local document tabs.
Keep review and viewer parameters during gallery navigation.
- Treat another Classic review receipt as a new request while image
navigation retains the selected revision.
- Make inline image controls work with a keyboard. Keep focus in the
modal and restore focus on close.
- Keep document, revision, review, and maximized-view link parameters
during image navigation.
- Fix a Classic revision-cache race found by the browser test. Recheck a
pinned revision when the saved document head changes.
- Update the feature and agent access maps. No new server API or
permission is needed.

## Verification

- Passed 119 focused tests for document galleries, the shared gallery,
document rendering, the revision panel, and hash routing.
- Passed all 3 Chromium journeys: desktop, mobile, and Classic. These
use real uploads and saved document revisions.
- The browser journeys also check explicit current-task owners, review
parameters after reopening, other-task links after tab switches, and a
second Classic review link after Return to latest.
- Browser checks cover keyboard and button navigation, wraparound,
shared-link reload, exact historical content, invalid positions, focus
return and containment, scroll locking, and Escape, Close, and backdrop
dismissal.
- UI typecheck, token gates, map checks, and diff whitespace checks
passed.
- The UI production build passed in the browser harness.
- Earlier browser runs found and then verified the Classic
revision-cache fix. A later build exited 137 while the full test suite
ran. The browser run passed after that suite stopped.
- Full repository typecheck and build could not complete because Cargo
is absent. The full repository test run did not complete within this
sandbox. These checks remain subject to CI.

## Risks

- Image positions follow document reading order. Editing an unpinned
document can change those positions. A revision link retains the saved
sequence.
- The shared modal now uses Radix Escape handling. The existing gallery
tests and nested mobile dialog journey pass.
- No schema change or migration.

## Model Used

OpenAI GPT-6 through Codex. The runtime did not expose a more specific
model ID or context window size. Used reasoning, code editing, shell
commands, 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-10-30 07:52:15 -05:00
DottaandPaperclip 8f50704135 fix(e2e): wait for pending native recovery (#18298)
## Thinking Path

> - Paperclip manages agents and their work.
> - Native runs can retain a bounded automatic recovery on the same run.
> - Product E2E observes those runs before it checks the delivered work.
> - The onboarding journey treated every failed run as a final failure,
even when the server had saved its next recovery attempt.
> - This pull request waits only for the explicit agent-owned native
recovery projection.
> - The journey still requires successful execution and the same
independent delivery checks.

## Linked Issues or Issue Description

**What happened?**

The onboarding journey can stop after a native turn completes without
its semantic result. The server marks that attempt failed and saves a
same-run retry. The journey rejects the failed row before the saved
retry is due. This also affects a native child that follows a proven
workspace deferral.

**Expected behavior**

Observe the saved automatic recovery within the original campaign
deadline and run cap. A pending recovery cannot satisfy completion.
Ordinary failures and exhausted, terminal, or board-owned recovery must
still fail.

**Steps to reproduce**

Use the existing onboarding fixture with a native failed row whose
nativePhase is retryable_failure. Give it the server-owned
native_session_interrupted cause, an agent-owned retry_scheduled
projection, a valid retry time, and attempt 1 of 3. Transition that same
row through reconnecting and running to success. The old journey rejects
the first row.

Related public context: #18292. A search of related native-recovery PRs
found no duplicate harness fix.

## What Changed

- Observe the authenticated native recovery state in the existing
workspace-deferral module. Require matching nonempty cause strings and
every owner, phase, attempt, schedule, deadline, scope, and successor
guard.
- Apply it to the proposal wait, failed native rows, workspace successor
tails, and final settlement.
- Keep defensive rejection of known permanent, permission-declined, and
exhausted causes. Diagnostic cause strings are not a positive retry
policy.
- Add behavioral recovery, deadline, and rejection controls to the
existing workflow tests.
- Document that this wait preserves the original campaign and final
delivery requirements.

## Verification

- Baseline workflow regression: 4 expected premature failures with 90
controls passing. The final structural calibration rejected 20 valid
pending-recovery cases before the correction, with 120 controls passing.
- Final regression: 140/140 pass, including existing and new diagnostic
causes on direct and workspace-successor paths. Known terminal,
ambiguous, malformed, mismatched, and exhausted states still fail.
- Focused Product E2E compatibility: 297/297 pass across 10 files.
- pnpm test:e2e:runner:typecheck: pass after building the normal SDK and
Runner TypeScript dependencies.
- git diff --check: pass.
- Final source passed these checks before the reviewed commit.
- Full repository tests/build and live Cloud acceptance were not run
locally for this harness-only change. Required CI run 41049692194 passed
on 04dedd7d. Live acceptance remains separate.

## Risks

The execution projection is a polling observation, not dispatch
authority. A server that never resumes can hold this wait until the
original deadline. The predicate requires matching native interruption
state and cause, an agent owner, a bounded attempt and schedule, and no
successor. Known terminal-code rejection is a defensive check, not the
authority to retry. The journey must still observe actual success and
pass its document, artifact, download, and parent-link checks.

## Model Used

OpenAI gpt-6.1-sol, ultra reasoning, inherited from the parent runtime
metadata. Context window size is unavailable. Used source inspection,
code edits, shell tools, Git, and deterministic tests.

## 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
- [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-30 06:55:41 -05:00
DottaandPaperclip 8035f8b245 test: require saved onboarding approval cards (#18292)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product E2E tests exercise real user workflows through the browser.
> - The onboarding journey requires a human to accept one proposed child
task.
> - A live agent tried to create the child before it saved a proposal
card. The product correctly rejected that action.
> - The scripted request named the required result but did not name the
proposal tool or require its saved receipt.
> - This pull request makes that handoff explicit. It keeps the existing
human approval and independent result checks.
> - The benefit is a clearer scripted workflow without a change to
product authority.

## Linked Issues or Issue Description

Refs #18288 and #18266.

**What happened?**

The agent treated the opening task request as a step toward acceptance
without first saving a proposal. It then stopped after child creation
was denied. Its visible response referred to a pending proposal, but no
proposal card existed.

**Expected behavior**

The agent saves a native confirmation card, checks its receipt, and
waits for the human to accept it through the browser. It must not record
its own approval. Only an accepted card authorizes the child task.

**Steps to reproduce**

Run the scripted Cloud onboarding journey. Give the canonical onboarding
task its first task request. The observed agent skipped the saved
proposal and tried to create the child. Model behavior varies, so this
is a fixture guidance change rather than a deterministic product defect
claim.

**Paperclip version or commit**

Fixture base: `7a7ade4b9360aaf8e1a2808bb2b1a752c080f564`. The serving
product was Core `965184d2968f40b1183803529b88f288264c832f`.

**Deployment mode**

Testing Cloud workspace with native Codex. This pull request selects no
product release or deployment.

## What Changed

- Name the existing `request_human_input` confirmation or revision-bound
checkbox contract and `wake_assignee` policy in the parent request.
- Require a saved pending-card receipt. Require corrections when tool
arguments are rejected.
- Forbid self-approval. Require the actual accepted human card decision
before child creation.
- Document this scripted handoff. Keep the child brief, final download
links, browser actions, and all grading assertions.

## Verification

- Focused onboarding and Cloud journey tests: 79 passed.
- Shared evidence, campaign, and contract tests: 66 passed.
- `pnpm test:e2e:runner:typecheck`: passed after building the existing
workspace type dependencies.
- Credential-free preview under a network-deny guard: passed with zero
external calls. Its preparation plan matches the base fixture.
- `git diff --check`: passed.
- No prompt-string test was added. Existing tests continue to enforce
approval order, child scope, independent file checks, and real result
links.
- Full local repository build and database suites were not repeated for
this fixture text change. Required PR CI must pass before merge.
- The original live result remains unchanged. This local work does not
prove that a later model run will comply.

## Risks

- The model can still ignore the instructions. A new real campaign must
prove the workflow.
- More explicit guidance makes this a scripted product journey. It is
not a model discovery benchmark.
- There are no product runtime, schema, credential, model, budget, or
approval-policy changes.

## Model Used

OpenAI Codex, exact model `gpt-6.1-sol`, ultra reasoning effort. Parent
runtime metadata confirmed this model. Context window size was not
reported. Used source inspection, local code execution, and an
independent agent review.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 05:04:21 -05:00
DottaandPaperclip 7a7ade4b93 test: require real onboarding result links (#18288)
## Thinking Path

> - Paperclip lets people assign work to agents and use their saved
results.
> - The Cloud onboarding journey tests this handoff through a real
parent and child task.
> - The child can publish a correct file while the parent names that
file without linking it.
> - The existing journey correctly rejects that reply because the user
cannot download the named result from it.
> - This pull request makes the scripted parent request explicit about
real Markdown links and returned attachment paths.
> - The independent artifact and parent-link checks remain unchanged.

## Linked Issues or Issue Description

Refs #18266 and #18258.

**What happened?**

A Cloud onboarding attempt produced a correct child artifact and saved
document. The parent then named the child, document key, and filename in
inline code. It omitted the attachment URL. The attempt failed with
`onboarding_parent_result_links_missing`.

**Expected behavior**

The parent's final reply must link the saved child results. The file
link must use the real published attachment reference.

**Steps to reproduce**

Run the existing explicit Cloud onboarding journey. A reply that only
names the file must remain a failure, even when the child artifact is
correct.

**Paperclip version or commit**

The branch starts from `965184d2968f40b1183803529b88f288264c832f`.

## What Changed

- Ask the parent for real Markdown links in its final reply. Use the
published attachment's returned content or download path. Do not invent
IDs or URLs.
- Add a filename-only reply to the existing negative oracle cases.
- Document this scripted fixture requirement.

## Verification

- Focused onboarding tests: 79 passed.
- Shared task, campaign, and contract tests: 66 passed.
- Existing artifact and native-completion Node checks: 137 passed.
- `git diff --check`: passed.
- Harness typecheck, `pnpm -r typecheck`, and `pnpm build`: passed after
building the existing workspace dependencies. The initial
missing-declaration and local-IPC setup failures remain recorded.
- The full local database test suite was not rerun. Required repository
CI runs the broader suites on Linux.
- Required repository CI passed on the exact PR head. No paid model
calls or Cloud operations were run for this patch.
- [Initial
CI](https://github.com/paperclipai/paperclip/actions/runs/41027635545/attempts/1)
failed one unchanged retention timing test (3310 ms versus the strict
3000 ms bound). The unchanged case passed once on an isolated local
Postgres17 fixture. One failed-jobs-only rerun passed in [attempt
2](https://github.com/paperclipai/paperclip/actions/runs/41027635545/attempts/2).
The original failure remains visible. No timing threshold or retention
source changed.
- The previous live attempt stays failed. Local tests do not prove that
a model follows the revised request. A new bounded live attempt must
establish that result.

## Risks

- The extra instruction can still be ignored by a model. The unchanged
oracle will reject missing links.
- This changes the fixture definition hash. Historical attempts retain
their original source and result.
- No product runtime, API, approval policy, model profile, budget, or
cleanup behavior changes.

## Model Used

OpenAI `gpt-6.1-sol`, ultra reasoning, with code execution and
repository tools. Model metadata was confirmed in the parent task. The
context window size is not exposed.

## Checklist

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

> - Paperclip lets people assign work to AI agents and read saved
results.
> - Product journeys must prove that a result is visible and belongs to
the completed run.
> - The shared observer compares stored Markdown with browser text.
> - A document link can render as an issue chip, so those strings
differ.
> - This PR keeps run and comment attribution, then compares full text
and exact link destinations.
> - The benefit is a valid browser result without a false timeout or a
weaker provenance check.

## Linked Issues or Issue Description

Refs: #18248, #18255.

**What happened?**

The protected-action story completed both decisions and all four native
turns. Its final explanation contained a document link. The browser
rendered that link as an issue chip. The observer waited for raw
Markdown to equal rendered text, so it could not accept the valid
result.

**Expected behavior**

Accept complete matching content from the final run after reload. Keep
the exact link destination, task anchor, author, run and durable
final-message checks. Reject missing or changed content.

**Steps to reproduce**

1. Save an attributed reply with bold text and a Markdown document link.
2. Render the link as an issue chip in the task bubble.
3. Run `readBoundTaskFinalReply`. The original observer times out. The
new browser regression preserves that failure.

## What Changed

- Add a UI-owned content projection using its existing Markdown renderer
and GFM/issue-reference plugins. Keep DOM observation, attribution and
destination checks in the task-reply observer. Keep source Markdown and
observed text separately.
- Read visible DOM text, link labels and destinations. Require the
structured projection to match the actual visible text. Allow only
recognized product chips to replace a link label. Ordinary links keep
their source label. Reuse the production issue-reference and
company-route helpers, plus the current task URL. Ordinary root-relative
anchors keep their original path. Preserve exact marker checks and all
run/comment/native-event attribution checks.
- Check visible decline explanations and unread data in preserved native
source text.
- Add browser regressions and source/content tests. Reuse the UI’s
existing `react-markdown` and `remark-gfm` dependencies. The final diff
changes no package manifest or lockfile.
- Match generated GFM checkbox states and reject changed states.
Document supported content and fail-closed behavior.

## Verification

- Original observer: the decorated-link browser regression fails at the
final-reply predicate.
- Fixed observer: all 21 browser regressions pass, without credentials
or model calls.
- Focused observer, decline, content and journey contract suites: 64
tests pass.
- E2E and UI TypeScript checks pass. All UI token gates pass. The
unchanged frozen install passes.
- Full CI passed on the preceding 6eba7ff head (41003112166). Full CI
passed on the preceding b9a2571 head (41006205475), with both reviewers
at 5/5. Current-head full CI passed at
b3d2d08305 (41009669966), including
typecheck, build and all eight E2E shards. Both reviewers scored this
commit 5/5, with no unresolved threads. The initial lockfile policy
failure was corrected. The final diff has no manifest or lock changes,
and its unchanged frozen install passed.
- The optional positive GFM strikethrough assertion also passes.
- The Node 24/tsx end-to-end observer probe passes. The callback has no
external compiler helper; a browser regression covers actual tsx
serialization.
- The Paperclip review finding is also fixed: bare URLs and issue keys
use the production plugins and the UI’s `scope=accessible`
company-prefix context, with RED/GREEN browser coverage. Source Markdown
is required in the receipt.
- All Greptile findings are fixed, including matching the UI’s
accessible-company scope: ordinary link labels, issue-prefix/fragment
resolution and ordinary root-relative paths have positive and negative
browser coverage.
- The deployed attempt remains a failed original measurement. Fresh
qualification is required after this repair.

## Risks

The comparison normalizes whitespace and inline formatting. It verifies
full text and exact link targets, while link labels may become product
chips. Images, raw HTML, tables and fenced code fail closed. Those
constructs may require a future explicit extension if a journey uses
them. No application behavior, model, budget, approval or connection
permission changes.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code execution and browser
tools. 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 version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal issue
identifier
- [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 00:57:59 -05:00
Nicky LeachandClaude Opus 5.5 fa760dbce4 fix(runner): reuse image packs only with matching contract digest (#18237)
## Thinking Path

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) through Claude Code in the
desktop app, with repository tools, shell execution and research
subagents. The session does not expose the context window size.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:55:11 -07:00
DottaandPaperclip 145214201d test: preserve the onboarding child brief at delegation (#18266)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product E2E journeys check onboarding through the real app.
> - The onboarding story asks a parent agent to delegate a file and
document task.
> - A parent can preserve the goal but omit the exact tool instructions
from its child description.
> - The child can then publish a note instead of the required JSON file
and task document.
> - This pull request asks the parent to copy the full child brief
without changing it.
> - The existing independent checks still decide whether the result
passes.

## Linked Issues or Issue Description

Refs #18258. Includes merged prerequisite #18270 for the existing
retention scheduling failure found by required CI.

**What happened?**

The scripted onboarding request gave the parent an ordered tool recipe.
It did not require the parent to keep that recipe in the child
description. A delegated child could compute the result but publish a
Markdown note and omit the Paperclip task document.

**Expected behavior**

The child receives the full approved brief. It must publish
`connection-proof.json`, save its Paperclip task document with the
returned file link, and report completion through the current contract.

**Steps to reproduce**

Run the explicit Cloud onboarding journey. Inspect the approved child
description and its published result when the parent summarizes the
request.

**Paperclip version or commit**

This change is based on public master
`b3c2172d417ea6b783e0c796aaed4a91e1f9d381`.

**Deployment mode**

Scripted Product E2E against a live Cloud testing workspace.

## What Changed

- Put the existing ordered instructions in one marked child brief.
- Require the parent to copy that brief verbatim into
`create_task.description`.
- State the exact JSON filename and workspace-relative content reference
for `register_deliverable`.
- State that a Markdown workspace note does not replace the
`write_document` step.
- Document this scripted scope in the Product journey guide.

## Verification

- Existing focused Product journey tests: 227 passed in 10 files.
- Credential-free Product journey discovery passed through the direct
tsx loader.
- Source comparison confirms that all code after the opening reply is
unchanged. The download, calculation, hash, provenance, document,
parent-link, approval and run-limit checks retain their original
behavior.
- No prompt word-matching tests were added. This is an instruction-only
change.
- `pnpm build`, `pnpm -r typecheck`, and `pnpm
test:e2e:runner:typecheck` passed.
- Full support Vitest check: 5,042 passed, 2 skipped, 2 failed. Both
failures occur during embedded PostgreSQL startup in the controller
database lifecycle fixtures. The log includes a missing bundled
`libzstd.1.dylib`. The separate Node support checks passed all 137
tests.
- `pnpm test:run` was attempted. It reached the general server suite and
repeated embedded PostgreSQL startup failures. I stopped only this owned
local test process group. The full local test command is incomplete.
Required Linux CI remains the merge gate.
- The first harness typecheck ran before workspace build outputs existed
and reported missing workspace modules. It passed after the full build.
The earlier failure remains recorded.
- The initial CLI discovery wrapper hit a local tsx IPC permission
error. The direct loader passed with the same source and arguments.
- The original required CI run found an existing skill-retention page
delay. Its unchanged test passed once against a dedicated local
PostgreSQL fixture. Separate PR #18270 added a deterministic regression
and fixed the scheduler. After that PR merged, this branch received one
normal merge from master. Its diff remains two fixture files. The
original failed CI run remains preserved.
- After the branch refresh, all 70 onboarding first-task tests and 7
retention/deadline controls passed. Harness typecheck passed. Fresh
required CI and review passed on head
`608e266c6567c19981fd3f8a07305c785346753b`.
- The refreshed CI run passed the retention shard but failed one
unchanged Antigravity authentication fixture. The same Runner lane
passed on the prior fixture head and the merged prerequisite. The exact
test passed once locally. Source review identified a possible
stdout/stderr ordering race, but the failed run did not retain its exact
error subtype. The one approved retry of the failed CI job and its
verification aggregate passed on unchanged source. The original failure
remains preserved. This proves recovery, not its cause.
- The live Cloud journey has not been rerun with this source. Historical
failed attempts retain their original results.

## Risks

- An agent can still fail to follow the brief. Existing independent
assertions will reject the wrong file or missing task document.
- The fixture definition changes. A later live attempt must record this
new harness revision.
- No application, model, effort, budget, cleanup or acceptance rule
changes.

## Model Used

- OpenAI `gpt-6.1-sol`, ultra reasoning effort, with repository tools
and code execution. The parent verified this model ID from current
runtime metadata. The context window size is not exposed.

## Checklist

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

> - Paperclip manages work assigned to agents.
> - Product E2E stories ask for useful user-facing results.
> - Classic runner and deployed QA reuse the same service
approve/decline task prompts.
> - The service returns a receipt marker that belongs in a saved
briefing document.
> - State that destination explicitly and ask for the document link when
complete.
> - The deployed decline path also needs the same durable final-reply
proof as Plan and Stop.

## Linked Issues or Issue Description

Refs #18222. Builds on the merged reply observer in #18248.

**What happened?**
The shared service tasks ask for titles and a “verification code”
without specifying that the code belongs in the document or asking for
its final link. A native QA attempt created its briefing but then
repeatedly failed the completion tool’s array validation. Those invalid
arguments remain a separate observed failure; the wording change does
not establish their cause or relax validation. Source inspection also
found that the declined-action oracle requires a projected comment even
when the settled native thread renders a durable final message.

**Expected behavior**
Ask for page titles and the service receipt code in the saved briefing,
then a document link. After a declined action, require the existing
explanation-only fallback without another service call.

**Steps to reproduce**
Run the shared service-approve/service-decline stories through the
classic runner or QA Product E2E adapter.

## What Changed

- Clarify the natural-language task for both shared service stories: put
page titles and service receipt code in the document and provide its
link.
- Use the reloaded run-bound final reply for QA service declines. Pass
an explicit native receipt to the existing decline oracle; do not
synthesize issue comments. Require the final native run to start after
the saved decline and keep exact decision, truthful explanation, no
unread marker, zero calls and unchanged connection checks.
- Keep classic callers on their existing attributed-comment path. No
internal tool instructions are added to the user prompt; ownership,
service data and model/runtime limits stay strict.

## Verification

- Decline regression observed RED: two cases reject a valid saved native
explanation without projected comments. After the repair, 79 focused
tests passed across native reply, decline guidance, agent evidence and
journey contracts. A two-successful-run control rejects the earlier
receipt and accepts the later one. Negatives cover stale/wrong run,
wrong agent/task, missing final proof, summary/unsettled/hidden output,
false explanations and unread service data.
- Product E2E TypeScript and `git diff --check` passed.
- Live protected-action qualification is required after merging this and
the companion private service/cleanup fixes. The previous failed result
remains failed; this is a bounded task-clarity experiment, not a claimed
model or completion-schema repair.
- Current-head Greptile and Paperclip reviews are 5/5 with zero open
threads. CI initially failed the unrelated agent-chat-projects cleanup
POST with a PostgreSQL lock timeout after its assertions completed. One
bounded retry passed on unchanged source; all current-head gates passed
at `64bc169e147290ed4dbaa18221e0268362ce81ee`. The original failing
attempt and its logs remain available. The task-clarity change is still
a bounded experiment; the observer repair addresses a demonstrated
storage-assumption defect.

## Risks

A clearer task can still fail with the selected model. All acceptance
checks and completion input validation remain strict; a saved briefing
alone cannot qualify the complete journey. Only test prompts and test
evidence code change. Missing or contradictory native evidence fails
closed.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 22:14:37 -05:00
DottaandPaperclip 59b76777db test: clarify onboarding artifact completion instructions (#18258)
## Thinking Path

> - Paperclip helps people manage AI agents and inspect their work.
> - Product E2E journeys test that work through normal browser and API
controls.
> - The Cloud onboarding journey asks one native child to publish a file
and save a document.
> - Its task request did not explain the completion report format or
make each output step distinct.
> - A live attempt published the file, then submitted an invalid finish
report and declared a blocker.
> - This change orders the scripted request and explains the existing
completion contract.
> - The agent must still produce the result and pass the same
independent checks.

## Linked Issues or Issue Description

Refs #17940. Refs #18228.

**What happened?**

The scripted onboarding request left completion details implicit. A live
child published its proof file, then submitted a finish payload without
verification and with an invalid schema value. Its later blocked report
also listed local paths as artifacts. This does not establish a Core
validator defect.

**Expected behavior**

The request should explain the existing tool contract. The child must
publish the file, save the document with its returned link, then submit
a valid completion report. Argument correction must not replace artifact
verification or bypass approval.

**Steps to reproduce**

Run the explicit Cloud onboarding Product E2E journey through its
private target provider. Approve the proposed child through the UI.
Inspect the native finish report and the independently checked
attachment, document, and parent links.

**Paperclip version or commit**

The observed deployment used public Core
`6a674716447e8fa268c5cdeb1db1020319368a77`. This fixture change starts
from `a8e07500db68f187b19de83823eb7fabf1196021`.

**Deployment mode**

Cloud testing with the scripted Product E2E harness.

## What Changed

- Order the child request: create files, publish the proof, save its
document, then finish.
- Require verification for actual checks and omit the optional schema
field.
- Explain receipt-derived references in evidence and file artifacts.
Keep local input paths in verification details.
- Document same-attempt argument correction and preserve historical
failed results.

## Verification

- Existing onboarding-first-task and artifact-evidence suites: 83 checks
passed.
- The maintained harness unit wrapper also passed 137 Node contract
checks.
- Independent source review found no contract, privacy, or oracle
change.
- Full `pnpm build` and `pnpm -r typecheck` passed at the preceding
commit `c3900cf2`. The only later change names the filename required by
the existing document assertion.
- Current `d75180b4`: the 83 fixture/artifact checks, 137 contract
checks, and `pnpm test:e2e:runner:typecheck` passed again.
- Credential-free `--list --suite product-journeys` passed.
- The local full repository Vitest run at `c3900cf2` was stopped before
the filename correction. It is incomplete and is not reported as a pass.
Current-head CI passed: 54 successful checks and two optional Storybook
skips. The separate advisory review is still running and is not reported
as passed. Initial fresh-worktree dependency and sandbox IPC failures
remain recorded.
- No paid model, Cloud workspace, release, or deployment was run for
this change. These checks establish harness compatibility, not a live
model pass. The prior failed campaign remains failed.

## Risks

The model may still submit an invalid report or fail another step. A
fresh live journey is required to measure the instruction change. This
PR changes fixture text and documentation only. It supplies no result,
checksum, real attachment ID, or successful status. Models, limits,
validators, and independent assertions stay the same.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, ultra reasoning. The model identity comes
from confirmed parent runtime metadata. Context window size is
unavailable. Tools and code execution assisted the change and review.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 22:02:51 -05:00
DottaandPaperclip 2badf8a4a5 fix(evals): verify native QA replies on the reloaded task thread (#18248)
## Thinking Path

> - Paperclip manages AI agents that do work for users.
> - Product E2E journeys check user outcomes on real deployments.
> - Native task threads can render saved final replies from a settled
run.
> - The new QA Plan and Stop checks looked only for agent comments.
> - Both flows reached the requested terminal state and showed the
correct reply, but that storage assumption rejected them.
> - This PR checks the reloaded visible reply and binds it to the final
successful run. Explicit presentation decisions remain authoritative.

## Linked Issues or Issue Description

Refs #18222 and #18244.

**What happened?**

The deployed Plan journey completed all three native runs, including
revision and approval. Stop completed native cancellation, resource
release and a new direction. Their final-answer checks failed because
the comments endpoint did not contain the rendered native reply. The
original failed grades remain unchanged.

**Expected behavior**

Require exactly one correct visible final answer after reload,
attributed to the final successful owned run. Reject an earlier run,
progress text, hidden content, duplicate answers or a cancelled run. If
its selected completion comment is projected, require that comment and
matching author/run/text. Otherwise require a single durable final
assistant message and its settled native final-response anchor.

**Steps to reproduce**

Run the Plan or Stop journey on a native deployment whose task thread
renders the settled run before a completion comment is projected.

## What Changed

- Add a narrow reply observer over the existing task-thread hooks. It
reloads the page and refreshes saved run/comment metadata while waiting.
- Bind native replies to a validated durable final assistant event and
the successful run's settled final-response anchor. Require the selected
comment when projected; support pending or suppressed projection without
accepting a summary fallback. Accept payload and item-normalized finals,
rejecting contradictory fields.
- Use the observer for Plan completion and Stop's new direction. Keep
existing run counts, deployment binding, cancellation and artifact
checks.
- Add negative grading tests, include the helper in the definition hash,
and document its evidence contract. Classic protocol comment matchers
are unchanged.

## Verification

- 63 focused tests passed across native reply evidence, agent evidence
and journey contracts.
- Product E2E TypeScript passed. The reply observer uses the remaining
journey deadline and backs off polling.
- Live Plan and Stop attempts exposed this grading failure. Their
original outcomes remain failed; fresh qualification is required after
merge.
- Full current-head CI passed at
`40840ed742977853630d733292461ad7003fc7fb`; Greptile and Paperclip
Review both scored 5/5, with zero unresolved review threads.

## Risks

The observer depends on existing task-thread test hooks and run anchors.
Missing or changed hooks fail closed. It reads rendered user-facing
text; a finish summary alone cannot satisfy it. Native event provenance,
run ownership and exact reply equality are required. No backend, model,
provider, budget or cancellation policy changes are included.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 21:35:15 -05:00
DottaandPaperclip 8941db9ce6 fix(evals): accept editor escapes and cancel sensitive QA requests (#18244)
## Thinking Path

> - Paperclip manages AI agents that do work for users.
> - Product E2E journeys check real browser actions and saved results.
> - A rich editor can store plain underscores as escaped Markdown.
> - The QA reply check treated that valid saved message as a failure.
> - A private target adapter also needs to cancel credential-safe HTTP
requests before cleanup.
> - This PR fixes reply comparison and adds abort and timeout options to
the existing sensitive transport.

## Linked Issues or Issue Description

Refs #18222.

**What happened?**

The artifact revision and Stop journeys rejected the correct single user
reply because its underscore was stored as `\_`. Sensitive connection
setup also lacked a way to pass its lifecycle signal to the actual HTTP
request.

**Expected behavior**

The check accepts the editor's underscore escape and still rejects
changed, duplicate, missing, or foreign replies. A cancelled sensitive
request closes before setup cleanup proceeds.

**Steps to reproduce**

Run an artifact revision with an underscore in the reply. For the
transport case, abort a pending sensitive request or let its deadline
expire.

## What Changed

- Compare the fixture reply after undoing only underscore escaping. Keep
exact text, count, and author checks.
- Let `ConnectionApi.postSensitive` accept a bounded timeout and abort
signal. Check cancellation again after cookie loading and before
dispatch.
- Test the retained reply failure and both cancellation paths with an
actual loopback HTTP server. Document the adapter contract.

## Verification

- Focused Product E2E tests: 30 passed across two files.
- Product E2E TypeScript check passed. After rebase, a final check first
found four diagnostics from stale runner/plugin SDK declarations;
rebuilding those two workspace packages cleared all four, and the
unchanged E2E check passed.
- The first sandbox run failed because loopback `listen` returned
`EPERM`. The unchanged HTTP tests passed with loopback permission. The
test now reports listener errors directly.
- Both independent reviewers found a possible pre-arrival deadline-test
hang. The follow-up races arrival against request settlement and adds
one second of deadline headroom. All 30 affected tests passed after that
fix.
- Full current-head CI passed in run 40982914525. Greptile and Paperclip
Review both scored 5/5 at `f0526f5fbbf13de5ea43e868eb012069ca3d8907`;
all review threads are resolved. Live QA requalification follows the
merged public and private fixes; no live pass is claimed here.

## Risks

The text normalization applies only to plain fixture replies and only
removes underscore escapes. It does not remove arbitrary Markdown.
Sensitive calls retain their existing 30-second default and closed error
messages. API wrappers must forward the optional signal and await the
actual request.

## Model Used

OpenAI Codex, GPT-6 family. The serving model ID and context window are
not exposed by this session. Used reasoning, code editing, shell
execution, and test inspection.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 20:14:56 -05:00
Nicky LeachandClaude Opus 5.5 7d194e901f feat(ci): merge lockfile refresh PRs through a dedicated bot (#18238)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - CI owns `pnpm-lock.yaml`. Contributors do not commit it, so a
poisoned lockfile cannot come in from a community PR.
> - `refresh-lockfile.yml` regenerates the lockfile from the manifests
on master and opens a PR.
> - That PR waits on required checks and code owner review. A
`GITHUB_TOKEN` push does not start the checks, so a maintainer must
merge each PR by hand.
> - The PR content comes only from manifests that maintainers already
reviewed on master. A human review adds little.
> - This pull request lets a dedicated GitHub App merge the refresh PR
at once, without CI or review.
> - A release-age gate holds the merge when the refresh adds a package
version that is less than 3 days old on npm.
> - The benefit is a lockfile loop that closes itself, without a bypass
for any identity that other workflows can use.

## Linked Issues or Issue Description

Refs #12115 (the same stuck-PR problem, fixed there by starting the
checks). Refs #18219 (an example refresh PR that needed a manual
approval and merge).

**What happened?**

Each lockfile refresh PR stays open until a code owner approves it and a
maintainer merges it. The required checks `ci / verify` and `ci / e2e`
also do not start, because the workflow pushes with `GITHUB_TOKEN`.

**Expected behavior**

The refresh PR merges with no human action and no CI run, unless it adds
a package version that is too new to trust without review.

**Steps to reproduce**

Merge a manifest change to master. Look at the `chore/refresh-lockfile`
PR that the workflow opens. It stays blocked.

## What Changed

- `refresh-lockfile.yml` runs in a new `lockfile-refresh` environment.
Only `master` can use this environment.
- The workflow creates a token for a dedicated lockfile bot app after
dependency resolution is complete. The token has only contents and pull
request write access.
- The workflow merges with `gh pr merge --squash --admin
--match-head-commit <sha>`, not `--auto`. It merges only the commit that
it pushed.
- New `.github/scripts/check-lockfile-release-age.mjs` compares the base
and refreshed lockfiles. It looks up the npm publish time of each added
package version. The bot merges only when every version is at least 3
days old. A lookup error, a missing publish time, a non-registry
version, or a resolution that is not a plain registry tarball also holds
the merge.
- When the gate holds the PR, the workflow posts or updates one report
comment on the PR and does not merge.
- A daily schedule runs the refresh again, so a held PR merges after its
versions are old enough.
- A held run uploads its lockfile as a `held-pnpm-lock` artifact. The
artifact records the hash of the master lockfile it started from. The
next master run resolves from it only while master still has that
lockfile, so held versions stay while their manifests do not change, and
a maintainer's lockfile correction replaces them. The workflow does not
read the PR branch for this, because users with write access can push to
it.
- The generated PR body now describes the gate.
- `tests/runner-e2e/OPERATIONS.md` now says that the bot can merge the
report-lock correction without review, under the same gate.
- New `lockfile-refresh-merge.test.mjs` pins the merge safeguards: the
environment, the step order, the gate conditions, and
`--match-head-commit`.
- `doc/RELEASE-AUTOMATION-SETUP.md` §8.1 tells an admin how to create
the app, the environment, and the ruleset bypass. It also tells why we
do not use `github-actions` or `commitperclip` for the bypass.

## Verification

- `node --test .github/scripts/tests/check-lockfile-release-age.test.mjs
.github/scripts/tests/lockfile-refresh-*.test.mjs` passes (17/17).
- I ran the gate against the real lockfile diff of #18219 and the live
npm registry. With 3 days, all 7 added versions passed
(`eligible=true`). With 60 days, it held all 7 `turbo` 2.11.10 versions
(9.1 days old) and wrote the report.
- The workflow YAML parses. actionlint did not run, because it is not
installed locally and Docker was not available.
- No live run yet. After the admin setup in §8.1, run the workflow with
`workflow_dispatch` on master, or merge a manifest change. Then make
sure that the bot opens and merges the refresh PR.

## Risks

- **Setup order.** An org admin must do the steps in §8.1 before this PR
merges. If not, the next refresh fails at the token step, and the PR
stays open for a manual merge, as it does now.
- **No CI on lockfile changes.** A bad resolution can land on master
without a check. The next manifest PR or the canary release shows the
problem.
- **Release-age gate limits.** The gate stops only fast-detected attacks
on new versions. A malicious version that stays undetected for more than
3 days still merges without review. Lockfile changes that add very new
versions now wait for a maintainer or up to 3 days.
- **Bypass scope.** The app bypasses the master ruleset only in pull
request mode. It cannot push to master directly. Only the master-only
`lockfile-refresh` environment holds its key. If the key leaks, the
holder can merge any open PR past review. Rotate the key if you think it
leaked.
- **More master runs.** A merge by an app token starts push workflows on
master. A merge by `GITHUB_TOKEN` does not. After each lockfile merge,
the canary release runs, and the refresh workflow runs again with no
change.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, in Claude Code with
tool use (shell, file edit, GitHub CLI).

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 17:55:02 -07:00
DottaandPaperclip ebed7f5237 test(evals): protect Antigravity setup and two-turn delivery (#18190)
## Thinking Path

> - Paperclip manages agents and their work.
> - A provider integration must work through ordinary agent setup and
task controls.
> - The recorded Antigravity walkthrough exposed setup, delivery, and
continuation failures.
> - A repeatable check must verify real work and retain failed attempts.
> - This pull request converts all 47 recorded steps into one fixed
Product E2E journey.
> - Maintainers can rerun the case and inspect independent delivery,
cleanup, and accounting evidence.

## Linked Issues or Issue Description

Builds on merged #18187, #18188, and #18189, and consumes the shared
repairs from merged #18230 and the equivalent manual-policy declaration
from #18222. Refs #18214 for the CI task wrapper. Refs #12503 and #14938
for related legacy adapter work.

**Agent or provider**

Google Antigravity native Runner with a saved managed Google
subscription and the exact Low model.

**Why this adapter is useful**

A user must be able to add an agent, connect its account, and receive
real task results across a follow-up. Picker visibility alone is
insufficient.

**How the agent is invoked**

A fixed Playwright driver uses ordinary product controls. The agent runs
through native ACP. Independent checks use public APIs, actual
downloads, owned process observations, and native lifetime fences.

## What Changed

- Register one explicit-only case:
`antigravity-agent-journey.runner-antigravity.local.saved-subscription-two-turn`.
- Map all 47 source steps and declare saved-account prerequisites,
finite limits, and same-host macOS ARM64 scope.
- Create an agent through the ordinary picker, connect the saved
account, select Low, run Test, and wait for readiness. Save an
instruction marker, deliver a file, and update it through an ordinary
follow-up.
- Require each run's visible completed file activity, exact downloaded
bytes, committed Done result, same tagged conversation, distinct
physical owner birth, released lease, and free native fences. Verify
reload persistence.
- Stop failed native runs that still own a retry. Replay an existing
Stop with its durable request identity and wait for the matching audited
acknowledgement. A terminal reservation without a native intent remains
unconfirmed.
- Keep private evidence in the existing result, report, dashboard, and
accounting pipeline. Retain the paused QA agent and financial history
while preserving the shared account and budget policies.
- Journal only the ordinary wizard's future ID, target, name, intended
harness and expected creator before forwarding its POST unchanged. Bind
the response and interrupted recovery to exact identity reads; a pending
404 stays unconfirmed.
- Serialize private resource snapshots through temporary-file fsync,
atomic rename and directory fsync. Abort forwarding on storage failure
and preserve legacy receipts. If later journal or diagnostic writes
fail, retain the primary error, always close the browser, and attempt
the ordinary failed report.
- Add production-component browser controls and harden task-menu
readiness, alias selection, scroll restoration, failure packaging, and
one hermetic auth-test budget.
- Wait for the existing GitHub recovery fixture to register its next
deadline before asserting the original range; preserve its
nested-transaction and zero-request checks. In the decision-expiry
fixture, verify the exact saved expiry separately from the earlier
global wake of another queue.

## Verification

- Fresh registered acceptance passed on eval source
`9060f3cd01b7c3445ecdf703d72e9cf30fe42b59` and merged serving product
`61bd4ac6919c2309f766a25e62273b074cee3261`. It completed ordinary setup
and two turns with native `.5` and `gemini-3.8-flash-low`. All 16
matchers, 14 checkpoints, and cleanup passed in **165,613 ms**. Actual
downloads were **61 bytes** and **119 bytes**. Both turns passed their
own run-bound browser activity checks and reload persistence.
- Independent read-back confirms Done, a paused retained agent, the same
connected saved default account, and no active owned run. Both accepted
results have the same full tagged conversation and distinct primary
process births. All 21 observed processes retired; both leases released
and all three native fences were free after each turn. The selected `.5`
checkpoints also showed equal agent/backend session IDs; this is an
observed case requirement, not a generic ACP invariant.
- Receipts report 339,273 input tokens, 7,224 output tokens, and 202,846
cached input tokens. Subscription prices are unavailable. Billing
coverage remains incomplete, not free.
- The normal report CLI passed. All 310 files from nine original
attempts and two separate recoveries retained their hashes. The twelve
current screenshots are byte-identical, and 194 local report links are
contained and valid. The eight earlier reports were copied without
regeneration.
- Delivery source `1bf4fb04df04710b82844b3c9355767f46b5f68f` branches
from `d3f2a60e795fc60d64c8b19d1eed4d48657d5492` and merges cleanly with
current master `1d571de5f9f886d66e520800baec8fc2f67d0948`. All 41 prior
`c8b332` authored file blobs remain identical; the 42nd path is the
decision-expiry fixture contract correction. Creation ownership, the
strict durable writer, and the ordinary successful workflow remain
unchanged. Of 43 measured file blobs, 30 remain identical. The
Antigravity oracle, artifact, billing and report gates and its
suite-specific validation block remain unchanged. The actual retained
agent matches its original creator; its original request `setupId` was
not captured and is not reconstructed.
- Later master changes include model-visible workspace guidance and
rejected-terminal-report handling. Their bounded source assessment is
separate: the first actual finish failed, then a same-turn replacement
was accepted and committed. Later read-only results match both original
native-result hashes, and the complete event catalogs have no
`session.failed` event. Master #18228 also expands detection of explicit
JSON file requests. The measured create/update-and-attach `.txt` task
already required publication under both parsers; the publication
validation gate itself is unchanged. Master #18240 changes remote
workspace cache staging and adds an OpenCode index refresh. The selected
local lane returns before those paths. Master #18213 adds optional
numeric turn timing and trace boundaries. Its selected Antigravity
model, text, IDs, result and retirement semantics remain unchanged in
the bounded source review. Local diagnostic rows and awaits can change
event ordinals and latency; the oracle checks relative semantic order.
Collector coverage and latency improvement remain outside this proof.
This does not claim that the whole current runtime is byte-identical to
serving `61bd`, or relabel the measured result as a new run.
- The adopted upstream cache controls passed 3/3 with pinned real Turbo.
Forced work disables local and remote reads and writes; ordinary work
reuses local results. The original genuine-pnpm/Turbo controls remain
historical to `9060`'s earlier write-only policy. The duplicate cache
patch is superseded by #18230. Its qualification-only pnpm addition is
removed because the adopted upstream controls do not require it.
- The E2E typecheck, map checks and 277-control replay are carried from
the unchanged eval source paths. That replay passed, including the 183
Antigravity controls, catalog/connection checks and the separate
product-journey validator. The carried creation controls include 91
config/recovery cases. The final launcher suite passed 19/19, including
five real campaign finalization fault cases; the report suite passed
7/7. These final checks did not rerun the earlier 277-control group. The
canonical production-component browser spec passed in 27.4 s under its
unchanged 60 s limit before the replay. Four paused-composer cases and
the product base's build/typecheck plus 376 focused regressions were
verified earlier.
- The shipped wizard and actual API client cover persistence before
forwarding, lost response JSON, foreign/malformed requests, wrong
response identity/creator and cleanup-error preservation. Real
filesystem controls failed 5/5 before the writer repair and passed 5/5
afterward, preserving the old journal on partial-write, temporary-file
sync and rename faults. Three persistent-sync campaign controls failed
before the finalization repair and passed afterward. All five final
campaign fault cases preserve the primary failure, cleanup failure,
usage and failed report while attempting browser closure. The strict
journal still blocks the next mutation. These are provider-free
ownership controls; the Google task proof remains the original `9060` →
`61bd` acceptance.
- The decision restart check passed in the local 20-case fixture run. A
current-source real-PostgreSQL rollback control reproduced the exact
90,000 ms earlier global wake: the old equality rejected it, while the
exact durable expiry and new future-wake bound passed. The original 60 s
open-state, exact-timestamp, continuation and quiet checks remain. The
broader local run was **FAILED: 19 passed / 1 failed**, with a 15 s
timeout and a 30 s cleanup timeout in an unchanged timestamp-pagination
case. That case passed in canonical `c8b332` CI; the local timeout cause
remains inconclusive. An extra local server typecheck failed against
stale cached Runner declarations; it did not check this excluded test
file. Both limits remain recorded for fresh canonical CI.
- A broader local GitHub recovery group passed 21/22. Its unchanged
pagination case observed an unexpected config request; the log does not
establish the cause. That result remains retained, and fresh
current-head CI is the final broader gate.

- Exact delivery-head CI completed with 55 successes, two skips, and one
optional neutral review. Required `ci / verify` and `ci / e2e`, build,
typecheck, and Runner checks passed. Fresh Greptile is 5/5 with zero
unresolved threads. Optional Paperclip is neutral 4/5; its carried
recommendations are dispositioned against the public Stop contract and
selected live identity evidence.

Seven earlier converted attempts retain their failed grades and partial
evidence. Historical Paid8 and its later read-only per-run UI
observation remain separate from the fresh acceptance above. Unknown
prices and the older partial startup accounting remain explicit. Full
lineage and raw evidence remain private in the normal report bundle.

## Risks

- This case requires an authorized saved personal default Google
subscription and finite operator candidate admission. It does not test
fresh OAuth or establish global qualification.
- The physical observer supports a same-host loopback macOS ARM64
target. Cloud, Linux, and other models remain outside this case.
- A known-cost stop cannot cap missing prices or in-flight subscription
charges. Existing operator policies remain unchanged.
- Raw account/native identities stay private. Missing retirement proof
keeps resources retained. The selected cleanup mode does not test agent
purge.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 19:51:32 -05:00
DottaandPaperclip d3f2a60e79 test(e2e): reuse core journeys across deployment targets (#18222)
## Thinking Path

> - Paperclip manages agents and their work.
> - Product E2E tests verify work through the browser and public APIs.
> - The classic matrix already tests several common task stories.
> - Its older stories depend on local fixture setup and workspace
access.
> - Deployment tests need the same story checks with a separate target
adapter.
> - This PR shares those checks and adds five explicit journey
selections.
> - A deployment pass still requires evidence from that deployment.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Product E2E journey reuse across managed instances and deployed Cloud
instances.

**Current behavior**

The deployed-target catalog covers task creation, assignment, Ask, and
fresh onboarding. Plan revision and Everyday stories run through the
classic fixture driver. Several story steps assume a local workspace.

**Proposed behavior**

Add explicit Plan revision, artifact revision, protected-action approval
and decline, Skill Studio, and Stop/redirect journeys. Share the main
browser sequences and content checks with the classic driver. Let target
adapters provide authentication, native agents, a reachable service
fixture, and owned cleanup.

**Reason and benefit**

A local pass cannot verify the deployed application. Shared story code
lets a deployed target exercise the same behavior without copying an
entire test or starting a replacement server.

**Breaking changes**

No product API or default matrix selection changes. Passed deployment
results must satisfy the declared story checks and work-run count.
Unsupported target capabilities fail before a story runs.

Related public work: #17262 and #18098. Upstream prerequisite: #18230.

## What Changed

- Extract shared Plan, artifact download/oracle, protected service,
Skill Studio, and Stop/redirect helpers. Keep classic callers on those
helpers.
- Add five explicit paid journey selections with owned-task observations
and native company, agent, model, and environment checks.
- Include classic prompts, delivery/decision code, and the decline
grader in the source-definition hash. Keep classic transient-read
retries and reject deployment binding failures immediately. Match cookie
directory boundaries in sensitive fixture requests.
- Require complete story checks and expected run receipts before
retaining a passing result. Keep failed evidence and private downloads.
- Add a secret-safe request method for deployment fixture credentials.
Add the missing declaration for the existing manual evidence policy
module so the E2E project can typecheck.
- Document target responsibilities and promotion after a real deployment
pass. This source catalog does not enroll candidates in a daily plan.

## Verification

- E2E TypeScript check: passed, including the review follow-up.
- Review follow-up: 30 tests passed across four files, covering
transient Plan reads, immediate binding rejection, cookie-path scope,
agent receipts, and artifact evidence. Stop now waits for a saved,
still-active native turn before the browser click and retains its
startup events. Counterexamples reject claimed-but-unstarted,
already-completed, interrupted, and non-native work. Shared observation
and API helpers also enter the definition fingerprint. Cancellation
snapshots are captured before lease cleanup. A direct terminal-boundary
assertion rejects native work after cancellation even if it is already
in the first snapshot; five cleanup-window counterexamples are covered.
The Stop-output regression first failed for both native `item.delta` and
`item.completed`; the fixed check detects both while allowing
accounting-only updates. A report-catalog test first failed because the
sandbox denied the tsx child IPC pipe (`listen EPERM`); the unchanged
test passed outside the sandbox.
- Affected journey, catalog, API, service fixture, and delivery checks:
313 tests passed across 19 files.
- Workspace build: passed after rebase.
- Workspace typecheck: passed. The default repository run was attempted.
Repeated embedded PostgreSQL startup failures prevented local database
coverage; it was stopped without claiming a full pass. Linux CI must
supply that coverage.
- Broad E2E support run: 4,793 passed, 23 failed, 2 skipped. Failures
include existing stale image/Pi assertions and process/startup timeouts
under host load. The affected tests pass separately. This is not a claim
that the broad suite is green.
- Upstream CI prerequisites: this branch is rebased on the merged #18230
repair. The earlier conflicting Turbo flags no longer apply. The
shell-hook fix is also supplied by that upstream change. Linux
shell-hook investigation: 19 focused tests and adapter TypeScript
passed. The exact staged-config sequence reproduced CI's 500 in a pinned
Node 24 Linux container. Node's default stdin socket at shell level zero
selects Bash remote-shell startup and reads `.bashrc` instead of
`BASH_ENV`. Ignored stdin and a nested shell each produce 1000. The
fixture now ignores stdin; the production hook and 1000 assertion are
unchanged. See [Bash startup
rules](https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files).
- GitHub CI on the earlier head passed most suites but failed two
browser tests (a fixture cleanup lock timeout and a fixture run staying
queued) plus the shell-hook assertion. The lock-timeout case received
one retry, which was cancelled by a later source push and does not
establish recovery. These failures remain part of the verification
record.
- Real Cloud qualification: the private target adapter is reviewed and
merged. These candidates must pass there before daily-plan promotion.

Current source review: Greptile 5/5 and Paperclip Review 5/5 on
`a9df1d6e8d880710fce39b87e689e07e1c8e6edc`, with zero unresolved review
threads. The full [GitHub CI
run](https://github.com/paperclipai/paperclip/actions/runs/40974946081)
passed on that exact head, including both required aggregate checks.

## Risks

Shared helper changes affect classic callers. The independent ZIP oracle
and visible delivery requirements remain in place. Stop requires native
acknowledgement, terminal event evidence, resource cleanup, and no later
original-turn activity. The managed local target still lacks paid-agent
fixtures and reports these journeys as unsupported.

## Model Used

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

## Checklist

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

- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 18:58:26 -05:00
github-actions[bot]andlockfile-bot 1843d27e09 chore(lockfile): refresh pnpm-lock.yaml (#18219)
## Thinking Path

> - Paperclip uses a dependency lock for reproducible builds.
> - Dependency changes on master need matching lock entries.
> - Paid eval reports also pin a reviewed offline correction.
> - Reports must install before paid model work starts.
> - This automated PR keeps the lock and report proof together.

## Linked Issues or Issue Description

**What happened?**

Dependency manifests on master changed after the last committed lock
refresh.

**Expected behavior**

Frozen installs must match those manifests. Eval reports must retain
matching offline lock proof.

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

- Refresh the dependency lock from the manifests on master.
- Include the matching offline report correction and hashes.

## Verification

- Pinned pnpm resolution completed with lifecycle scripts disabled.
- The report proof refresh accepted the reviewed committed baseline.
- Required PR checks and reviews must pass before merge.

## Risks

Dependency changes require review. Unknown report lock baselines remain
blocked. This update changes no permissions or paid enable gates.

## Model Used

None — generated by pnpm and the deterministic report-lock updater.

## Checklist

- [x] Thinking path and problem description included
- [x] Generated lock and matching report proof included
- [ ] Required CI checks and reviews pass

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-10-29 16:32:42 -07:00
DottaandPaperclip 99d27fd5e7 feat(evals): add a metadata overview for the chat catalog (#18194)
## Thinking Path

> - Paperclip is a control plane for AI agents that do work.
> - Its evaluation reports separate recorded results from source
coverage.
> - A case without a main baseline measurement can still have a
candidate run.
> - A normal campaign card treats an expected execution without a result
as missing evidence.
> - Catalog planning data must not create those cards or change a
recorded grade.
> - This change adds a typed metadata view to the existing Evals
dashboard.
> - Readers can compare main outcomes, candidate execution, allowances
and source review separately.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The existing Evals dashboard can show a campaign's retained results. It
cannot show the full chat catalog as metadata without synthetic result
entries.

**Current behavior**

An unused initial, an unknown allowance and a completed candidate run
can all lack a main baseline result. Showing them as missing campaign
artifacts hides these differences.

**Proposed behavior**

Add one validated metadata view in the existing renderer. Show one row
per frozen scenario, separate execution and main outcome columns,
filters, and the public request and expected outcome from static YAML.
Keep normal campaign cards unchanged.

**Reason and benefit**

Readers can see which cases ran, which have no main measurement, and
which still need preparation. Source review and candidate outcomes
cannot add baseline pass credit.

**Breaking changes**

None to existing campaign inputs or outputs. The new metadata mode uses
its own strict schema and requires a new private output directory.

No matching open or closed PR or issue was found in the duplicate
search.

## What Changed

- Add a strict display-only catalog schema with closed enums and fixed
catalog scope.
- Validate the 244 row identities against static YAML without importing
executable case callbacks.
- Show main results, recorded execution, allowances and source review in
separate columns.
- Add search and filters, passing examples, qualification notes and
expandable public test descriptions.
- Add one dated immutable snapshot link in the existing shared report
navigation. This does not change history data or update an
already-published page.
- Add a private metadata preview command to the existing dashboard
owner. Keep existing campaign generation on its current path.
- Keep allowance certainty independent of measurements and allow an
optional later candidate outcome alongside a main outcome, without
changing main counters.
- Add focused pure, JSDOM and file-loader checks. Document the metadata
command.

## Verification

- The owning `catalog-overview.test.ts` Vitest suite passes all fourteen
tests under the focused source configuration. The
valid-main/unknown-allowance and main-fail/later-candidate-pass controls
fail against the old renderer and pass with this repair. The
never-run/unknown-allowance control fails against e8686bf and passes
with the restored consistency guard.
- Scoped TypeScript verification of the changed source and its imports
has no diagnostics.
- The tests cover closed schema fields, duplicate and invented IDs,
candidate/main separation, filters, HTML escaping, private output mode,
existing output refusal, symlink and oversized input refusal, static
descriptions, and the normal campaign branch. Ceiling values below,
equal to and above the target are covered. Unsupported navigation is
hidden only in metadata mode.
- The source was independently reviewed. Actual generated DOM validation
also checked 244 rows and all public descriptions.
- No visual browser verification or live product journey is claimed. No
credentials, private projection, generated report or evidence files are
included in this PR.
- Repo-wide builds were not run locally for this report-only slice.
Normal remote CI passed on repair head `f813c18`, with 55 successful
checks, two skipped checks and one neutral review check. Required `ci /
verify` and `ci / e2e` both passed. Current-head Greptile is 5/5 and no
review threads remain open. The e8686bf normal CI had an initial failed
attempt and a successful failed-only replay. Both are retained; that
replay does not substitute for current-head verification.
- The first f813c18 CI attempt passed 373 tests in serialized server
shard 4/9 but failed one existing scheduled-retry test: its intermediate
cancellation count was 29 rather than 20. The actual CI-tested test,
route, worker, scheduler and DB-fixture source matches prior passing CI.
The one failed-only replay passed all 374 tests in that shard on the
unchanged head. The first failure remains recorded; no assertion or
timeout changed.
- Rendering the authenticated existing projection through both old and
new generators produces byte-identical HTML and both assets. The
already-published dated snapshot is unchanged.

## Risks

The view depends on an authenticated metadata projection. Shape
validation does not qualify source or execution. The view preserves
unknown states and keeps candidate outcomes outside main qualification.
The preview command does not publish reports or alter history. Existing
campaign result behavior remains separate. Shared navigation gains one
dated link. Existing published pages need a separate conditional
activation; this PR does not upload or rewrite them.

## Model Used

OpenAI GPT-6 through Codex, with source editing, tool use and pure/JSDOM
checks. The exact serving model ID and context-window size are not
exposed to this worker.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 16:05:12 -05:00
github-actions[bot]andlockfile-bot 4a6f6a65eb chore(lockfile): refresh pnpm-lock.yaml (#18185)
## Thinking Path

> - Paperclip uses a dependency lock for reproducible builds.
> - Dependency changes on master need matching lock entries.
> - Paid eval reports also pin a reviewed offline correction.
> - Reports must install before paid model work starts.
> - This automated PR keeps the lock and report proof together.

## Linked Issues or Issue Description

**What happened?**

Dependency manifests on master changed after the last committed lock
refresh.

**Expected behavior**

Frozen installs must match those manifests. Eval reports must retain
matching offline lock proof.

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

- Refresh the dependency lock from the manifests on master.
- Include the matching offline report correction and hashes.

## Verification

- Pinned pnpm resolution completed with lifecycle scripts disabled.
- The report proof refresh accepted the reviewed committed baseline.
- Required PR checks and reviews must pass before merge.

## Risks

Dependency changes require review. Unknown report lock baselines remain
blocked. This update changes no permissions or paid enable gates.

## Model Used

None — generated by pnpm and the deterministic report-lock updater.

## Checklist

- [x] Thinking path and problem description included
- [x] Generated lock and matching report proof included
- [ ] Required CI checks and reviews pass

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-10-29 12:41:33 -07:00
DottaandPaperclip cd0c86e5e1 fix(evals): support private evidence for the frozen chat catalog (#18170)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product E2E tests need to retain evidence from both successful and
failed work.
> - Manual private runs use the existing protected AWS evidence route.
> - Its fixed eight-case registry blocks other scenarios in the frozen
chat catalog.
> - Failed Playwright cells also produce static trace files that need
exact owner and content checks.
> - This pull request admits the fixed catalog, keeps eight cells per
run, and retains the existing report identities.
> - Exact source and run approval still controls each private operation.

## Linked Issues or Issue Description

Refs: #18134, #17888.

**What happened?**

The manual private route accepts only its first eight execution IDs. It
rejects other IDs from the frozen 244-scenario chat catalog before a run
can start. The dotted `area.case` report identity also fails the
retained report parser. A failed Playwright cell can produce canonical
trace assets that the private evidence owner does not yet recognize.

**Expected behavior**

The trusted route must recognize exactly the frozen 244 OpenCode/local
execution IDs. Each original run must still select at most eight cells
and have exact protected approval. The evidence owners must retain
complete scanned originals from the actual pinned report producer.
Unknown carriers and credential contamination must still fail closed.

**Steps to reproduce**

Use a known frozen chat ID outside the first eight with the current
manual classifier. The classifier rejects it. Parse a dotted chat
execution ID with the current report parser. The parser rejects it.
Generate a synthetic failed Node-only Playwright test and pass its
actual trace/report tree through the private evidence owners.

This change includes the narrow parser repair from the existing open
#17888. It does not merge or close that PR. The related source work was
checked for overlap before this branch was created.

## What Changed

- Replace the small private registry with the exact frozen 244 execution
IDs. Preserve the two existing undotted standalone task IDs.
- Keep the private run limit at eight through classification, approval
rows, cell binding and transfer sessions. Preserve nonprivate selector
behavior.
- Bind private cell report assets to the actual installed pinned
producer, selected cell, canonical path and exact bytes before the
existing scans and archive checks. Pass that verified owner into both
real launcher packaging calls.
- Exclude installed build staging from the private evidence walk. Retain
the real standard-file cap and reject unknown nested carriers.
- Add the existing dotted chat report grammar. Preserve other report
families and legacy task IDs.
- Use the existing public announcement dismissal control in one
external-link/upload E2E test so a real announcement cannot cover its
composer button. Preserve the open menu and existing timeout.
- Document source compatibility and operator gates. No workflow,
product, dependency, lockfile, case callback, query, clock or budget
changes.

## Verification

- 132 distinct focused controls are closed. The current affected owner
suite passes 39 controls under a nondefault temporary directory. The
other 93 unchanged controls retain their previous passes. The initial
registry, map-order and test-tooling failures remain recorded.
- Two actual launcher call-expression controls fail on the prior source
because canonical trace files are dropped. Both pass after the
private-owner wiring. These controls do not claim full launcher
lifecycle or actual E2E qualification.
- Temporary paths use the real operating-system temporary directory,
including the handoff check.
- The controls check all 244 IDs through real private routing, cell
binding and original-run approval. They reject unknown IDs, aliases,
wrong profiles, traversal, private duplicates and excess private cells.
- The controls preserve actual nonprivate 33-ID and duplicate selector
behavior.
- A real synthetic Node-only failed Playwright test produces the report
and automatic trace. The control uses actual package, seal, archive,
receipt and restored validation paths with mock AWS transport only.
- Owning TypeScript `--noEmit` check passes. No local product server,
browser, model, database, SDK build or evaluation was run.
- Prior-head CI run 40906120388 failed one E2E test because the real
announcement footer intercepted its Add to composer click. The other 28
tests in that shard passed. The narrow fixture uses the existing UI
dismissal pattern. The added handler passes an isolated noEmit check
against the real Playwright Page type. An additional strict check of the
whole browser test fails on five unchanged shared-fixture type errors;
checking that unchanged shared file alone gives identical diagnostics.
The initial shell exit was misreported and corrected in the validation
record. Browser verification is deferred to the next normal CI run; no
local browser or server was started.
- Repository-wide local build and test commands were not run because
this is a scoped source change. Normal required PR checks will provide
the repository CI result.

## Risks

A registry entry is not proof that a target or feature is ready. A
future target must use the exact matching private helper and producer
contract, retain any stronger target scanners, and produce fresh source
fingerprints. Existing running jobs keep their pinned workflow and
target sources. All original attempt limits, declared inputs, private
storage checks, fatal scanners and exact administrator-controlled run
approval remain in force.

The new cell report contract accepts only canonical assets from the
actual pinned Playwright installation. Other assets and layouts still
fail closed. No private evidence or generated report is included in this
PR.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 11:42:35 -05:00
DottaandPaperclip cc6a3296e5 fix: keep agent YAML compact and preserve omitted settings (#18168)
## Thinking Path

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

## Linked Issues or Issue Description

Refs #2219. Follow-up to #18036.

**Current behavior**

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

**Proposed behavior**

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

**Reason and benefit**

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

## What Changed

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

## Verification

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

Run the focused browser suite with:

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 11:17:17 -05:00
07c6df260b fix(server): schedule archived runner evidence from saved deadlines (#17925)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/85/changes/paperclip/85
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Retired native sessions leave continuity and quarantine evidence on
disk.
> - The old hourly loop mixes evidence retention with backup expiry,
which has different database eligibility rules.
> - Evidence already has saved creation timestamps and local publication
signals.
> - This pull request gives evidence its own registered worker and
actual next deadline.
> - The worker stops filesystem and SQL activity when its evidence
obligations settle.

## Linked Issues or Issue Description

Stack slice 65. Parent: #17923
(`codex/sleep-64-skill-version-retention`). Related foundation: #15625.

**What happened?**

At parent `7b94aa185c29673372646bbf2e07a2fbd16bc394`, an hourly
backup/evidence tick still inspects native state roots. Evidence's
private due time is checked by that recurring tick instead of the shared
scheduler. Empty evidence and future retention windows have no reason to
be rediscovered every hour.

**Expected behavior**

Reconstruct evidence once. Wake from the existing publication signal.
Register the earliest saved retention deadline. Keep busy, failed, or
incomplete evidence recoverable. Preserve backup eligibility as a
separate duty.

**Steps to reproduce**

Start retention with an empty evidence root or archives inside the
seven-day window. The old timer still visits the combined owner. The new
evidence worker disarms when empty, or registers the saved expiry with
no evidence filesystem or SQL calls between relevant changes and that
deadline.

## What Changed

- Add an evidence worker through the delivery coordinator and shared
scheduler. Track startup reconstruction without delaying HTTP readiness.
Unsubscribe local publication before delivery shutdown.
- Select `backups` for the existing backup timer and `evidence` for the
new worker. Existing callers that omit the selection retain combined
behavior. Backup expiration remains the next separate migration.
- Use hourly retries for concrete busy or failed evidence, with earlier
saved expiries and one-second continuations independent. Restore
candidate/removal/byte summaries. Schedule publication at the first
removable instant; preserve legacy manual-tick semantics.
- Expose the existing earliest evidence deadline. Preserve one-second
bounded continuation, concrete failure/busy retries, cleanup-source
archive exclusions, symlink protection, late activity checks, atomic
rename, and interrupted removal recovery.
- Preserve non-ENOENT inspection errors as recovery obligations. Retry a
failed session root in a new evidence pass instead of continuing past it
and forgetting it.
- Register the first removable instant after the inclusive retention
boundary. Keep the existing manual dry-run publication semantics.
- Add real filesystem/isolated PostgreSQL lifecycle tests and
disabled/held-startup wiring cases. Add no table or migration.

The archive and quarantine writers already call
`noteNativeRunnerEvidence`; this PR connects that existing signal to the
scheduler. Shared code owns scheduling, while evidence rules stay with
the retention service. See
[`doc/plans/2026-10-27-runner-evidence-retention-sleep-audit.md`](doc/plans/2026-10-27-runner-evidence-retention-sleep-audit.md).

## Verification

- Adopted actual prerequisite squash
`b06ea111a254c62e0a55199b010d82e0adb33bf0` from #17923 through normal
merges. Qualified runtime/package/UI/map trees remain unchanged. The
final nine-path diff includes one browser-spec readiness repair.
- Runtime qualification remains **652 passing TypeScript cases across 22
complete files**, plus **29 passing Rust cases** in native-backend,
runtime-notification and configured-environment targets. One actual
closed Pi snapshot launch is intentionally skipped because its external
distribution root is not provided. Accepted source is
`b80eee32f344ae0218d8b791c14f2ea174da09cc`; all runtime and earlier
sleep-test bytes are preserved.
- The complete outage-recovery browser file passes **all five journeys**
on a fresh isolated database after four additive rendered-history
readiness assertions. Every original assertion, outage control and
timeout remains byte-identical when those new lines are removed. The
intentionally unresolved first-session scenario keeps its pre-auth
interaction and delayed-owner coverage. The prior CI/local timeout
evidence and one rejected broader precondition remain in the audit.
- Adapter/Runner/database builds, server/Runner typechecking, Rust
formatting/workspace checks, server build, module boundaries, migration
order and generated TypeScript/Rust profiles pass. PostgreSQL 17
fixtures apply all 413 journal entries through index 414; source hashes
and temporary fixture imports restore exactly.
- **Inherited validation exception:** Copilot profile 81's separate
source-identity check fails on the merged Rust configured-environment
hash. Its inputs and attestations equal upstream and stay unchanged
here. Grok's identity check passes. No release attestation is
regenerated or new live-provider qualification claimed. Required
exact-head CI/security and Greptile 5/5 still must pass.
- [The evidence
audit](doc/plans/2026-10-27-runner-evidence-retention-sleep-audit.md)
retains historical failures, counts and limitations. No full local
repository-suite, live provider, external-alarm, measured suspension or
fleet-savings claim. Fresh final-head CI/security, exact-head Greptile
5/5 and actionable Ponytail findings remain separate merge gates.

## Risks

- Live publication is the existing server-owned executor in one process.
Independent filesystem writers need an explicit signal contract. Startup
reconstructs restart state.
- Busy sessions and concrete inspection/removal failures retain retries.
Unknown cleanup-source archives remain protected.
- The existing scan enumerates directory names before applying its
entry/removal budget. This PR preserves that behavior and does not claim
a bounded total directory-listing allocation.
- An in-process deadline cannot wake stopped compute. Cloud sleep-safety
and external-alarm coverage stay unchanged. Physical evidence
reclamation can wait for a supported host wake.
- Backup expiration still has an hourly database eligibility scan. This
slice removes only the archived-evidence duty from that loop and does
not claim full instance suspension.

## Model Used

OpenAI Codex (GPT-6-based coding agent), using repository inspection,
normal Git merges, composition proofs and complete
PostgreSQL/filesystem/startup suites. No subagents were used in this
reconciliation.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 11:12:16 -05:00
Devin FoleyandPaperclip fd98075a22 fix(ui): show environment variables on agent Secrets pages (#18121)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

Reproduced on master `27270e9bf8b7a294cf03f8b84f4857f1b1ff05c7` before
the fix.

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 08:32:30 -07:00