Commit Graph
475 Commits
Author SHA1 Message Date
DottaandPaperclip e5e22148e4 test(evals): pin the reviewed chat catalog fixture repairs (#18710)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The chat catalog uses a trusted TestOps workflow and an immutable
candidate source.
> - The retained first pass found fixture failures before real feature
work could start.
> - Candidate repairs must use the same source checks as the original
lane.
> - This pull request advances only the fixed catalog target and its
source note.
> - New AWS measurements keep the original case queries, limits, graders
and reporting path.

## Linked Issues or Issue Description

Refs: #18542, #18647, #18680, #18693.

**What happened?**

The full-catalog lane remains pinned to the original candidate. A repair
candidate cannot run through the trusted TestOps selection without a
reviewed pin change.

**Expected behavior**

TestOps must select the reviewed immutable repair source. It must keep
the existing case identities, model, clocks, private evidence controls
and original grading.

**Steps to reproduce**

Inspect the full-catalog target in the manifest. The trusted contract
uses that exact commit for selection, source checks, build and export.

## What Changed

- Advance the immutable full-catalog target to
[`9ab0f951a5b5990c266ef4456610e0a0775aa334`](https://github.com/paperclipai/paperclip/commit/9ab0f951a5b5990c266ef4456610e0a0775aa334).
[Candidate-only
delta](https://github.com/paperclipai/paperclip/compare/3b66c3c144360ddf32714a0742fd774b8ceafb16...9ab0f951a5b5990c266ef4456610e0a0775aa334).
- Preserve all original queries and limits. Record company observer
source ownership and the secret-entry v2 oracle as explicit metadata
overrides against the original definition source.
- Explain SDK staging, scoped human membership, original-clock
observation and exact controller-secret baseline conditions. Preserve
the original failed measurements.
- Leave the application and held core fixes off master. This change does
not copy the candidate app or catalog implementation to master.

## Verification

- Candidate integration: 167 focused pure tests passed for SDK custody,
membership, feature and privacy controls.
- Trusted target consumers: 46 manifest, full-catalog adapter and
dispatch contract tests passed.
- The candidate has no diff to the original YAML queries or descriptor
bytes.
- `git diff --check` passed.
- Local full typecheck, application build, DB and model execution were
not run for this two-file pin change. Worker typecheck attempts hit
existing missing workspace dependencies and are not recorded as passes.
The trusted AWS source check and build must pass before any native
query. It imports the real candidate catalog and checks every descriptor
before provider access. It does not typecheck all harness TypeScript
files.
- Initial CI41563164012 passed48 jobs with1 skip. A later review
requested the exact target assertion; the valid-SHA mutant is now
rejected. Corrected-head CI41564795118 passed48 jobs with1 skip
on2226f093. Both required checks passed. Greptile and the follow-up
source review are5/5 with no unresolved threads. No new candidate case
result is claimed here.

## Risks

A new fixture condition can change a measured outcome. Each result
records the actual candidate and trusted workflow revision. Original
failed measurements remain unchanged. The model, case bounds,
independent feature requirements, private custody, reporting identities
and automatic retry count remain fixed. This pin applies to future
full-catalog runs, so operators must not infer that every catalog case
has been qualified. The inherited source-ref label is not source
authority; the exact checked commit is authoritative.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) with reasoning, source editing and
tool use. The exact context window is not exposed by this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 20:28:06 -06:00
DottaandPaperclip ca3f99449e fix(testops): report retained catalog results with explicit gaps (#18693)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Product E2E reports preserve the original evaluation and its
evidence.
> - The catalog report joins one safe projection for each selected case.
> - One unavailable projection currently blocks every retained sibling
result.
> - A reporting gap must not become a fabricated evaluation result.
> - This PR adds an explicit offline retained-reporting mode to the
existing aggregate owner.
> - It preserves authentic grades and reports unavailable originals as
separate operational gaps.

## Linked Issues or Issue Description

**What happened?**

A completed 196-case catalog run produced 153 safe projections. The
strict aggregate rejected the incomplete set, so no outcomes reached
TestOps. One additional retained original can be recovered through the
unchanged strict reader. The expected retained archive keys for the
remaining 42 are absent.

**Expected behavior**

Publish authentic retained outcomes. Mark unavailable original evidence
as a reporting gap with an UNKNOWN original grade. Keep exact
selected-case coverage and all original evidence checks.

**Steps to reproduce**

1. Prepare two valid singleton projections for a three-case selection.
2. Supply a terminal, source-bound custody disposition for the third
case.
3. Observe that the existing aggregate rejects the incomplete projection
set.

Refs: #18647, #18676, #18680. This PR changes evaluation infrastructure
only. It does not merge product fixes or change the candidate
application.

## What Changed

- Add an explicit `retained-reporting` mode to the existing catalog
aggregate CLI.
- Validate each authentic singleton with the unchanged strict reader,
merger and Allure exporter.
- Require an exact, disjoint partition of authentic originals and
explicitly recorded missing retained archives.
- Emit separate BROKEN reporting-gap records. Their original status,
native-run count, checks and cleanup are null. They contain no
fabricated execution time or test steps.
- Freeze one Allure payload and a file-hash manifest. Keep recovery
executor identity separate from original measurement identity.
- Document the operator data-preparation and once-only publication
procedure.

## Verification

- Meaningful parent RED: the existing aggregate rejects the valid
partial original set with `Incomplete projection set`.
- Pure Vitest: 30 tests pass, including four new recovery controls and
26 unchanged strict exporter controls.
- Existing API and streaming Node controls pass alongside the new
partition controls.
- Negative controls reject foreign origin, duplicate or unexplained
membership, active upstream jobs, corrupt authentic data, foreign
archive keys, injected private text and a supplied gap PASS.
- Actual retained data validates as 154 authentic originals: 29 passed
and 125 failed. Seven failed originals also have failed cleanup. There
are 42 separate UNKNOWN reporting gaps. This is not a new model run or
regrade.
- `git diff --check` passes.
- Local runner noEmit encountered stale workspace package output/type
errors. No changed-file type errors remain. The current-head AWS/GHA
typecheck, build and test gates pass. Full app/database/provider setup
was not run locally under the user's execution constraint.
- CI run 41547666905 is successful at head
b20ee216f1: 48 successful jobs and 1
allowed skip. One unchanged server fixture failed before its test body
with PostgreSQL23505 on its short company prefix. One failed-only
recovery passed. All 46 prior successful executions were carried forward
with identical execution/step timestamps. The original failure is
retained; its conflicting row identity was not captured. No server code
or timeout changed.
- Greptile is 5/5 on the exact current head. All known review threads
are resolved. The nonrequired Paperclip Review check is queued; it is
not a required CI gate.

## Risks

The disposition is an operator data record, not an authentication
mechanism. The operator must authenticate the original selection,
terminal job state and exact-key custody observations before using it. A
missing retained archive does not establish that an evaluation passed or
failed. Upstream producer byte/privacy limits remain unchanged. The
command does not upload, dispatch agents, acquire credentials or grant
privileges. An ambiguous later upload must be reconciled with GET
requests, without another export or blind resend.

## Model Used

OpenAI GPT-6.1 (`gpt-6.1-sol`), with reasoning, repository tools and
code execution. The host does not expose a context-window value. No
model or provider evaluation was run for this change.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 19:26:11 -06:00
DottaandPaperclip 82c033ed12 test(e2e): cover uploaded input and personal inbox triage (#18643)
## Thinking Path

> - Paperclip lets people assign work to agents and manage their tasks.
> - Product E2E journeys verify the saved outcome through the browser
and normal APIs.
> - Uploaded input and personal inbox actions need repeatable coverage.
> - An agent answer must match the input file, and an inbox action must
retain its saved state.
> - This change adds two journeys with independent evidence checks.
> - A blocked fixture action must use the normal human-owned unblock
contract.
> - Registration stays separate from deployed qualification and daily
admission.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Product E2E coverage for file attachments, saved task documents, and
personal inbox read and archive actions.

**Current behavior**

The journey catalog lacks an uploaded-input calculation and a persisted
personal inbox triage path. A successful agent run alone cannot prove
either outcome.

**Proposed behavior**

Upload a generated CSV through the task composer. Require an exact saved
answer and unchanged input bytes. Read and archive one owned task
through the inbox, reload each state, and verify that a new Blocked
event brings it back without agent work.

## What Changed

- Add a file-input journey with a random reference held only in the
uploaded CSV.
- Check exact result values, document authorship, native run binding,
original input bytes, and persistence after reload.
- Add a browser inbox journey with an independently authenticated human
author, saved read and archive state, unchanged work status, and
activity resurfacing checks.
- Reject wrong, missing, duplicate, and foreign evidence in assertion
controls.
- Register both cases and document their scope and privacy rules.
- Supply a current-human unblock owner and action for the archived-task
fixture. Test that exact payload through the production route and retain
the bare-blocked422 negative control.
- Include the fixture constructor in the source definition hash and both
new cases in the exact catalog assertion.
- Reject collected inbox receipts with unexpected runs, providers,
models, or native/legacy execution modes.

## Verification

- The frozen source is `cdb6659fb4e4b67e9321bc3fd963cf11e9b8b2f3`. It
includes one fixed master integration at
`fd0d61b8e329efc89ff541dc2cac44e7c7a37f78`. The single map conflict
retains both coverage paragraphs.
- The production HTTP route rejects the original bare blocked payload
with422 and accepts the exact human-owned fixture payload with200.
Neither control wakes an agent. The full related route file passes
all200 tests.
- The frozen current head passes recursive workspace typecheck, runner
typecheck, full build, map checks, and diff checks. Its full related
journey/catalog suite passes723 tests, the production route suite
passes200, and the separate Node support suite passes347. The retained
contract file passes all38 tests. Fresh Greptile review is 5/5 on the
frozen current head. Current-head hosted CI passes after one authorized
failed-jobs-only recheck. The original Runner close test failed; the
unchanged, properly cargo-prepared focused local control passed in2.99s,
and the hosted recheck then passed. The cause remains unknown; no Runner
code, test timing, or assertion changed. The original hosted diagnostic
and the initial invalid local invocation without required fake binaries
remain recorded. The ordinary local full-test run is in progress.
- The unrestricted local runner support run on the fixed-master
integration is not green:5993 tests passed,12 failed,3 skipped. The
unchanged failures cover onboarding cleanup expectations, Pi metadata,
workflow-security expectations, and an expired test allowance. An
untouched743 baseline reproduces the same non-PG failures; their
source/test blobs also match pre-feature40b807. This change does not
extend an allowance or alter paid admission. The
original5983-pass/15-failure run remains recorded. Restoring the local
Postgres package's own library aliases resolved its two startup
failures. The feature-related catalog omission is corrected.
- The uploaded-file case passed its first complete deployed QA attempt:
one configured native run, all six independent checks, original
evidence, complete cleanup, and no active operations.
- The first inbox attempt stopped at the agent comment execution-context
guard. That guard stays intact. The fixture uses an approved,
independently authenticated QA human.
- The next original inbox attempt verified protected-secret retrieval,
human attribution, and session closure, then failed its unread
prerequisite. The product unread defect was repaired in #18670.
- The fresh deployed inbox attempt passed external-human activity, saved
read state, archive persistence, and unchanged task status after the
product rollout. It then stopped at the fixture's bare blocked PATCH
before any resurfacing assertion. The response status was discarded;422
is an explicit contract inference independently reproduced through the
production route. That failed attempt remains retained. A fresh full
inbox qualification on the current frozen head now passes all six checks
and all five phases; the normal human comment receipt, closed human
session, zero agent work, complete cleanup, and absence of active
operations are verified in the original evidence. Daily admission
remains a separate coordinator action.
- The retained-result review gap failed a negative receipt control
before the repair. All38 retained journey contract tests now pass. The
two old unread advisory threads are resolved only after the fresh full
deployed inbox pass.
- Original failures remain recorded, including the earlier unchanged
environment-runtime assertion and unchanged runner/occupied-port startup
failures. Closed operation codes and failure screenshots retain the
failing step without raw browser errors. Actual retry qualification
remains separate from source tests.

## Risks

The target must supply the declared external-human fixture. Inbox
control selectors may differ across deployed UI revisions. File
processing depends on the configured native agent. Exact saved-state and
source checks must remain required when those dependencies fail. The
change adds test journeys and does not change production behavior or
schemas.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and browser
tools. The runtime does not expose a more specific model identifier 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 (relevant suites; broader
baseline failures 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-11-02 18:12:16 -06:00
DottaandPaperclip 4814d1ab69 fix(ui): show composer images as rounded thumbnails (#18689)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People use the new-task and thread composers to send text and files.
> - Images currently enter the text editor or appear with other files.
> - Large images interrupt text entry and make the two composers
inconsistent.
> - This pull request puts image previews above the text in both
composers.
> - People can check and remove images while they continue to edit the
text.

## Linked Issues or Issue Description

Refs: #13206. Related shared-composer work: #15091.

**What existing behavior does this improve?**

Image selection, paste, and drop in the new-task and thread composers.

**Current behavior**

Thread images enter the editor at the text cursor. New-task images can
appear inline or with file attachments. Images do not have one preview
size.

**Proposed behavior**

Show images above the text as 80 by 80 previews with rounded corners.
Use the existing spacing and radius tokens. Keep file attachments in
their current row. Add image references when the thread message is sent.

**Reason and benefit**

People can review images without moving or deleting message text. One
shared image row keeps both composers consistent.

**Breaking changes**

New image uploads stay outside the editor until send. Old inline-image
drafts remain readable. No server API or database changes are required.

## What Changed

- Add `ComposerImageAttachments` for local previews, removal, upload
status, and retry.
- Let `TaskChatComposer` own the image row and all image input paths.
Keep attachment IDs in the existing send flow.
- Let `NewIssueDialog` stage images and upload retained files after task
creation. Save file bytes in browser IndexedDB by account and company.
Restore them after reload. Clear them after creation. Show storage
errors. Merge saved file changes in one IndexedDB transaction. Delete
only the files removed by that draft. This keeps files saved by other
open tabs.
- Keep rich editing for old image Markdown. Use the same MIME and
filename checks for image previews in both composers.
- Save optional MIME data with thread draft attachments. Existing draft
records remain valid.
- Add desktop and mobile Storybook examples. Update the task feature map
and component tests.

## Verification

- `pnpm exec playwright test --config tests/e2e/playwright.config.ts
tests/e2e/board-attachment-receipts.spec.ts`: all 14 Chromium tests pass
against the real local Board, API, storage, and disposable database. The
suite proves image recovery in two open tabs after saves and task
creation, new-task image recovery after reload, byte-for-byte upload
content, cleanup after creation, rich editing of old image drafts,
upload receipt recovery, and removal during pending uploads.
- The first local browser attempt could not start because Chromium was
absent. Chromium was installed. A later run passed 12 tests but the new
legacy-draft fixture restored an empty body. That fixture wrote storage
while an empty composer was mounted. It now seeds before React startup
and uses a real uploaded image. The complete 13-test rerun passes. Early
component runs also exposed the new restore timing. Submit and file
controls now wait for restoration. The test helper now waits for React
effects.

- 316 focused tests pass across `TaskChatComposer`, `NewIssueDialog`,
`MarkdownEditor`, `composer-draft`, and `useStagedIssueFiles`. The tests
cover explicit file removal, file recovery, account and company changes,
storage failures, MIME-empty images, upload retries, and removal.
- The two-tab browser test failed on the previous commit: the second
save erased the first image. The fix merges files in one read/write
transaction and records explicit removals. The first fixed run reached
the final create step but had no text request after the other tab
cleared the shared text draft. The test now enters a fresh request
before that step. The full 14-test rerun passes.
- `pnpm check:token-gates`, `node scripts/check-maps.mjs`, `node
scripts/storybook-catalog.mjs`, and `git diff --check` pass.
- `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter
@paperclipai/ui build` pass after building the local plugin SDK
dependency. Repository typecheck and build stop because this workspace
has no `cargo`. Full CI must pass before merge. The first CI run passed
typecheck, build, and all unit-test shards. Its browser failure expected
the old inline upload label. The assertion now uses the thumbnail upload
status.
- The prior browser review used the production components with simulated
upload and submit calls. Desktop, mobile, and dark-theme captures were
accepted before this PR. Browser checks confirmed equal-size rounded
previews above the editor, no inline image nodes, no horizontal
overflow, and removal that preserves text. These checks do not prove
live backend persistence.
- Earlier repository typecheck and build attempts also stopped without
`cargo`. An earlier full test run was killed with a recorded
out-of-memory event during a server integration shard. It had no
full-suite verdict. One document-recovery test timed out during that
concurrent run. Its isolated rerun and later complete focused runs
passed; the initial timeout cause was not established.
- An initial catalog command in this workspace ran before dependency
installation finished. It could not load Storybook. The command passed
after installation. The first UI typecheck could not find plugin SDK
declarations while that package was still building. The UI typecheck
passed after `pnpm --filter @paperclipai/plugin-sdk build`.

To inspect the layout, open `composer-new-task--images`,
`composer-new-task--mobile-images`, `composer-add-menu--images`, and
`composer-add-menu--mobile-images` in Storybook. Select images with
different aspect ratios. Check removal, mixed files, failed upload and
retry, and draft restoration.

- Greptile reports 5/5 for commit
`9b9e93beeed80371f667ad2e1a9573e82332c05c`. There are no open review
threads.
[CI](https://github.com/paperclipai/paperclip/actions/runs/41544180330)
passed on this commit. All 58 checks finished: 54 passed, one review is
neutral, and three optional checks were skipped. The legacy Snyk status
passed. Paperclip also reports 5/5. No review threads are open.

## Risks

- Open tabs share the account and company draft. Atomic file writes keep
changes from other tabs. A reload can restore those saved files.

- Attachment state now controls when image references enter a thread
message. Tests cover pending uploads, failures, retry, removed images,
and retained upload IDs.
- New-task images use the existing staged-file upload flow after task
creation. A failed upload follows that flow's existing error behavior.
Browser storage can be unavailable or full. The composer keeps the files
in memory and shows a recovery message.
- Legacy inline-image drafts retain their original text. No migration is
required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and shell
execution. The exact runtime snapshot ID and context-window size are not
exposed in this session. The earlier implementation's model snapshot is
not recorded in the handoff.

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 23:35:32 +00:00
DottaandPaperclip 3f8ebfff8a fix(evals): pass named environment secrets to case workflows (#18680)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect their work.
> - The chat catalog sends each original Product E2E result to TestOps.
> - Each case uses a reusable workflow with separate protected job
environments.
> - The caller passed literal empty strings for three secret names.
> - A live worker received an empty model key although its environment
had that secret.
> - GitHub requires matching named secret references at the caller
boundary.
> - This PR uses those references and keeps the closed credential
boundaries.

## Linked Issues or Issue Description

Refs #18647, #18666, #18676.

**What happened?**

The first two workers in a live streaming check failed before a
qualified native case. Their model-key environment values were empty.
Name-only metadata confirmed that the key exists in the intended
protected environment. Both closed diagnostics recorded zero runs, zero
checks and no original result carrier. The remaining case was cancelled
before its original execution. These records are setup failures, not
feature or model grades.

**Expected behavior**

Each caller passes only the three declared secret names through matching
expressions. Each called job uses its own protected environment and only
its existing credential consumers. GitHub documents this requirement
even when the secret exists only in that environment: [Reuse
workflows](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows).

**Steps to reproduce**

Run the new `paidWorker` consumer control against the parent helper. It
rejects the supported named-reference caller. The deployed literal-empty
caller also has the retained live empty-key witness.

## What Changed

- Replace six literal empty values in the two case callers with exact
matching secret references.
- Keep the host-contract resolver closed to those three names and
expressions.
- Reject blank, extra, mismatched and inherited credentials in focused
consumer and workflow controls. Keep the existing lane and authorization
controls.
- Keep the called workflow, protected environments and
credential-consuming steps unchanged. No secret was read, copied,
rotated or added during this repair.

## Verification

- Parent consumer control: RED with `Workflow caller boundary mismatch`
for the named-reference contract.
- `node --test
tests/runner-e2e/chat-completion-testops-contract.test.mjs
tests/runner-e2e/chat-catalog-testops-streaming.test.mjs`: 36 controls
pass.
- Review found an existing streaming-test mutation that became a no-op
after the caller contract changed. Its actual `Missing expected
exception` failure is retained. The mutation now uses a blank value, and
its description names the current contract. All production posts are
unchanged by this test correction.
- The focused `Runner eval workflows pin actions and gate paid live
execution` security control passes.
- Four JavaScript syntax checks, actionlint for caller and callee, and
`git diff --check` pass.
- An independent source peer checked the four original frozen posts and
unchanged callee. The two-line dependent-test correction has a separate
peer review.
- Local checks use synthetic values, source files and mocked boundaries.
No local app, database, native build or provider ran.
- Corrected-head GitHub CI passes with 48 successful jobs and one
skipped. Both required aggregates, typecheck, build and browser checks
pass. This head needed no CI recovery.
- Live nonempty resolution and incremental TestOps publication still
need qualification after delivery.

## Risks

- The previous assumption that literal empty placeholders would resolve
environment secrets was wrong in the observed run. This change follows
the current primary contract. Local controls do not prove GitHub runtime
resolution.
- The three names stay explicit. There is no `secrets: inherit`, new
secret, environment change or permission expansion. The model worker,
private reader and TestOps uploader keep their existing separate
consumers.
- The immutable evaluation source, cases, original grades, run limits,
deadlines and zero-retry policy do not change. Earlier setup failures
remain recorded. The existing large batch is not changed or replayed.
- Streaming publication and final backend coverage remain unqualified
until a real small run proves them.

## Model Used

OpenAI `gpt-6.1-sol`, with tool use and code execution. The session does
not expose a context-window size. The independent source peer uses the
same model family.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 16:25:55 -06:00
DottaandPaperclip 5d40e75253 fix(evals): distinguish scheduled TestOps results from uploads (#18676)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect their work.
> - The chat catalog reports each original Product E2E case to TestOps.
> - TestOps creates scheduled result rows before a case runs.
> - Those rows have identity fields but no status property.
> - The publisher currently mistakes any case row for an uploaded
outcome.
> - This PR distinguishes scheduled membership from an outcome after
strict identity checks.
> - Each case can upload once and wait for processing without changing
its grade.

## Linked Issues or Issue Description

Refs #18647, #18666.

**What happened?**

A real TestOps launch had all three scheduled result rows before any
model case started. Each row had the expected case, project, launch and
job-run identity. Its status property was absent. The publisher treated
the row as already uploaded, skipped its only POST and then rejected
readback.

**Expected behavior**

A fully bound scheduled row permits the first immutable case upload. It
does not count as an outcome. Readback waits within the existing bound
until the original status and exact attachments are ready.

**Steps to reproduce**

Run the new scheduled-row control against the parent API. It rejects
before sending the initial result. Fixing only that initial check still
rejects the first scheduled readback after one POST.

## What Changed

- Share the strict result-detail identity check between initial
inspection and readback.
- Recognize an absent status property as scheduled only after that
check. Present valid statuses, including unknown, stay readback-only.
Malformed statuses and foreign identities fail closed.
- Keep scheduled full-catalog readback unready within the same poll and
deadline bounds. Keep the final status, evidence and attachment checks
unchanged.
- Calibrate three planned rows, delayed and permanent processing,
unknown outcomes, wrong job/source and explicit-null status. Retain the
once-only upload and uncertain-response controls. Use the registered
legacy full-name alias in the fixtures.

## Verification

- The real-shape parent control fails with `result_mismatch` after the
first upload is suppressed.
- A controlled initial-only fix sends one POST and still fails on
scheduled readback. The final two-seam fix passes.
- All 77 focused controls pass: `node --test
tests/runner-e2e/chat-catalog-testops-streaming.test.mjs
tests/runner-e2e/chat-completion-testops-api.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs`.
- Both changed files pass Node syntax checks. `git diff --check` passes.
- All local controls use synthetic data and mocked HTTP. No local app,
database, native build or provider runs.
- The affected live run was cancelled during build after metadata proved
no original case had started. Its build instance is terminated. No
original grade was changed or inferred.
- Latest-head GitHub CI is green: 48 successful jobs and one skipped.
Typecheck, build, browser and required aggregate checks passed.
- The first CI attempt failed a heartbeat scheduling test’s five-second
idle wait after its 51-admission assertion passed. Its six direct owners
were byte-identical to the prior passing CI. One same-head failed-job
recovery passed the server shard and required aggregate; all 46 earlier
successful jobs were carried unchanged. The original failure is
preserved, and its underlying cause remains unresolved. No heartbeat
source, fixture or timeout was changed.
- Live streaming qualification remains pending. No user command or
documentation contract changes.

## Risks

- The observed JSON distinction is status-property absence, not a
result-stage or UUID field. Those fields are not used.
- A scheduled row must match the current project, launch, case,
registered full name, job run and GitHub source URL. It never qualifies
as passed or complete.
- The same 12-poll and time limits remain. A permanent scheduled state
fails. A present outcome never causes another POST. An uncertain write
still uses GET-only reconciliation.
- Backend handling of uploaded scheduled rows still needs live
qualification. Duplicate, foreign and final-coverage guards remain; this
PR does not assume server deduplication.
- Earlier dispatch and cancelled setup records remain separate. The
first integration HTTP 500 cause is still unknown. No in-flight legacy
workflow is changed or rerun.

## Model Used

OpenAI `gpt-6.1-sol`, with tool use and code execution. The session does
not expose a context-window size. The independent source peer uses the
same model family.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 15:43:33 -06:00
DottaandPaperclip 410b0e2701 fix(evals): accept refreshed catalog workflow URL (#18666)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect their work.
> - The chat catalog reports original Product E2E grades to TestOps.
> - TestOps can refresh its job metadata from GitHub.
> - That operation returns a canonical master workflow-file URL.
> - The catalog guard currently rejects that exact URL before case
selection completes.
> - This PR accepts that fixed URL and keeps the existing source and
identity checks.
> - The catalog can use the refreshed job without changing its cases or
grades.

## Linked Issues or Issue Description

Refs #18542, #18647.

**What happened?**

A supported TestOps job refresh changed the catalog job URL to the
GitHub `blob/master/.github/workflows/chat-catalog-testops.yml` form.
The selection guard rejects it as `job_mismatch`.

**Expected behavior**

The guard accepts that exact parent workflow URL. It still rejects
another owner, branch or workflow.

**Steps to reproduce**

Run the new adapter regression against the parent commit. It fails in
`validatePilotSelection` before the job-run request.

## What Changed

- Add one exact canonical master URL to the full-catalog workflow URL
guard.
- Add a regression through the real selection validator with refreshed
job metadata. Keep negative checks for another owner, branch and the
called case workflow.

## Verification

- The new selection regression fails on the parent with `job_mismatch`
and passes with this change.
- All 73 focused controls pass: `node --test
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-completion-testops-api.test.mjs
tests/runner-e2e/chat-catalog-testops-streaming.test.mjs`.
- Both changed files pass Node syntax checks. `git diff --check` passes.
- These controls use synthetic metadata and mocked HTTP. No local app,
database, native build or provider runs.
- Removing the one added predicate restores the parent API file exactly.
The branch, job, case, source, evidence and grade checks remain
unchanged. The pilot URL policy also stays unchanged.
- Current-head GitHub CI passes: 48 jobs pass and one is skipped,
including the required typecheck, test, build and final summaries. Live
streaming qualification remains pending. No documentation change is
needed for this internal URL compatibility fix.

## Risks

- The alias accepts only this repository, master branch and parent
workflow in the full-catalog lane. It grants no alternate source or
execution authority.
- An earlier TestOps dispatch failed with an integration HTTP 500 before
GitHub created a run. Its cause remains unknown. This patch addresses
the separate, reproduced metadata compatibility failure; it does not
claim to cause or cure that HTTP 500.
- Existing in-flight workflows keep their original source. This PR does
not patch, rerun or upload into them.

## Model Used

OpenAI `gpt-6.1-sol`, with tool use and code execution. The session does
not expose a context-window size. The independent source peer uses the
same model family.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 14:53:30 -06:00
DottaandPaperclip 53f480d1b3 fix(native): preserve warm continuity and deferred review replies (#18631)
## Thinking Path

> - Paperclip manages AI agents and their saved work.
> - Product E2E tests must check saved personal files across separate
turns.
> - The server records file collection in the durable `instruction_save`
run-log event.
> - The warm test read optional terminal result metadata instead and
rejected a recorded successful save.
> - This pull request reads the complete event stream for the current
run and uses its latest save receipt.
> - The prompt now specifies the exact nine bytes required by the
temporary-file transfer count.
> - Human review actions select the actual interaction card, which can
share its interaction ID with a navigation button.
> - A later real three-turn run exposed a missing reply after workspace
finalization moved to its durable recovery owner.
> - Reply recovery handled completed tasks but omitted ordinary tasks
that awaited review.
> - This pull request also publishes their recorded final reply once
while preserving the pending review.

## Linked Issues or Issue Description

**What happened?**

The [retained live continuity
attempt](https://github.com/paperclipai/paperclip/actions/runs/41477302876/job/125420001074)
saved the correct memory file and unchanged 8 MiB binary. Its durable
run log contained a successful `instruction_save` receipt. The oracle
read `resultJson.instructionSave`, which was absent, and failed before
turn two. The temporary file also had a trailing LF. Its prompt allowed
that result, while the byte-count check required nine bytes.

**Expected behavior**

The oracle must use the documented authoritative save event. A missing
receipt, a later failed save, incorrect transfer counts, or another
run's events must fail. The prompt must specify the bytes that its
independent check requires.

**Steps to reproduce**

1. Run `daytona-warm-continuity.runner-codex.daytona.warm-three-turn`
with the configured protected credentials and immutable image.
2. Complete a native turn whose terminal result has no `instructionSave`
field.
3. Compare the oracle output with the same run's successful
`instruction_save` event.

A subsequent [three-turn
attempt](https://github.com/paperclipai/paperclip/actions/runs/41495337334/job/125451304553)
passed every personal-file assertion and reused the same warm process.
Its first final reply was recorded as a completed agent-message event
but was absent from comments. The log shows
`native_workspace_finalization_busy`; the durable recovery path excluded
`needs_review` replies. The final message matcher correctly failed. This
failure remains recorded.

The observed application revision was
`aab87ce70744660a4a21c77278b0ede267c04720`. Related work: #14695 and
#18494. The retained failed result keeps its original grade and
definition.

## What Changed

- Read all run-event pages through the existing bounded collector.
- Require events to belong to the requested run and select the latest
`instruction_save` event.
- Retain strict byte counts and reject missing, failed, pending or
superseded receipts.
- Specify nine ASCII bytes and no trailing newline for the temporary
file.
- Scope human review actions to the interaction card and its exact
interaction ID.
- Advance the warm suite definition to version 5 and document its
evidence source.
- Recover recorded final replies for ordinary native tasks with an
accepted `needs_review` result and terminal state.
- Preserve pending reviews, existing reply selection,
company/turn/digest checks and external governed-response authorization.
- Update the task feature and agent access maps.

## Verification

- Real PostgreSQL regression: deferred review reply discovery failed
before the production repair (expected one candidate; found zero). The
final-message event and pending review were present.
- Recovery cases cover one publication, no repeated provider run,
unchanged review, and rejection of absent/wrong-turn final messages, bad
digest and suppressed comments.

- Red: seven new boundary regressions failed against the old receipt
lookup.
- Green: 169 focused oracle, event pagination and catalog checks passed.
Product E2E typecheck passed after rebuilding local package
declarations.
- Retained-evidence replay confirms that the new lookup finds the real
successful save event. The original attempt remains failed because its
temporary file included an LF.
- Recursive typecheck passed before the final recovery change; server
typecheck passed afterward. The recovery and control-plane suites passed
all 112 tests. Full build and map checks passed.
- The broad local test run reached one unrelated 30-second timeout in
`attention-retention-work.test.ts` (maintained-review/confirmation
batching). The same unchanged case then passed on one targeted retry
(39.9 seconds including module load). The original failure remains
retained. The broad run also reported one unchanged workspace-conflict
case, which passed on its targeted retry (14.85 seconds including module
load). Both original failures remain retained. The redundant broad local
run was stopped after current-head CI completed all required gates: 55
successful checks and 3 selection skips. No all-green local broad-run
claim is made.
- The separate artifact-transfer cell already passed on the recorded
application revision: independent source and delivered bytes matched at
407,485 bytes, with a completed task, succeeded native run and cleared
execution locks. This does not establish a three-turn continuity pass.

- [Real native three-turn
acceptance](https://github.com/paperclipai/paperclip/actions/runs/41499102994/job/125465795210)
**passed** at `3b207a42943e9eeb371d4f2d5623de72093eb6d5`, suite
definition 5. Turn one exercised `committed_task_response_recovered`.
All three completed final replies were persisted once and in order. All
three strict personal-file receipts passed. The unchanged 8 MiB binary
survived; later transfers copied only 36 and 54 bytes. The lease was
created, resumed, and resumed with the same runner PID/start time,
runner instance, native session and provider session. Final task was
`done`, all three runs succeeded, and checkout/execution locks were
null.
- The aggregate startup summary has no separate provider-process PID
proof. The raw run records independently prove the stable runner process
and provider session stated above. This single native cell does not
qualify the legacy cell or a full provider matrix.
- The passing campaign reused the signed immutable runner image. It
required no disk expansion. Earlier campaign image builds used the
recorded temporary 120 GiB mitigation; default 60 GiB build capacity
remains unqualified. All scoped completed probes were removed and
independently returned 404; org CPU/disk usage returned to zero. This
does not resolve unknown historical resources under a different
credential identity.
- Current-head Greptile is 5/5; review-thread pagination is complete
with zero threads. All 55 current-head checks are successful; 3
selection checks are skipped. The paid campaign, result enforcement and
report publication all completed successfully.

## Risks

- Publishing a reply must not approve the work. Recovery only copies the
accepted turn’s completed final message. It preserves the pending review
and does not start an executor.
- Conversation and external governed-response paths retain their
existing separate authorization.

The latest save event can record failure after an earlier success. The
oracle rejects that case. Event pagination, missing receipts and
cross-run evidence also fail closed. The exact temporary-file byte count
remains required. The review selector still requires the intended
interaction ID and enabled action on its actual card. The production
change is limited to ordinary internal-task reply recovery. It still
requires an accepted result, a matching successful terminal disposition,
the completed final message, and existing publication authority.

## Model Used

OpenAI Codex, based on GPT-6, with shell and code tools. The exact
deployment variant and context-window size are not exposed in this
session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 14:19:48 -06:00
DottaandPaperclip 0fd82e386e feat(evals): stream completed chat catalog results to TestOps (#18647)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect their work.
> - The chat catalog uses real Product E2E cases and reports their
original grades to TestOps.
> - The current report matrix waits for every selected worker.
> - A large selection can hide completed results for hours.
> - Each case can use the existing private reader and safe exporter
after its own worker ends.
> - This PR gives each case a separate upload and readback job, then
verifies final coverage without another upload.
> - People can inspect completed cases while the rest of the selection
runs.

## Linked Issues or Issue Description

Refs #18542, #18625.

**What existing behavior does this improve?**

The existing chat catalog reports results to TestOps only after all
selected workers finish.

**Current behavior**

One slow case holds back the report and upload jobs for all other cases.

**Proposed behavior**

Each finished case gets its own protected reader, safe projection,
upload and backend verification. The final job checks the whole
selection through read-only requests. It does not upload results again.

**Reason and benefit**

A person can inspect a completed grade and its safe evidence receipts
while other cases run. This changes future runs. It does not change an
in-flight run.

## What Changed

- Add one same-commit reusable workflow with separate worker,
private-reader and TestOps-upload jobs. Each job uses only its own
protected environment. Callers pass empty named secret placeholders and
do not inherit secrets.
- Reuse the original exporter and grade checks. Freeze each case's three
Allure JSON files once. Allow known sibling results during per-case
readback. Keep final exact selection coverage.
- Submit each bundle at most once. Reconcile uncertain responses by
readback. Retain only closed publication, failure and upload-intent
receipts. A rerun attempt still fails the existing attempt-one admission
guard.
- Preserve failed original grades, failed cleanup and missing evidence.
No missing original can become a passing result.
- Keep external-input cases in the serial lane. Small native-only
selections allow two cases at once. Small mixed selections allow one
native and one external case. Larger selections retain eight native
cases and one external case.
- Add source, privacy and failure controls to the existing unit roster.
Document the reporting flow and runner-group admission requirement.
- Fix an existing corruption-test fixture that could write the same byte
back to a random IV. Read and flip one bit instead. Keep the storage
rejection and unpublished-plaintext assertions unchanged.

## Verification

- 152 focused Node controls pass across the shared client, API,
selection, CLI and streaming tests. The retained parent controls show
the missing multipart and partial-readback behavior, plus the small
external-selection error before its fix.
- The focused workflow security control passes. Actionlint passes for
both workflows. Changed JavaScript files pass syntax checks. Git diff
checks pass.
- Local controls use synthetic data and mocked HTTP. They make no
provider call and do not start an app, database or native build.
- Previous head `b51406df` passed PR CI (48 jobs pass and one is
skipped). The review-driven test-only successor `0c65cc21` then failed
one unchanged snapshot-storage corruption test, plus the final CI
summary. The latest head includes its narrow fixture repair. Its first
CI attempt separately hit runner shutdown/lost-communication failures,
two setup/timeouts and a heartbeat-cancel cleanup HTTP 500/lock timeout;
those observations are retained without claiming their underlying cause.
One same-head failed-and-cancelled-only recovery now passes at
`bf9c3e8f`: 48 jobs pass and one is skipped, including required `ci /
verify` and `ci / e2e`. All 31 already-passing jobs retained their
original execution records; all 15 recovered leaves and both dependent
summaries passed. The first attempt remains recorded; the recovery does
not establish the underlying causes of those failures. A small AWS run
after delivery must prove that one case and both attachments are visible
before another original case ends. That live proof is pending; local
controls do not prove vendor ingestion or environment-secret resolution.
- Retained earlier fixture-calibration failures remain recorded. The
final integrated Node control run is green. A deterministic Node
crypto/filesystem control also reproduces the no-op corruption mutation
with a valid IV byte equal to `X`, then passes after flipping that byte.
This control uses no app or database. The failing CI byte was not
captured, so the exact historical byte remains unknown.

## Risks

- The called workflow needs its exact master ref in the existing
selected-workflow runner group. No IAM role change is needed.
- Environment-only secrets must resolve in the called jobs. The caller
passes no actual model or reporting key. The small live proof must
confirm this behavior.
- TestOps does not document an idempotency key for this upload route. An
uncertain write is never resent automatically. If readback cannot verify
it, the workflow fails with retained closed receipts.
- The existing job run can already be marked finished by the selection
watch. The live proof must record its actual stage and prove subsequent
uploads are accepted. This PR does not reopen, stop or close that job
run.
- Backend ingestion does not prove that an already-open TestOps page
refreshes automatically.
- The corruption-test repair changes no production storage or
cryptography. New-head AWS CI must qualify the existing database-backed
owner test.
- Each case adds short protected reader and upload jobs. The app source,
original case clocks, graders, model, budgets, raw-evidence privacy
boundary and zero eval retries stay unchanged. The versioned stream
concurrency group serializes new streaming runs; an old immutable batch
run can continue in its original group.

## Model Used

OpenAI `gpt-6.1-sol`, with tool use and code execution. The session does
not expose a context-window size. Independent source peers used the same
model family.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 14:18:00 -06:00
DottaandPaperclip 1f8f2e195f perf(ui): reuse parent metadata when loading the inbox (#18645)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The Mine inbox combines task rows with approval and failure items.
> - It waits for parent captions before it reveals the initial list.
> - It fetched rich diagnostics for every parent, including parents
already in the task index.
> - Parent captions only use fields that the index already provides.
> - This change reuses loaded parents and fetches missing parent
metadata through the index view.
> - Failure items keep their rich interruption data and the initial
reveal boundary stays in place.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The initial load of Mine and other inbox views that need parent task
captions.

**Subsystem affected**

`ui/` collection reads. The API contract and database schema stay the
same.

**Current behavior**

The inbox fetches all parent and failed-run task IDs with `view=rows`
after the primary task request. This adds active-run, blocker, review,
interruption and recovery work to the reveal path. The observed hosted
case fetched four parents. One was already in the 31-row task index. The
other three were completed parents. The serial context response took
1.0–2.9 seconds during the diagnostic reloads.

**Proposed behavior**

Reuse parents from the selected source index. Fetch missing parents with
`view=index`. Keep `view=rows` for every failed-run task, including
overlaps with parents or source rows. Keep both role-specific ID lists
in the query key. Drop old placeholder rows when the new index supplies
a parent.

**Reason and benefit**

This removes unnecessary diagnostic work from a required serial request.
Five alternating same-four-parent requests on the hosted app had index
times of 189, 162, 156, 128 and 169 ms, versus rich-row times of 282,
211, 329, 219 and 284 ms. All requests missed the response cache. All
consumed parent fields matched. This isolates the projection cost; it is
not a deployed UI speedup claim.

**Breaking changes**

None. Membership, ordering, nesting, archive state, authorization and
failure presentation retain their owners and contracts. Refs: #18323 and
#18492 for the prior collection and startup work. This change addresses
the remaining parent-context read.

## What Changed

- Partition missing parent metadata from failed-run context. Load the
two batches concurrently, with at most two batch requests in flight.
- Keep richer failure rows last in the context result. Filter
placeholders by company and current requested IDs. Track completed
failure reads, including missing tasks, so a parent placeholder cannot
reveal an unverified failure card. Keep existing verified cards mounted
through refresh.
- Cover delayed captions, reuse of indexed parents, refreshed parent
captions, failure overlaps, resolved failures and parent-to-failure
cache transitions.
- Add a real browser check for delayed parent metadata and stable
geometry through deferred diagnostics. Give the test its own disposable
company.
- Add a reusable local timing harness and update the collection
verification recipe.

## Verification

- Baseline source: `0710c5684243a663c09ff907011ab88838173a02`. Final
measured candidate: `c8c69b5af11966b4144707a3da21e840c73c6cca`.
Production UI assets were built from the same checkout and dependencies,
with only the Inbox module changed between variants.
- Targeted regression failed on the old implementation and passed after
the change. All 58 Inbox component tests pass, including existing
archive/undo and order checks.
- Full workspace typecheck passes. The final UI typecheck passes. Full
build passes. Token gates, map checks and diff whitespace checks pass.
- All 12 collection browser checks pass, including pagination and
reading-position restoration.
- The full CI workflow passes on
`c8c69b5af11966b4144707a3da21e840c73c6cca`, including all server, chat,
workspace, serialized, runner and E2E shards. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/41502803275).
Greptile reports 5/5 on this commit with no unresolved threads. The
separate Paperclip Review check is still queued. Its first attempt saved
a text result but did not complete the GitHub assessment. Normal retry
was rejected because that attempt already recorded a result. The
current-head review request is queued. The review service is now
unavailable, so this external gate remains open.
- The duplicate local `pnpm test:run` was interrupted after the
equivalent CI run passed. Its six chat shards passed 1,828 tests. The
general-server phase was stopped. This local full-suite run is
incomplete, not a passing result.
- Local synthetic fixture: four parents and 30 children, with three
completed parents archived. The fixture also has 30 archived child
records. No agent or provider calls ran. Mac arm64, Node 24.22.2,
Chromium, production assets, 1440×900, native CPU, loopback network,
fresh HTTP/query caches for each cold sample.
- Five alternating local pairs produced identical 31-row membership and
order and no browser errors:

| Journey | Baseline median (range), ms | Candidate median (range), ms |
Median paired saving, ms |
| --- | --- | --- | --- |
| Cold first usable Mine rows | 310 (252–435) | 258 (250–261) | 50 |
| Warm Recent → Mine | 60 (56–64) | 67 (61–71) | -7 |
| Task → Back to Mine | 42 (40–47) | 43 (40–45) | 0 |

The final cold result has a material control limitation. The median
primary-request start was 259 ms for baseline and 210 ms for candidate.
Much of the cold difference occurs before the changed request. The
parent response medians were 19.3 and 13.5 ms, with fewer parent IDs
requested. Do not attribute the full 52 ms difference between cold
medians to this fix. Four cold pairs were faster and one was 6 ms
slower. Warm Recent → Mine was about 7 ms slower at the median; Back was
unchanged. These runs establish no warm-navigation gain. The earlier
five-pair experiment showed the same startup confound and mixed
warm/Back results. All samples remain in the local evidence. A hosted
final-shape comparison timed out and was cancelled by closing its owned
browser tab; it supplies no result. The candidate has not been deployed.

Reproduce the contract and geometry check against an isolated production
UI with `pnpm exec playwright test --config
tests/perf/collections/playwright.config.ts parent-context.spec.ts`. Run
`tests/perf/collections/measure-mine-context.ts` against baseline and
candidate loopback production origins that share one disposable API, as
documented in `tests/perf/collections/README.md`. Preserve upstream
startup timings as controls. Required parent responses remain inside the
reveal boundary.

## Risks

- Explicit-ID `index` and `rows` requests use the same company,
visibility and actor filters. They do not use the inbox archive filter.
An archived parent is still returned by either projection. A deleted or
unreadable parent is absent in both. A second index request for a
failure-parent overlap would not restore missing caption data.
- A failed-run task must never reuse parent-only metadata. The query key
includes each projection role. Completed reads carry explicit failure-ID
coverage. The tests cover overlaps, pending role changes, late heartbeat
data, known absence, and transitions to empty views.
- Old parent context must not override a fresh indexed parent. The
current-ID placeholder filter and caption-refresh regression cover this
case.
- The hosted app still has unrelated server contention. This PR reduces
parent request work. It does not claim to fix all hosted loading delay.
Deployment acceptance should confirm the serving revision, compare
matched Mine reloads and inspect errors and row stability. Revert this
change if failure items or captions regress.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, browser
diagnostics and code execution. The exact runtime model identifier and
context-window size are not exposed by this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 13:29:04 -06:00
DottaandPaperclip 6aabcff7d1 fix(ui): add space above failed attempt notices (#18636)
Add token-based top padding outside failed-attempt notices and assert the full 16px gap in the browser check.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-02 12:10:43 -06:00
DottaandPaperclip 97c4dc969e test(evals): retire duplicate chat TestOps plans (#18625)
## Thinking Path

> - Paperclip manages AI agents and preserves their work history.
> - Product E2E cases use TestOps plans to select real AWS evaluations.
> - The full chat catalog now includes the former smoke and
completion-pilot cases.
> - The two old bootstrap workflows can recreate their smaller plans
after deletion.
> - This pull request removes those workflows and stops their
plan-creation functions before API access.
> - The full-catalog workflow keeps its shared clients, evidence rules,
case identities, and measured results.

## Linked Issues or Issue Description

Refs #18542, #18516.

The user requested removal of the duplicate smoke and completion-pilot
plans and investigation of their recreation paths. Both old workflows
accepted manual dispatch only. Their bootstrap operations created plans
by name when the plans were absent. They had no schedules in their
workflow definitions.

The old workflow records were disabled before plan removal. An existing
pilot execution was allowed to finish successfully. This change does not
cancel executions or delete cases, results, launches, or private
evidence.

## What Changed

- Remove `chat-feature-testops.yml` and `chat-completion-testops.yml`.
- Make the former singleton plan creator reject every call before API
reads or mutation markers.
- Reject pilot bootstrap before API access. Keep the full-catalog branch
and its integration validation.
- Remove tests that require the retired workflow files. Keep shared
helper and full-catalog controls. Run the trusted-checkout boundary test
against the active catalog workflow.
- Replace old setup instructions with retirement guidance and the active
full-catalog route.

The master sync preserves the incoming typed launch-search fix from
#18620, including both regression tests. The only conflict was the
retired pilot documentation. Its search-format note remains as a
retained-helper contract.

## Verification

- Two new retirement controls fail against the parent code because it
reaches an API or mutation marker. Both pass after the change.
- Six owning Node suites after the master sync: 146 passed (144 before
the sync). Shared contract: 22 passed. Catalog and retained export
controls: 12 passed. Focused workflow and release controls: 7 passed.
- Two modified API modules pass Node syntax checks. `git diff --check`
passes.
- The pure workflow-security file has the same four failures and 13
passes on both the untouched parent and this branch. Two assertions
expect eight trusted bootstrap steps where master now has nine. Two
lists omit the already-shipped catalog workflow. This change does not
repair or relax those unrelated assertions.
- A broader release-test invocation had 73 passes and 20 sandbox
failures from blocked mock HTTP listeners or npm permissions. Its
focused affected workflow control passes. A standard Vitest setup
attempt stopped on a missing `acpx/runtime` bundle dependency before
tests. No local app, database, provider, or native runtime was
qualified.
- Current-head PR CI passes: 48 successful jobs and one skipped job,
including both required checks. Greptile is 5/5. Independent source
review passes. No new model run is needed for this retirement.

## Risks

- Existing integrations that point at either retired workflow will stop
dispatching. This is the requested behavior; use the full catalog
instead.
- Historical evidence readers still use shared helpers. Those helpers
remain, including the transport and official-context parser used by the
active catalog.
- Workflow removal is a repository change. TestOps plan deletion and
disabling obsolete executors are separate service actions. Neither
action should delete shared cases or measurements.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with source editing, shell tools,
and independent source review. The context-window size is not asserted.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 11:07:32 -06:00
Dotta a6afe3e230 Fix TestOps launch preflight search encoding (#18620)
## Thinking Path

> - Paperclip manages AI agents that do real work.
> - Product evals verify the saved outcome of that work.
> - TestOps plans select and dispatch these evals.
> - Operator launchers check a unique launch name before they request
work.
> - TestOps expects an encoded filter, but the launchers send plain name
text.
> - This change uses the vendor filter format in the shared TestOps API
owner.
> - The existing checks can then prevent duplicate launch requests.

## Linked Issues or Issue Description

Refs #18516, #18608, and #18542. The completion pilot registered
successfully after #18608. Its optional API launcher then stopped with
HTTP 400 in [run
41477551241](https://github.com/paperclipai/paperclip/actions/runs/41477551241).
It stopped before the launch mutation marker. No evaluation was
dispatched by that request.

The launch search API uses Base64 of UTF-8 JSON filters. The launchers
sent plain name text. I confirmed the format in the deployed public
[vendor filter
codec](https://paperclip.testops.cloud/es-testops-CICoDnkU.js) and its
launch UI. The encoded name filter displayed the existing pilot launch.
The TestOps UI separately dispatched [the genuine three-case
pilot](https://github.com/paperclipai/paperclip/actions/runs/41478906153);
this PR does not create another run or claim that pilot passed.

## What Changed

- Add the typed name-filter encoder to the existing TestOps API module.
- Use it in the backlog and completion launch preflight requests. The
full-catalog route uses the same completion adapter.
- Preserve the exact launch name, nonce, selection, authorization,
once-only markers, and no-resend behavior.
- Add protocol controls through both real launch functions. Document the
wire format.

## Verification

- Red: both new consumer controls reproduce the HTTP 400 boundary with
plain name text. The other 109 API controls pass.
- Green: all 111 API controls pass after the fix. All 166 related API,
pilot contract, and full-catalog controls pass with Node 24.22.2.
- The first broad local invocation lacked the `yaml` dependency in the
new worktree. Its failure log is retained. Reusing the existing
installed dependencies allowed all 166 controls to run and pass without
further source changes.
- The vendor-format query displayed the existing uniquely named pilot
launch in the authenticated TestOps UI. No launch POST or model call was
used for this read-only verification.
- Diff check passes. All required CI checks pass on exact head
`b55bdc6753fa042e4c2465e7b9b366b8126b4730` ([run
41480643021](https://github.com/paperclipai/paperclip/actions/runs/41480643021)).
Both current-head reviews are 5/5, with zero unresolved findings. No
TypeScript, compiled product, workflow, grader, model, clock, retry, or
evidence-boundary changes.

## Risks

The vendor can change its search format. The format is kept in the
existing provider-specific API module, and both launch consumers have
protocol controls. Existing duplicate detection and uncertain-response
refusal remain in place. The already-running UI pilot is independent of
this fix.

## Model Used

OpenAI GPT-6 through Codex assisted with reasoning, repository
inspection, code execution, and native accessibility tool use. The host
does not expose the exact 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
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [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 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-11-02 10:40:23 -06:00
Dotta 9203ab52f0 fix(evals): bind complete unassigned TestOps plan buckets (#18608)
## Thinking Path

> - Paperclip manages agents that do real work.
> - Product evals check the saved outcome of that work.
> - TestOps plans select the exact automated cases to run.
> - A new plan can report its unassigned cases as a job-statistics
bucket.
> - The pilot registration guard rejects that bucket as a foreign job.
> - This change binds only a complete, known unassigned bucket and
records assignment diagnostics before writes.

## Linked Issues or Issue Description

Refs #18516 and #18542. The metadata-only bootstrap in
[41464514278](https://github.com/paperclipai/paperclip/actions/runs/41464514278)
created the dedicated plan and verified its GitHub job definition, then
stopped at `plan_job_mismatch` before job or case-assignment mutations.
No model work ran.

The retained receipt did not include the assignment rows. The live
failure's exact shape remains unconfirmed. The API's job-statistics
carrier permits an absent job. The old guard rejects a complete
unassigned bucket. This PR covers that case and records the actual rows
in the next closed inspection.

## What Changed

- Accept one closed unassigned bucket with the exact selected-case
count. Support an explicit null job or an omitted optional job field.
- Assign the exact selected cases once. Keep the existing owned
assignment without assigning it twice.
- Reject foreign jobs, mixed buckets, wrong counts and unknown
unassigned fields before mutations.
- Retain only bounded assignment kinds, numeric job IDs and counts in
the existing observation receipt.
- Merge current master, including the full-catalog adapter from #18542.
Retain its context-aware plan and job checks alongside the new pre-write
assignment inspection. The helper consumes that context’s expected case
count.
- Document the inspection and binding rules. The helper takes the
expected count from its owner. This does not import or run the
full-catalog route from #18542.

## Verification

- Red: both complete unassigned carriers fail on the old guard; the
other 70 dispatch/API controls pass.
- Green: all 72 dispatch/API controls passed before the master sync.
After the sync, all 104 related pilot and full-catalog Node controls
pass. They include ordinary registration, no duplicate assignment,
foreign-job rejection, incomplete and unknown bucket rejection, launch
fences, uncertain-response protection and result readback.
- Diff check passes. No TypeScript or compiled product code changes.
Full repository checks were not run locally. All required CI checks pass
on current head `a8bec6418065a7faae28c8daab3efdfc9b184797` ([run
41473510972](https://github.com/paperclipai/paperclip/actions/runs/41473510972)).
Both current-head reviews are 5/5 with no unresolved threads. Before the
master sync, one unchanged server timing test failed on attempt one and
passed on the only targeted rerun; that original failure remains in CI
attempt one. No rerun was needed on the current head.
- Live acceptance still requires another metadata-only inspection,
followed by a genuine three-case TestOps launch. This PR does not claim
a new passing measurement.

## Risks

An overly broad unassigned rule could replace an existing job. The new
rule permits only one known bucket with the exact selected-case count
and no foreign job. All final binding checks still apply. Unknown
assignment shapes stop before writes. Original case queries, model,
clocks, graders, evidence rules and retries are unchanged.

## Model Used

OpenAI GPT-6 through Codex assisted with repository inspection, code
execution and tool use. The host does not expose the exact 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
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run the relevant local controls and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-11-02 09:56:36 -06:00
DottaandPaperclip 27db8354e4 fix(ui): make failed attempt notices stand out (#18174)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/257/changes/paperclip/257
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations show when an agent could not finish a saved
request.
> - The exhausted-attempt notice currently looks like ordinary muted
status text.
> - People can overlook both the failure and its available Retry action.
> - This pull request gives failed attempts a padded, tinted surface and
a recognizable error icon using existing tokens.
> - The benefit is a clearer failure state while automatic recovery
keeps its quiet presentation.

## Linked Issues or Issue Description

Related: #17386 and #14156 cover recovery behavior. This PR only
improves the exhausted-attempt notice's presentation. Searches found no
duplicate styling PR.

**What happened?**

“Couldn’t finish this attempt. Your message is saved.” appears as muted
text without a background or padding above the task conversation, making
the failure easy to miss.

**Expected behavior**

An exhausted attempt should have a distinct, readable surface with
internal spacing and an obvious Retry action when permitted.

**Steps to reproduce**

1. Open a task whose system-owned interruption is `failed`.
2. Find the notice above the conversation.
3. Compare it with an automatic retry countdown. Previously, both had
the same muted inline treatment.

## What Changed

- Style failed attempts with a rounded destructive-tinted background,
token-based padding, foreground text, and a decorative error icon.
- Center the icon with the message and Retry button, including when the
message wraps.
- Keep the Retry button from shrinking on narrow screens.
- Check the center positions in the existing browser layout test.
- Add a production-component Storybook example beside a saved message.
- Document the exhausted-attempt treatment in the design guidance.

## Verification

- `pnpm check:token-gates` and `node scripts/check-maps.mjs`: pass.
- `pnpm exec vitest run
ui/src/components/ExecutionBlockerNotice.test.tsx`: 8 tests pass. These
cover Retry, countdowns, read-only access, active and resolved states,
admission waits, and admission errors.
- Chromium layout: 4 cases pass at 320px and 1280px in light and dark
themes. The icon, text, and Retry button have the same vertical center.
The previous code failed this check by 8–10px.
- Updated desktop and mobile screenshots are saved with the task.
- `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter
@paperclipai/ui build`: pass after the workspace SDK is built.
- Full local typecheck and build need Cargo. Cargo is not installed in
this sandbox. The full local Vitest run did not complete in the prior
session. CI must verify these checks.
- The updated head `4ba8de9da3e5c0c084cb5f752f371eccff31376a` passes all
test jobs, typecheck, build, and all eight E2E shards. The final CI
summary is queued.
- Greptile completed its review of this head with a score of 5/5. It
found no actionable issues. There are no review threads.
- The separate Paperclip Review check is queued. Its review task stopped
before it could publish the result. This check must complete before
merge.

## Risks

Low risk: this is a presentation-only change. The failed state takes
more vertical space. Recovery, authorization, retry timing, and API
contracts retain their existing behavior. Colors, spacing, radius, and
icon sizing use existing design tokens.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 09:25:24 -06:00
DottaandPaperclip 774ddc7271 test(evals): add the full chat catalog to TestOps (#18542)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat feature evaluations check real user requests through the
product.
> - The YAML catalog has 244 scenarios, but the shipped TestOps
completion route selects only three.
> - The preserved catalog already supplies the execution mappings and
independent oracles.
> - A larger TestOps plan needs exact identities, bounded selection and
source-bound private evidence.
> - This pull request adds that plan route without merging the catalog
app into master or replacing its grades.
> - Users can run the full catalog or a selected subset and see the
actual outcome and prerequisites.

## Linked Issues or Issue Description

Refs: #18516 and #18515. This extends their completion pilot and reuses
its trusted reporting path.

**What existing behavior does this improve?**
The existing three-case TestOps completion workflow.

**Current behavior**
The remaining catalog scenarios cannot be selected through that TestOps
job. The one-case backlog plan has a separate strict singleton contract.

**Proposed behavior**
A separate candidate-scoped plan maps all 244 scenarios. Existing case
aliases, jobs, plans and result history stay intact. Registration is
distinct from a measured pass.

## What Changed

- Add a source-derived 244-row manifest. It binds the 242 domain
descriptors and two legacy tasks to the unchanged YAML queries,
contexts, outcomes and original bounds. The JSON snapshot avoids
importing the unmerged domain tree into master.
- Reconcile exact case identities and a dedicated full-catalog plan.
Reuse legacy aliases, including the existing backlog case, without
renaming them. Preserve history and stop on conflicting aliases or
uncertain writes.
- Extend the shared completion adapter with a separate trusted
full-catalog workflow context. Return a compact observed binding that
fits one 48 KB protected variable. Keep the three-case pilot contract
intact.
- Add a fixed-source manual workflow. Small selections run serially.
Larger selections allow eight independent workers and one serial
external-input worker. Each worker and report reader keeps a singleton
approval and exact-key AWS session. The eight-cell private authority
limit is unchanged.
- Validate and merge metadata-only singleton projections before one
protected Allure upload and complete paginated readback. Preserve failed
originals and cleanup failures beside passed results. Keep screenshots
and raw evidence private.
- Discard a changing full-catalog page-count snapshot and retry within
the same observer bounds. Malformed page fields still fail at once. A
pass still needs one consistent exact selection and all final evidence
checks.
- Keep workflow source and app source separate. The full lane builds
candidate `3b66c3c144360ddf32714a0742fd774b8ceafb16`. Its only changes
from the existing `de0941835cc8f0d01c982574ee258e110babdbeb` pin are
finite TestOps host admission and its offline test. This is not
current-master app qualification.
- Give full selections above three cases a bounded metadata-read
allowance above the existing 120-second deadline ceiling. Readback has
two upper bounds: at most twelve polls with five-second pauses, and a
size-derived deadline of at most 374 seconds, whichever exhausts first.
There is no guaranteed minimum wait or processing SLA. Small selections
and pilot deadlines stay unchanged. Final identity, grade and evidence
predicates stay intact.
- Document the real readiness limits and setup path. Five coverage gaps,
six evidence exceptions, eighteen additional-credential declarations and
thirty-seven external-input declarations overlap. They are not new pass
claims.

## Verification

- Related Node controls passed: pilot API and dispatch, 244-row
manifest, idempotent reconciliation, full selection, three-page result
readback, source guards and partition/output-size bounds. The latest ten
adapter controls include the actual registration receipt's variable-size
limit and the real bootstrap facade's closed failure codes and privacy
checks.
- A deterministic 244-result replay with one second per HTTP response
failed at the old deadline and now verifies after 127 virtual seconds. A
three-second response replay still rejects at 375 virtual seconds. The
full-lane allowance accounts for paginated reads and four-way result
batches; it is not a guaranteed network SLA. All 55 related API/adapter
controls pass. They also reproduce the changing-page-count failure
before the fix, then verify the consistent snapshot. Permanently
changing counts fail after twelve polls. A malformed numeric field still
fails before a retry.
- Owning export controls: 26 passed. They include all 244 synthetic
carriers, mixed passed/failed originals, missing and foreign
projections, privacy filtering and exact source binding.
- Candidate host owner: 31 offline controls passed. The new
finite-catalog case failed before admission changed.
- Preserve two actual local regressions: canonical scenario provenance
failed before its one-line fix; the full registration binding exceeded
the variable limit before compact output. Both now pass.
- Initial local harness setup attempts failed before test execution. The
final narrow owner configuration avoids provider-bundle setup.
- Full repository tests, build and typecheck were not run locally.
Normal required PR CI provides the remote checks.
- Owning TypeScript no-emit, actionlint, paid-workflow policy with
unsafe controls, and diff checks passed.
- Local tests used Node 26.4.0. These are synthetic source controls. No
local app, database, native build or provider qualification ran.
- CI
[41307571776](https://github.com/paperclipai/paperclip/actions/runs/41307571776)
on `23e518be` recorded one 15-second timeout in
`attention-retention-work.test.ts:153`. All other ordinary leaves
passed. The test used a fixed JavaScript date but its retention deadline
comes from PostgreSQL `updatedAt`. The exact failing await and original
SQL timestamp were not captured. The corrected pre-sync head’s server
shard (2/12) passed on AWS in CI 41309030928. Current master
independently fixed the same clock assumption in #18543; conflict
resolution adopts that whole upstream file. No local PostgreSQL run or
timeout increase was used.
- Current-head normal CI
[41463567187](https://github.com/paperclipai/paperclip/actions/runs/41463567187)
passes all required checks on
`fc6c2309cfc7d1e5a83f0a597c7fa1d2beb987e1`, with Greptile 5/5 and all
review threads resolved. The final diff has 23 catalog files. Current
master’s whole retention test is adopted; the redundant earlier test
change is absent. The valid changing-page snapshot regression passes
with all 55 related API/adapter controls. No new TestOps import or live
evaluation has run for this change. After delivery, use metadata-only
bootstrap and a three-case normal TestOps selection to verify the new
route. Do not claim a new 244-case measurement.

## Risks

- The app target remains the preserved catalog candidate. Each result
records its target and workflow revisions. No old campaign ordinal,
acceptance gate or core fix is changed.
- Some mapped cases need private account configuration or have known
source/evidence gaps. Their original checks and evidence rules can still
fail. A registration does not establish readiness or success.
- Whole-plan execution can take hours and spend provider and AWS money.
Original per-case limits and zero retries remain. Unknown setup usage is
not free. This PR does not run all 244 cases.
- The raw private `SOURCE_REF` field retains the prior
integration-lineage label. It is not a verified checked-out branch. The
actual candidate checkout and all authority checks use immutable
`3b66c3c144360ddf32714a0742fd774b8ceafb16`; public projections set
`source.ref` to null.
- TestOps has no atomic bulk upsert. Reconciliation retains partial
progress and performs no automatic resend after an uncertain response.
- The trusted inventory keeps a 12 MiB limit per public carrier file.
The larger parser ceiling does not promise admission above that limit.
The existing 244-case fixture produces a 1,359,465-byte normalized
carrier; this is not a guarantee for future payload sizes.
- Raw evidence remains under the existing private retention owner.
Public GitHub artifacts and TestOps attachments contain only allowlisted
metadata and availability receipts.
- The new workflow needs the exact master entry in the existing runner
group's selected-workflow list before a live run. No repository or
runner-group visibility is broadened by this source change.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) assisted with implementation and
independent source review, using code and tools. The host does not
report 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 linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run the relevant local controls and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 08:58:44 -06:00
06bc8db75c fix(runner): install verified API artifacts in execution workspaces (#18494)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Native agents use authorized API tools to read saved results.
> - Copying a large response as model-generated text can lose bytes.
> - The execution workspace needs an exact copy of the saved artifact.
> - This change copies the authorized bytes without shell API
credentials.
> - The runtime verifies size and SHA-256 before it reports success.
> - A live evaluation checks capture origin, installation and delivered
bytes.

## Linked Issues or Issue Description

**What happened?**

A native agent lost one byte while copying a 24576-byte API text page.
Existing capture and paging controls passed. The runtime had no verified
saved-artifact-to-workspace copy tool. A separate historical screening
refusal does not establish capture corruption.

**Expected behavior**

An authorized native run can install the complete saved artifact. The
stored and installed bytes must match in size and SHA-256. A conflicting
file must remain unchanged. A lost publication receipt must not cause an
unsafe repeated write.

**Steps to reproduce**

Run
`server/src/services/native-runtime/artifact-transfer.integration.test.ts`
on baseline `c46b8f35add9255fc71be294d27f5a7865bcb47f`. Its capability
assertion fails because `download_artifact` is absent. Apply this PR and
run the same regression with the filesystem and API controls. It
verifies 388131 synthetic bytes through the authority and installation
boundary.

Refs #18429. Related #17393, #17086 and #17285 cover paging, transfer
foundations and remote output reads. This PR adds the inbound
installation contract.

## What Changed

- Add `download_artifact` for supported standard-mode native runs, with
a 10 MiB limit.
- Reuse current company, task, run, asset-content and responsible-user
access checks. Check authority again before publication.
- Bind installation to the current execution lease. Stage through
confined Linux descriptors and publish with an atomic create-only link.
Keep API credentials out of execution commands.
- Verify bytes at storage and execution boundaries. Reject unsafe paths,
symlinks, different existing files, truncation and corruption. Reconcile
an unknown publication through verification only; an identical explicit
retry remains safe.
- Add API documentation, access-map entries and content-free audit
records.
- Preserve only the pinned Daytona SDK numeric HTTP status when failed
creation cleanup is unconfirmed. Keep provider exception messages and
headers private.
- Keep only the finished runner binary and portable provider pack in
their builder layers. Remove Rust targets/downloads and the Node install
workspace/store before export. Report tree sizes.
- Add one explicit Codex/Daytona Product E2E cell. Its independent
oracle checks the server capture audit, redacted tool receipts, stored
source, delivered attachment and browser link after reload. Uploaded
substitutes and one-byte loss fail.

## Verification

- Merge update at `6766b46553cab5b9787ade87a002eccaf50e68fc`: merge
current master and preserve both explicit suites in the catalog. Focused
catalog, image and oracle checks: 122 pass. Filesystem and authority
integration: 20 pass. Maps, module boundaries and whitespace checks
pass. New-head CI and Greptile are running. Full local build and
typecheck remain unavailable because cargo is absent.

- Behavioral red/green: the absent-tool regression failed before
implementation and passed afterward. The initial missing-package attempt
is recorded as setup failure.
- Linux filesystem and real PostgreSQL/authority integration: 19
filesystem tests and 1 authority test pass. Existing API authority,
capture and paging controls: 70 pass, 2 skipped. Provider transport in
these integration controls is simulated.
- Qualification calibration: 118 focused tests pass. The real
persisted-event redaction case and a byte-identical uploaded substitute
each failed before their oracle repair. The unchanged controls then
passed. Harness typecheck passes.
- Full recursive typecheck and build pass locally on the integrated
production source at `086f7a2901`. Later commits change only
qualification tests and documentation.
- Structural map/module checks and whitespace checks pass.
- Full local `pnpm test:run` was attempted by the implementation worker
and stopped under its 8 GiB memory limit, with no full-suite verdict.
Current-head CI must supply the full test result.
- The complete local Product E2E support suite has 13 failures. The
unchanged pre-qualification baseline reproduces all 13: host PostgreSQL
semaphore capacity, stale timeout/profile/workflow inventory
expectations, and expired fixed-date allowance fixtures. This is not a
full local suite pass.
- Earlier CI at `086f7a2901` failed a browser test during cleanup
cancellation with a database lock timeout. It remains recorded. All
browser shards passed on both later fully checked heads.
- Two qualification campaigns were canceled during setup before provider
execution while correcting the oracle. They provide no live product
verdict.
- Previous-head CI at `28fa001457f59df1c300c016dc569049e72d0061`: 53
checks pass, 3 intentional selection skips; no failed or pending checks.
- Real image/export regression: campaign 41272351780 compiled the Linux
runner and passed root/unprivileged CLI and transport checks, then
failed BuildKit export with `no space left on device` (exit 102,
filesystem 99.99%). No provider cell ran. Removing the Rust build trees
alone was insufficient: campaign 41273604815 also failed during
provider-pack export with exit 102. Commit `5bbb549c54` also
consolidates dependency installation and pack construction so the
disposable workspace/store can be removed in the same layer. All 122
image/oracle/catalog checks pass. Image and remote-pack publication then
passed in campaign 41275196741 after cleanup changes plus a scoped
60-to-120 GiB expansion of only its delete-on-termination builder disk.
The VM terminated and the expanded volume was deleted. This does not
establish that cleanup alone makes the default 60 GiB builder
sufficient.
- The Daytona admission probe then failed before agent creation, with
unconfirmed provider cleanup. The queued continuity case was canceled
because it shares this prerequisite. No artifact-transfer or continuity
success is claimed.
- Status-diagnostic regression: the original generic wrapper failed the
HTTP-status assertion. After the repair, the full plugin suite passes
501 tests, with 7 skips; its standalone TypeScript check passes.
Controls reject invalid status values, avoid accessors, preserve the
original create status and exclude credential canaries.
- Previous-head Greptile: 5/5; its summary names
`28fa001457f59df1c300c016dc569049e72d0061`. All review threads are
resolved.
- Live artifact transfer and three-turn warm continuity: NOT VERIFIED.
The diagnostic case in
https://github.com/paperclipai/paperclip/actions/runs/41277598289
confirmed Daytona HTTP 401 before agent creation. The configured
`DAYTONA_API_KEY` in the existing `runner-e2e-paid` environment needs
verification or refresh. The queued continuity control was not run after
its shared admission prerequisite failed. No further provider attempt is
planned until the credential changes. Unconfirmed provider cleanup
remains recorded.

## Risks

- Source-provenance changes can repeat the provider dependency install.
The combined build layer trades install-cache granularity for lower
retained disk use.
- Linux descriptor semantics and Node are required on the execution
host. Unsupported providers and restricted runtime profiles fail closed.
- Storage reads buffer at most 10 MiB. A provider outage can leave a
reserved staging file. Partial bytes never become the destination.
- A lost publication receipt can leave a complete file with an unknown
result. Recovery verifies the existing file without installation.
Conflicts are never overwritten.
- Artifact contents remain untrusted. The copy does not bypass screening
or authorize downstream execution.
- Live qualification uses the governed Codex API profile. It does not
establish every model, subscription profile, platform or historical
failure cause.

## Model Used

OpenAI GPT-6 in Codex assisted with diagnosis, code, tests and
qualification. The desktop runtime does not expose a more specific model
deployment ID or context-window size. The model used reasoning, source
inspection, tools and code execution. The native implementation agent is
configured with OpenAI `gpt-6.1-sol`.

## 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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 08:27:09 -06:00
DottaandPaperclip f6fc336a35 fix(ui): reveal task conversations without loading layout shifts (#18545)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tasks combine saved messages, documents, run output, monitors, and
decisions.
> - Compact history makes long tasks load quickly.
> - The loading view still showed the real task header before the thread
scrolled to recent messages.
> - Different loading frames also changed the viewport, composer bounds,
and header typography.
> - This pull request uses one loading frame and reveals the prepared
conversation once.
> - The benefit is a stable first view without a material loading-speed
penalty.

## Linked Issues or Issue Description

**What happened?**

A cold task open could show a generic skeleton, then the real title and
monitor above placeholder messages, then jump to recent content. The
loading view changed width on desktop and height on mobile. Its title
line height differed from the real title.

**Expected behavior**

Keep the loading viewport and composer in place. Prepare the initial
reading position out of view. Reveal the recent conversation once its
data, fonts, scroll position, and composer bounds settle. Cap the font
wait at three seconds if the font host does not answer.

**Steps to reproduce**

1. Open a task with a long title, long saved replies, document cards, a
monitor, and a pending decision.
2. Reload it with CPU and network throttling.
3. Watch the header appear above placeholders, then move offscreen when
the recent conversation appears.

**Paperclip version or commit**

e122478368. The synthetic baseline recorded 10 animation frames with a
real header visible before the conversation was ready.

**Deployment mode**

Built from source. Local production previews used the same disposable
PostgreSQL fixture and API.

Related work: #17593, #16878, #18092, and #18461 preserve compact
startup and saved-card behavior. Older open PR #14667 addressed
transcript reveal and reading anchors; this change targets the remaining
loading-frame transition on current master.

## What Changed

- Prepare task data while the personal layout preference loads. Keep the
temporary page hidden until the correct layout is known. This removes a
12 px mobile header change.
- Share one matching loading frame across task metadata and history
preparation. Use the real composer surface and dock geometry for its
placeholder.
- Keep the real title and monitor concealed until the viewport, scroll
position, composer, and fonts settle. Bound a stalled font request to
three seconds.
- Reserve the final chat viewport and breadcrumb identifier position.
Mount task properties after the personal preference resolves.
- Match the loading title typography to the selected task interface,
including Classic.
- Add normal-CI browser coverage for rich tasks, Classic startup and
typography, mobile layout selection, and stalled fonts. Preserve the
outage recovery assertions.
- Add Design Guide examples and an optional retained fixture with 200
long messages, documents, a PR card, a monitor, and a pending
confirmation. Disable both interval and on-demand agent wakes in this
fixture.

## Verification

- Final UI source: `8398af3493`. The later commits change tests or merge
master. The recorded production build is `99867e2dc3`; its UI source is
identical to the final PR head.
- All 10,263 UI tests pass: `pnpm --filter @paperclipai/ui exec vitest
run`. Workspace typecheck and the full production build pass. Token
gates, module boundaries, map validation, and diff checks pass.
- Task browser checks pass 40 cases. Shared chat passes 22 cases. The
normal-CI loading and outage recovery suite passes all 13 cases on the
final head.
- The eight rich loading cases cover direct and list entry, delayed
fonts, and delayed personal preferences on desktop and mobile. At 4× CPU
slowdown and 80 ms latency, each records zero real-header frames before
reveal. Loading-frame, composer, and initial reading-position movement
are 0 px. Title typography matches.
- The normal browser suite also verifies that unresolved mobile layouts
stay hidden, the selected mobile viewport stays fixed, and a seeded
Classic loading title matches the resolved title after an uncached
reload.
- Cold speed: five fresh contexts per variant and viewport, alternating
before/after order. Same local API and synthetic fixture; 4× CPU
slowdown, 80 ms latency, 1.18 MB/s download. No interception,
recordings, builds, or test suites during measurement. Desktop median:
3578 ms before, 3572 ms after. Mobile median: 3500 ms before, 3476 ms
after. Sample ranges overlap.
- The unmodified baseline records 10 real-header frames before
readiness. The final eight-case matrix records zero. Local recordings
and failed prototype evidence are retained outside the repository. No
private staging content is published in this PR.
- CI initially counted hidden zero-size elements as visible frames. Its
saved data confirms the `(0, 0, 0, 0)` entries. Both browser samplers
now ignore those entries and retain all visible geometry checks. The
corrected local suite passes.
- The default `pnpm test:run` command stopped in the unchanged server
chat integration shard with `No test found ... in lines ...` and 1817
skipped tests. This is not a local full-suite pass. One unchanged
AgentActionButtons test also failed during a concurrent run; all 37
cases pass in isolation, and the full 10,263-test UI rerun passes
without source changes to that component.
- Final-head [CI
passes](https://github.com/paperclipai/paperclip/actions/runs/41320240728)
at `d1ef4a955f`. No checks are failed or pending. Greptile and Ponytail
Paperclip Review both report 5/5 for that exact head. All review threads
are resolved.
- The fix is not deployed to staging.

## Risks

- First reveal waits for stable geometry and fonts, with a three-second
font cap. A font that arrives after this degraded-mode cap can still
change text metrics. The existing history deadline still exposes usable
content if another dependency stalls.
- The loading frame cannot predict arbitrary conversation content. The
real content remains concealed until its initial position is ready.
- The shared thread also serves agent chat. Its browser startup and
scroll journeys are included in final verification.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, tool use, code execution, and
browser inspection. The host did not expose a more specific model ID or
the context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 08:13:34 -06:00
TonioandClaude Opus 5.5 8ea240218d feat(ui): bring the Refine-v2 layout to the agent page (#18378)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The agent page is where an operator reads and changes one agent.
> - The page grew one tab at a time. Ten tabs sit in one flat list, the
header holds many buttons, and the audit links leave the agent.
> - A design pass, called Refine-v2, made a calmer layout for this page.
It ran in a prototype on fixture data only.
> - This pull request moves the Refine-v2 layout and behavior into the
live agent page. Where the prototype and the live page differ, the live
behavior stays. For example, the floating save bar stays on screen.
> - The benefit is a shorter navigation, edits in place, and audit data
that stays inside the agent.

## Linked Issues or Issue Description

Refs #13716
Refs #9166

Both pull requests mount plugin tabs or slots on the agent page. They
touch the same files, so one of the three needs a rebase after the
others merge.

**Subsystem affected**

The agent detail page in `ui/` (`ui/src/pages/AgentDetail.tsx`, its
sidebar, header actions, and the shared agent config form).

**Problem or motivation**

The agent page is hard to scan. The navigation shows ten items in one
list. The header shows Run now, Pause, Clear error, and Assign task as
separate buttons. The name, title, and manager are form fields deep in
the Harness tab. Activity, Runs, Costs, and Budgets open company-wide
pages, so the operator loses the agent context. Each tab uses a
different card and table style.

**Proposed solution**

Use one layout system for every agent tab. Group the navigation into
Agent and Audit. Edit the name and title in the header. Move the work
actions into the actions menu. Show audit views inside the agent. Keep
the persistent save bar and add a status dot to it.

**Alternatives considered**

We considered a flag that lets operators opt in to the new layout. We
did not use a flag, because two layouts on one page double the test
surface. We also considered moving the save button to the end of the
scrolling content, as the prototype did. We kept the floating save bar,
because it is always visible.

**Roadmap alignment**

`ROADMAP.md` has no item for the agent page. This change is a UI
refinement of an existing page. It adds one optional field to an
existing API request and no database schema change.

## What Changed

- **Navigation.** The agent sidebar shows two groups. Agent has
Overview, Identity, Harness / Runtime, Secrets & variables, Permissions
/ Trust, and Advanced. Audit has Activity, Runs, Costs, and Budgets.
Skills, Tools, Channels, and API Keys leave the navigation. Their URLs
still open. The Instructions tab is now Identity, at `/identity`. The
old `/instructions` URL redirects.
- **Header.** The agent character shows at a larger size. The name and
title edit in place. Enter or blur saves. Escape cancels. An error
restores the old value. A rename updates the URL. While a tab has
unsaved changes, the header refuses the edit and asks the operator to
save or discard first. The third line shows the title and a link to the
manager. A crown button to the right of the name replaces the "Set as my
primary" link and the separate primary indicator. It is outlined and
dimmed until the agent is your primary, then fills with a short pop.
Replacing an existing primary asks for confirmation first, and the pop
plays after the dialog closes. Reduced motion skips the pop. Run now,
Pause or Resume, Clear error, and Agent history move into the actions
menu. Assign task is the primary button. For an agent that still needs
setup, Finish setup is the primary button and Assign task moves into the
menu.
- **Agent history.** A new dialog in the actions menu replaces the
Revisions entry. Each row shows a plain-language summary, the person or
agent who made the change, the date, and Restore. Restore asks for
confirmation. A failed restore shows its reason inside the confirmation.
- **Overview.** Four metric tiles show activity this week, runs this
week, costs this month, and budget used. Each tile links to its audit
view. When the list behind a count is capped, the tile shows a lower
bound, for example 200+. The activity tile follows live updates.
Profile, Skills, and Recent tasks panels follow. The Profile panel lists
direct reports under their label in at most two rows, then a "+N more"
button that expands the list. The Latest run card is removed.
- **Identity.** The file preview shows the raw text. A pencil button
switches to a plain text editor. Copy and Delete are icon buttons. A
chip next to the file name says "Managed by you" or "Managed
externally". Per-file history and unsaved edits stay.
- **External instructions.** "Advanced settings" opens Root path and
Entry file fields and a Load profile button. Load profile asks the
server to switch only if the root directory and the entry file already
exist. If either is missing, the server refuses and the panel shows the
reason. The entry file can have any name inside the root.
- **Instructions bundle API.** `PATCH /agents/:id/instructions-bundle`
accepts an optional `requireExistingEntry` flag (`packages/shared`
validator, `server` service, `ui` client). With the flag, the server
checks the root directory and entry file before it creates or copies
anything. Without the flag, the behavior does not change.
- **Harness / Runtime.** The config form gets a `panels` layout: Harness
and Execution side by side, then the runtime test, then environment
variables. The identity and run-policy sections are hidden from this
tab.
- **Secrets & variables and Advanced.** These tabs use the same filled
panels and table headers.
- **Permissions / Trust.** The trust presets show as selectable cards.
An Allowed connectors panel shows up to three connector logos and links
to Apps, filtered to installed connectors. Capabilities sit in their own
panel. Changes on this tab save at once, with no save bar.
- **Audit inside the agent.** Activity, Runs, Costs, and Budgets render
inside the agent page. Runs is locked to the current agent. A failed
budget incident action shows its reason under the incident.
- **Save bar.** The floating save bar stays. It shows an amber dot for
unsaved changes and a green dot with "Changes saved" after a save.
Discard stays.
- **Leave guard.** If the form has unsaved changes and the operator
clicks a link, a dialog asks to keep editing or discard the changes.
Browser back and the header actions keep the native confirm.
- **Apps.** `/apps?source=installed` opens the Apps page on the
Installed filter.
- **Tokens.** New `--agent-detail-*` tokens in `ui/src/index.css` hold
every spacing and fill value. Each fill is a mix of foreground into
background, so one value works in light and dark themes.
- **Tests and maps.** Tests cover the navigation model, sidebar, header
menu, Overview layout, Identity editor, and helpers. The
agent-configuration recipe in `maps/feature-map/agents.md` describes the
new page.

## Verification

- `cd ui && npx vitest run`: 849 test files and 10,081 tests pass.
- `cd server && npx vitest run
src/__tests__/agent-instructions-routes.test.ts
src/__tests__/agent-instructions-service.test.ts`: 40 tests pass.
- `npx playwright test --config tests/e2e/playwright.config.ts
tests/e2e/onboarding.spec.ts
tests/e2e/chat-adapters-ui-providers.spec.ts`: 26 tests pass.
- `cd ui && pnpm typecheck` passes. This includes the Storybook catalog
check. The `server` and `packages/shared` typechecks pass.
- `cd ui && pnpm build` passes.
- `pnpm run check:token-gates` reports all gates clean.
- `node scripts/check-maps.mjs` and `node scripts/storybook-catalog.mjs
--check` pass.
- Manual check on a local instance, in light and dark themes:
1. Open an agent. Confirm the sidebar shows the Agent and Audit groups.
2. Click the agent name in the header. Type a new name and press Enter.
Confirm the URL changes. Rename it back.
3. Open the actions menu. Open Agent history. Confirm the rows and the
Restore confirmation.
4. Open Identity. Click the pencil. Change a line. Confirm the save bar
shows the amber dot. Click a sidebar link. Confirm the discard dialog.
Click Keep editing, then save. Confirm the green dot.
5. Open Harness / Runtime, Secrets & variables, and Permissions / Trust.
Confirm the panels and the trust cards.
6. Open Runs under Audit. Confirm the list shows only this agent and the
page stays inside the agent.

## Risks

- This changes a high-traffic page for every operator at once. There is
no flag to switch back.
- Run policy and Reports to are no longer editable on the agent page.
The header shows the manager as a link only.
- Skills, Tools, Channels, and API Keys are reachable by URL only.
Operators who use them from the sidebar must use the URL.
- The pull request conflicts with #13716 and #9166 in `AgentDetail.tsx`
and the agent sidebar.
- Storybook stories for the agent page and `DESIGN.md` are not updated
in this pull request.
- The new `requireExistingEntry` flag is opt-in. Existing API callers
keep the old behavior, which creates a missing external directory and
entry file.
- I ran two e2e spec files locally, not the full `pnpm test:e2e` or
`pnpm test:release-smoke`. CI runs the full e2e suite. I did not run the
repo-wide `pnpm -r typecheck`, because the local toolchain has no Rust.

> 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`), in Claude Code, with
reasoning and tool use (shell, file edits, and a browser for visual
checks). A person directed every design decision.

## 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-11-01 22:27:09 -08:00
DottaandPaperclip 7751fc3107 fix(server): complete volume-free controller admission and recovery (#18543)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Its volume-free web server must admit remote warm execution without
depending on a local disk.
> - Fresh run rows retain the initial legacy label during workspace
preparation.
> - The native runtime selector commits the execution mode later.
> - The earlier guard rejected valid remote runs before that selection.
> - This PR checks storage during preparation and the resolved lifecycle
during runtime selection.
> - Agent-file recovery also has to reconstruct disposable cache paths
from the retained remote directory.
> - The deployment test removes the complete predecessor home, including
immutable caches, to enforce that contract.

## Linked Issues or Issue Description

Refs #18518, #18529, #18533.

**What happened?**

A real Codex/Daytona deployment test failed during setup because the
volume-free workspace guard checked the initial run label. After fixing
admission, controller retirement first failed on an immutable skill
cache. Removing that cache exposed a production recovery failure: B
rejected the saved agent-directory path from A, even though the remote
execution identity was unchanged. The next live attempt recovered that
directory and transferred the same runner, but adoption then tried to
recreate provider launch assets from the deleted controller home.

**Expected behavior**

Allow remote workspace preparation before native selection. Reject
actual legacy and per-turn execution at the runtime boundary. Delete the
entire stopped predecessor home, including immutable caches, without
following links to shared dependencies. B must reconstruct its local
agent-file projection from the exact registered remote lease while
preserving the save baseline and unsaved remote edits. Reattaching an
already-running provider must not prepare a new launch or require the
old launch files. The full backend must recover the admitted
instructions from the matching durable run checkpoint.

**Steps to reproduce**

Run the explicit
`rolling-web-deployment.runner-codex.daytona.recover-controller` Product
E2E cell with a complete server/UI build, disposable PostgreSQL/S3, and
an owned Daytona fixture. The new boundary regressions also reproduce
the premature guard and missing runtime rejection without a model call.

**Paperclip version or commit**

The failures were observed on
`247552fe0719dcc92f7b42c50b658be6f624986d`. This branch is based on
`e122478368`.

## What Changed

- Validate Runner and remote workspace authority before runtime
selection without trusting the initial run label.
- Reject resolved legacy execution and local-source fallback, preserving
the native warm-policy check before admission.
- Rebind remote agent-file caches on ephemeral controllers and retrieve
their validated contents without uploading over the retained execution.
Preserve pending saves when the remote collector is unavailable.
- Restore over-quota remote directories without applying save quotas to
run admission; ordinary saves still enforce quotas.
- Skip provider launch asset materialization when adopting an existing
Runner. A real-process regression deletes the old skill/instruction
sources before reattachment.
- Recover admitted system instructions through Runner-owned checkpoint
validation for the same run, session and context digest. Fresh launches
still compose current instructions.
- Make the attention-retention test advance past its database-assigned
deadline, fixing a clean-master clock mismatch.
- Serialize remote collection and cleanup across controllers with an
operation-scoped Postgres advisory lock; fence stale cache-path updates.
- Keep synthetic deployment probe tasks in a separate disposable company
so they cannot block the business completion oracle.
- Share the launcher's directory cleanup with rolling retirement. Reject
a symlink root and skip linked descendants.
- Test admission with real PostgreSQL transactions and cleanup with real
read-only directories and external symlinks.
- Update developer documentation and the canonical qualification record.
Broader deployment acceptance remains in progress.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed.
- All 156 workspace preparation, runtime selection and ephemeral
contract tests passed. Two new regressions failed before the source fix.
- Seven focused Product E2E cleanup/replacement tests and `pnpm
test:e2e:runner:typecheck` passed.
- `pnpm test:run` stopped at an unrelated 15-second chat integration
timeout after 338 passes. That exact test passed in isolation without
increasing its timeout. The later full-suite shards did not run.
- `pnpm test:e2e:runner:unit` reported 5,898 passes and 13 failures.
Clean master reproduced 11 failures in unchanged onboarding
expectations, operating receipts, Pi catalog assertions, workflow
bootstrap counts and embedded PostgreSQL startup. The other two workflow
assertions were fixed by the intervening master commit. These failures
are retained, not counted as passes.
- All 122 workspace-preparation tests pass after the reviewed
host-fallback fix. The first broader attempt exposed a test environment
leak; restoring the ephemeral flag between cases resolved it.
- Agent-directory and instruction regressions passed 179 tests. Five
focused cache-loss cases pass: different home, same path on an empty
filesystem, foreign lease, concurrent controller, and missing collector.
- The live fixture at `a18f6b85a3` gracefully stopped A and deleted its
entire home, then failed the 420-second remote reattachment deadline on
the saved local agent-directory path. That failure is retained; exact
owned sandbox cleanup was independently confirmed. The next live attempt
at `e14ca5f3e9` restored the cache and transferred the same runner, but
failed while rematerializing launch assets from A. Both failures are
retained and their owned sandboxes confirmed absent. No active-overlap,
ten-deploy, or production-canary acceptance is claimed.
- All 71 related Runner adoption/recovery cases pass, including the new
removed-context regression (failed before the source fix).
- The revised full agent-directory suite passed 110 cases and failed
three cleanup timing cases. All 20 cleanup/cache-loss cases then passed
in isolation with unchanged timeouts, including over-quota recovery.
- Server and Runner TypeScript checks pass after the latest corrections;
the live retry remains pending.

- The live test at `67714af9ff` adopted the same remote execution after
A was deleted, then failed while the full backend read the retired
instruction bundle. All owned sandboxes were independently confirmed
absent. Its regression now passes with actual backend recovery and no
new thread or turn. All 59 backend factory tests and focused checkpoint
identity tests pass. Runner and server TypeScript checks pass; the exact
committed server build passes. A fresh paid-model retry followed.
- The attention-retention CI timeout reproduced on clean master. The
deadline correction passes all 53 tests in that file with unchanged
timeouts.

- The real `cd690de4d3` run transferred the same runner/session after
deleting A, completed, and completed the next revision. During handoff,
372 reads and 38 saves had zero failures; all 38 saves were verified.
The full attempt was interrupted because the probe's open task
contaminated the business company oracle. This remains incomplete
evidence. The scope regression fails before the fixture fix, then
passes; all nine deployment support tests and E2E typecheck pass. All
three owned sandboxes were confirmed absent and temporary
credentials/storage were cleaned up. A clean corrected attempt is
running.

## Risks

- The runtime guard must still reject legacy and per-turn execution
before dispatch. Tests cover these refusals and a valid resolved warm
policy.
- Directory permission changes apply only during cleanup of stopped,
test-owned homes. Traversal does not follow symlinks. This changes no
production cache permissions.
- Cache reconstruction must not change remote execution authority or
rebase the original save baseline. Tests verify foreign-lease rejection,
preserved receipts, and absence of local-to-remote upload.
- Postgres locking is scoped to active remote file work and adds no idle
polling; local/durable-server locking remains unchanged.
- No schema or public API changes. External conversation exemptions
remain unchanged.

## Model Used

OpenAI GPT-6 Codex, with reasoning, repository editing, shell execution
and live integration-test tools. The exact runtime model variant and
context-window size are not exposed in this session.

## Checklist

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

Latest real qualification at f5915fdc33: both empty-home replacements
completed with 523 reads, 53 saves and 53 verified saves, zero probe
failures. The active remote execution survived and completed once; saved
project bytes and the later useful answer passed. The full workflow
remains FAILED: the later continuation reset its native/provider session
and the public run row lacked the native terminal contract. These newly
exposed compatibility/projection gaps are tracked in the next
implementation slice; this PR is not a claim of full Railway
qualification. All owned Daytona sandboxes were independently confirmed
absent after cleanup.

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 08:24:14 -06:00
Dotta e122478368 test(evals): run and record the chat completion pilot through TestOps (#18516)
## Thinking Path

> - Paperclip evals must verify real user outcomes.
> - A passing manual pilot does not make its cases runnable from
TestOps.
> - The existing TestOps adapter owns one separate backlog case.
> - The three-case completion pilot needs its own exact selection and
reporting path.
> - This workflow binds a real TestOps job run to reviewed catalog
source and AWS execution.
> - Results retain their original verdict, checks, source and private
evidence.

## Linked Issues or Issue Description

Refs #18364, #18377, #18515 and #18509. This is the main-side companion
to merged #18515. The immutable evaluated source is its actual
integration-branch squash merge,
`de0941835cc8f0d01c982574ee258e110babdbeb`; its tree matches the
reviewed catalog head. The host admission remains inert until this
main-only workflow exists. The broader catalog stays off master.

The existing TestOps connection can run only the separate backlog cell.
The project-work, project-defaults and instance-restart cases currently
require manual campaign dispatch and private retrieval. This change
creates a dedicated reusable TestOps plan and records fresh execution
outcomes there. Source checks and registration do not establish a new
live pass.

## What Changed

- Add a default-branch-only workflow with exact TestOps selection,
immutable source/build outputs, serial AWS execution and zero eval
retries. No source/model/budget selector is accepted.
- Register the three exact reusable cases and a separate plan with the
existing reviewed GitHub integration. Preserve opaque job definitions.
Validate the observed single Branch/defaultValue carrier, PATCH only
enable/integration, and use the job’s default branch without rewriting
its definition or adding plan overrides. Fence the initial operator
launch by actual GitHub run number and nonce; normal TestOps Run remains
repeatable.
- Reuse the existing private-evidence authority, scanners, bounds and
exact-key S3 policies. Authenticated selection supplies only this
original attempt's exact source and case identity. The three trusted
protocol files are unchanged.
- Skip report retrieval after an unsuccessful build or skipped
execution; retain evidence and failed grades when evaluation actually
ran.
- Check out trusted main after the target in both build and execution
jobs, and reject any target tree containing the reserved trusted-helper
path. A real temporary-Git-tree regression exercises the actual YAML
guard.
- Keep reporting credentials in separate protected jobs. Export only
closed verdict/check/accounting metadata and private-evidence receipts
to TestOps. Verify final PNGs privately and record their checksums; keep
all screenshot bytes in protected AWS storage and out of public GitHub
artifacts. Preserve failed grades and failed cleanup.
- Verify actual same-run case results and complete result-owned
attachment metadata within a fixed processing window. Missing or
inherited attachments never qualify. Keep source/result links and stable
case identities.

## Verification

- 68 dispatch, selection, registration and readback controls pass. A
checkout-boundary regression fails on the old ordering, accepts an
ordinary target and rejects a candidate-owned helper tree before trusted
checkout. They cover real workflow environment wiring, actual GitHub
metadata guards, exact subset selection, wrong sources/cases/jobs,
replays and attachment readiness.
- 38 exporter controls pass, including the existing backlog exporter and
the unchanged private-evidence authority consumer. Red/green controls
prove project work accepts the catalog’s 1–3 run range in both export
gates, while 0/4 runs are rejected; the actual pinned-source control
verifies all three cases’ run bounds. Cancelled, failed and scheduled
TestOps job stages are rejected even with complete results. The three
new cases retain all 35 independent checks; private diagnostics and all
image bytes are excluded from the public artifact. Extra media files and
directories are rejected.
- The actual checked-in workflow environment is exercised against the
actual pinned source matrix and host function for all three cases before
provider access. Local fixture controls make zero provider calls and do
not claim live AWS qualification.
- All 71 workflow-policy controls pass. Actionlint and owning typecheck
pass. Relevant TypeScript build dependencies pass.
- Full support suite: 5,827 passed, 13 failed, four skipped. A clean
unchanged-master baseline reproduces all 13 failures in the same five
files. They include fixture expectation drift, operating-receipt
fixtures, a profile pin, pnpm bootstrap counts and local database
startup. This change updates the exact TestOps workflow registries; the
two affected boundary controls now pass. Baseline failures remain
retained and are not presented as a green full support suite.
- The catalog dependency passed CI and current-head 5/5 review, has no
unresolved threads, and is merged. All current-head CI checks pass; both
Greptile and Paperclip reviews are 5/5, with no unresolved threads. No
new TestOps mutation, provider call or passing launch is claimed yet. A
fresh three-case TestOps launch and verified server-side results remain
the delivery gate.

## Risks

This is a paid execution and reporting boundary. The new workflow
accepts only trusted default-branch actor identities and a verified
project/plan/job/case selection. Its evaluated source is immutable and
separate from main reporting code. The full catalog is not promoted.
Screenshots, raw evidence and hidden provider data stay in protected
storage. Public GitHub artifacts carry only the closed metadata
projection. TestOps receives checks and private-evidence
availability/checksum receipts. Unknown setup or AWS accounting stays
unknown. One passing launch will not establish full-catalog reliability.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `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-11-01 06:09:47 -06:00
DottaandPaperclip 16787e4167 Qualify rolling web deployments and preserve Stop through handoff (#18526)
## Thinking Path

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

## Linked Issues or Issue Description

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

OpenAI Codex, GPT-6. Tool use, code execution and repository review. The
runtime does not expose a more specific model ID or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 02:53:27 -06:00
DottaandPaperclip 7e595fd055 test(e2e): verify native hiring, delegation and teammate reuse (#18351)
## Thinking Path

> - Paperclip manages real work by AI agents.
> - Daily QA must verify that work on the staging deployment.
> - Classic Agent Chat coverage already exercises hiring and teammate
reuse.
> - The deployment journey should share that behavior and its ownership
oracle.
> - Saved documents, exact callback replies and physical cleanup
establish success.
> - The corrected journey and complete daily suite now pass on QA.

## Linked Issues or Issue Description

**Subsystem affected**

Product E2E deployment journeys and their shared browser controls.

**Problem or motivation**

QA must prove that one newly hired teammate completes two different
tasks and returns both saved results to the lead conversation. Names,
chat claims and successful-run counts alone cannot establish authorship
or completion.

**Proposed solution**

Reuse the classic hiring oracle and production composer. Verify
immutable creation audits, initial assignment, current project and
ownership, saved document revisions, exact native authors, durable
callbacks and their own task links after reload. Bound execution to five
lead turns and two child turns.

**Alternatives considered**

A separate QA implementation would duplicate the classic journey. Name
matching or later reassignment would accept broken initial ownership.
Links elsewhere in the conversation cannot substitute for either
callback's own result link.

**Roadmap alignment**

This verifies existing features. Related merged repairs: #18389, #18465,
#18459, #18463, #18502, #18503, #18504, #18506, #18507 and #18514.
Separate dependency #18517 repairs file preservation after lifecycle
cancellation and is merged as Core `050365e`, which also contains
#18514. This primary PR now differs from that protected mainline in only
16 unchanged H harness/documentation paths; it adds no application
production delta. The measured QA deployment serves Core `050365e`, with
its matching bundled provider pack and unchanged approved model/ROM.

## What Changed

- Add the shared `hire-delegate-reuse` journey, catalog, types,
dispatch, launch fingerprints, journey-feature entries and
documentation. Hire one teammate, delegate a checklist, then reuse the
same teammate for a saved review. Require seven canonical native runs:
five lead and two child turns.
- Require exact company, lead, chat and native creation receipts. Both
tasks must be created for the intended teammate using immutable
creation-audit assignee fields. Independently verify current project and
ownership. Creation-time project is not recorded in that audit and is
not claimed by this assertion.
- Verify both current document revisions belong to the exact child runs
and preserve the original checklist.
- Use ordinary production rich-editor agent/project autocomplete
controls. Verify exact reference chips, then send once. Preserve the
shared default sender.
- Require each durable, run-owned callback reply to contain its own
exact completed-task link. Collect links through the actual production
Markdown renderer and issue-reference decoration, then apply the
existing company-scoped route authority. An unrelated table or code
fence cannot hide a rendered link; foreign, wrong-task and code-only
links remain failures.
- Preserve approved connection, account, grant and responsible-user
attribution. Verify the child's independent installation and retain the
immutable binding snapshot. Do not copy credentials or broaden grants.
- Record ownership before later observations can fail. Retry only typed
transient observation GET failures. Preserve authority and cleanup
failures.
- Retain all 14 daily journeys, the model matrix, deadlines, seven-run
cap and 500-cent aggregate allowance split 300/200.

## Verification

- **Current composed head:** `afa3f5552ab0c1a9f0ee7327dfa5665d57cc7bcb`.
It normally merges mainline `1e8e322` and exact #18517 source `adb1d4e`,
retaining the intermediate `b2d9eb4` and `6fd1042` ancestry. The only
merge conflict was the Playwright support registration; it is resolved
to the exact previously qualified union. All 16 H harness/documentation
paths are byte-identical to `5c0830f`; all four #18517 paths are
byte-identical to `adb1d4e`. Every other tracked path matches actual
protected mainline `050365e`. A clean merge preview of `050365e` and
this head equals the current head tree, so no additional source commit
is needed. GitHub's three-dot display still lists the four already
merged helper files because #18517 used a squash merge; those blobs
equal protected mainline and add no net application change. No journey,
oracle, cap or model change accompanies this composition. A final clean
merge preview on intervening mainline
`006d5691a6245d5a710e25ba3df6d609754e163a` preserves all unrelated
changes and adds exactly the same 16 measured H blobs, with no net App
production delta. That later mainline is not represented as the AppCore
measured by the QA run.
- **Local qualification:** 149/149 focused tests across six suites,
including the report-catalog case, and 11/11 real Chromium checks passed
on `b2d9eb4`. All H modules, browser inputs and parser/package
dependencies are byte-identical at `afa3f55`; those unchanged suites
were not repeated. Current-source transitive types, maps, module
boundaries and diff checks pass. Official Node24 QA runtime imports pass
again using exact public `afa3f55` and private `8671fa9`, with a clean
credential-free environment and network disabled. The initial local
report-catalog failure is retained: the child `tsx` process was denied
its local IPC socket before importing the report or writing an artifact.
The same source and selected case pass after correcting only sandbox IPC
permission; no source workaround or deselection was used.
- **Current canonical CI and reviews pass.** [CI
41275109691](https://github.com/paperclipai/paperclip/actions/runs/41275109691)
completed successfully at exact `afa3f55`: all 59 contexts are terminal
and clean (55 success, three skipped, one neutral). Fresh exact-head
Greptile and official Paperclip reviews both scored 5/5; all 27 review
threads are resolved with pagination complete. The official review is
static and its check is neutral; it did not execute tests or live QA. A
separate exact-head independent composition assessment found no
actionable issues at 4/5 confidence and performed no live actions.
**Fresh QA qualification passed: all 14 daily journeys, including the
corrected H7, passed against deployed Core `050365e`.** Prior check
conclusions and review scores retain their actual heads. The previous
`5c0830f` completed all 59 contexts cleanly, actual exact-head Greptile
and official Paperclip reviews both scored 5/5, and all 27 review
threads were resolved. Its separate independent journey-source review at
`2b803f08` remained 4/5 with a unit-helper authorship caveat.
Intermediate `b2d9eb4` received an actual exact-head Greptile 5/5 with
zero open findings, then was updated to compose the valid dependency
review fix before live QA. That score and its pending CI are not
attributed to `afa3f55`.
- Existing causal controls remain unchanged: invalid immutable assignee,
either missing callback link, foreign/code/wrong-task links and an
earlier handoff fail against the relevant prior source. Renderer
controls prove that tables and fenced code elsewhere in a valid callback
do not hide its actual task link. Both composer and document-navigation
browser registrations remain present.
- #18503 merged after its actual QA document case passed four canonical
checks and five phases, positively established zero native work, and
completed cleanup. Its measured files are unchanged in this composition.
#18506 and #18507 merged after their own checks; their causal
worker-settlement controls remain intact.
- #18514 is merged as `1e8e322`. It reproduces the selected-task
metadata-only-project startup failure against deployed `756599e` and
passes 19 real-PostgreSQL selected controls after repair. Both direct
and assembled baseline controls fail before it. Real source, explicit
selection, policy and workspace-isolation guards remain enforced. It is
included in measured Core `050365e`; fresh H7 reached and completed both
delegated native tasks.
- #18517 initial source `6fd1042` passed 320/320 focused and sibling
Stop/recovery tests, including 20 preservation controls. Its actual
official review was 4/5 and found a valid follow-up: the new
live-controller guard should wait for actual lease expiry rather than
repeat locked checks every 30 seconds. Both an already-live lease and a
real under-lock renewal reproduce that issue against `6fd1042`.
Corrected source `adb1d4e` passes all 22 preservation controls and 124
directly affected tests across three suites, exact-head server
build/stamp, typecheck and structural checks. It defers before locking
and rechecks renewed expiry afterward, preserving the transactional
owner guard. The old score/failure and successful owner tests remain
attributed to their actual sources. Independent exact-head review of
`adb1d4e` found no actionable issues at 4/5 confidence. This is
local/source evidence, not physical QA recovery. Its current [CI
41274963476](https://github.com/paperclipai/paperclip/actions/runs/41274963476)
completed successfully with all 59 contexts clean; both actual current
reviews are 5/5 with zero unresolved threads. It merged normally as
`050365e` after those gates. QA now runs that image. The historical
allocation is positively stopped and retained; its files-only export
remains a separately tracked repair, not a passing-test assertion.
- The historical [first H7
pass](https://pages.paperclip.ing/evals-qa-smoke-41226065043-1/) remains
attributed to public `5d3f143`, private `dabad62` and App `b7f1c37`: all
checks and five phases passed, seven native runs succeeded, both saved
documents and exact callbacks were verified, and physical cleanup
completed. An optional runtime-metadata receipt was inconclusive and was
not grade authority.

Material failed attempts remain failed:

| Attempt | Actual result and correction |
| --- | --- |
|
[41231853638](https://pages.paperclip.ing/evals-qa-smoke-41231853638-1/)
| 13 passed; hiring omitted initial teammate/project assignment and
started extra work. The production composer repair retains the ownership
negative. Later recovery stopped physical work without changing the
failed grade. |
|
[41238711372](https://pages.paperclip.ing/evals-qa-smoke-41238711372-1/)
| All seven native runs succeeded, but the final callback had no durable
chat reply. Cleanup passed. #18502 repairs premature completion-outbox
retargeting; the fresh measured H7 now verifies both durable, run-owned
callback replies and their own task links. |
|
[41253428446](https://pages.paperclip.ing/evals-qa-smoke-41253428446-1/)
| 12 passed; hiring rejected a mentioned metadata-only project before
delegation, and document reopening hit an immediate-control-probe race.
#18504 and #18503 repair those separate boundaries. Historical
missing-task absence remains quarantined; physical termination does not
manufacture absence evidence. |
|
[41266385118](https://pages.paperclip.ing/evals-qa-smoke-41266385118-1/)
| On `5c0830f` and App `756599e`, 13 passed, including the exact
composed document helper. Hiring created the correctly assigned task,
but its child admission failed before runtime selection because the
organizational project had no repository source. #18514 repairs that
selected-task boundary. The cancelled native lead retained an active
prepared-workspace lease; cleanup 41271035231 failed with
`owned_work_stop_unconfirmed`. #18517 addresses its file-preservation
admission. Launch 1110, original evidence and automatic Slack FAIL
remain failed. |
| [CI
41257779002](https://github.com/paperclipai/paperclip/actions/runs/41257779002)
/ [CI
41263476916](https://github.com/paperclipai/paperclip/actions/runs/41263476916)
| Existing enrollment and snapshot-retention fixtures observed
intermediate I/O before worker settlement. #18506 and #18507 have
controlled causal failures, complete-settlement observers and preserved
deadlines/negative controls. Runtime scheduling behavior is unchanged. |

**Fresh measured acceptance:** [QA run
41285131220](https://github.com/paperclipai/paperclip-cloud/actions/runs/41285131220)
and its [permanent
report](https://pages.paperclip.ing/evals-qa-smoke-41285131220-1/)
passed **14/14**, zero failed or incomplete, with all five phases and
complete cleanup for every case. The strict verifier independently
matched original grades, current provenance and completed manifests:
public harness `afa3f5552ab0c1a9f0ee7327dfa5665d57cc7bcb`, private
workflow `8671fa93e27501fabbfffa377bec6dea453b5db7`, AppCore
`050365e09d88411960fc3bacc1c08c46c0d9b6fa` and matching Cloud
image/provider pack. All model, ROM, deadline and run-budget controls
remained unchanged. All three workflow jobs completed successfully; the
automatic Slack notification reported PASS with links to this run. The
passing TestOps launch was closed normally after evidence verification.

The hiring case passed all 11 check entries across nine IDs and five
phases, with exactly five lead and two child native runs. Both saved
documents match their live current revision/body hashes and exact
hired-agent run attribution. The immutable original checklist remains
intact; the same teammate authored the review. Both own callback replies
contain their exact delegated task link. Independent canonical readback
confirmed all seven native runs succeeded and committed their accepted
result, assessment and decision, with no live owner and zero pending or
failed effects; each of the seven exact owned leases has its own bound
DESTROYED receipt and successful cleanup. All seven final snapshot
operations match their source run, workspace, task, epoch, SHA,
generation and export location. The four earlier lead snapshots are
retained SUPERSEDED ancestors of the current committed snapshot; the
latest lead and both child snapshots are COMMITTED. The initial
diagnostic required current COMMITTED status for every historical
snapshot and correctly remained false until the separate lineage
diagnostic established this supported supersession. The product oracle
and original grade were not changed. Canonical Suite metadata is
`qa-basics`; the daily plan was saved with its standard suite-only query
and synchronized, retaining all 14 ACTIVE cases.

The older failed allocation remains separately stopped, retained,
isolated from reuse and owned by terminated actors. That permits fresh
campaigns without replaying old work. Its same-allocation files export
is still unresolved and has separate bounded files-only recovery work;
it is not claimed by this successful campaign. Original failed grades,
reports and automatic FAIL notifications remain unchanged. No failed
result was closed, relabelled, hidden or retried unchanged to obtain
green.

## Risks

The journey requires Agent Chat, normal hiring permission, a scoped lead
and a provider that finalizes owned resources. Missing or extra work,
wrong ownership, absent saved documents, missing callbacks and
unconfirmed cleanup must fail.

The deployed app and bundled runner pack must match the verified Core.
The old run's cancellation ACK and terminal database row do not prove
physical termination or saved files. Its coordinator has no accepted
result or decision; pending-effect absence cannot be inferred from that
missing decision. File recovery must preserve the exact allocation and
original destroy disposition without a provider turn.

Current source checks, reviews, fresh H7 and full-14 aggregate all pass.
Canonical Suite metadata and actual 14-case daily-plan synchronization
were verified after closing the genuine passing launch. The original
failed allocation still has a separate files-export debt; its STOPPED
receipt is not a SAVED or DESTROYED claim.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
- [x] Historical passes and material failed attempts retain their actual
source and outcome
- [x] The composed document helper passed normal QA with complete
cleanup on its actual source
- [x] The corrected hiring journey passes fresh normal H7 with complete
cleanup
- [x] The active hiring case has canonical Suite and daily-plan
membership after the passing launch is closed

---------

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

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

## Linked Issues or Issue Description

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

**Current behavior**

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

**Proposed behavior**

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

**Reason and benefit**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-01 01:58:54 -06:00
DottaandPaperclip f0ff466aaf fix(testops): wait for complete attachment evidence (#18509)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Product E2E evaluations check real user requests and their saved
results.
> - The TestOps reporter also verifies the uploaded result and
attachment evidence.
> - One failed attachment-row snapshot stopped the reader before its
existing observation allowance.
> - A later read with the same protected credential reference verified
the original result. The original failed subfield remains unknown.
> - This pull request handles attachment readiness within the existing
bound while preserving the complete final evidence predicate.
> - The reporter can wait for complete evidence without accepting
missing, inherited, or incorrect files.

## Linked Issues or Issue Description

Refs #18477 and #18470.

**What happened?**

The chat case passed its ten checks and cleanup in [run
41217990335](https://github.com/paperclipai/paperclip/actions/runs/41217990335),
but the final reader failed at `attachment_page / attachment_rows`. The
unchanged reader later verified that same retained result through the
protected reporting identity in [read-only run
41268693639](https://github.com/paperclipai/paperclip/actions/runs/41268693639).
This proves the observed snapshot differs. It does not identify which
original row subfield failed or prove an upload race.

The reader already permits twelve polls and 120 seconds for complete
result and attachment metadata. It nevertheless rejects `missed ===
true` immediately. That flag cannot satisfy complete evidence, but it
can be observed again within the existing allowance.

**Expected behavior**

Wait within the original limit for attachment evidence to become
complete. Accept only the same full source, case, status, cleanup,
attachment-name, media-type, byte-count, and non-missed predicate.
Reject malformed IDs and inherited rows immediately. Permanent missing
or incorrect evidence must still fail.

**Steps to reproduce**

1. Call the real verifier with otherwise valid responses and one
`missed: true` attachment.
2. Return the complete attachment on the second poll.
3. The old reader fails on the first snapshot. The regression now
reaches the original complete acceptance predicate on the second
snapshot.

**Paperclip version/commit**

Base `987e0932bf66e703750cd04698b3c7e8993580a7`.

**Deployment mode**

TestOps reporting observer after a Product E2E evaluation. This change
starts no model or app and changes no feature oracle.

## What Changed

- Move the strict `missed === true` condition from immediate structural
rejection into bounded readiness.
- Keep page shape, counts, unique positive IDs, inherited-row rejection,
and every source and case guard hard.
- Require the same complete final signature and status before success.
Keep twelve polls, five-second intervals, the 120-second deadline, and
request limits.
- Retain closed per-poll counts and readiness booleans on verification
and unverified failure. Clone failure observations so callers cannot
change retained diagnostics.
- Add seven focused regression and negative controls. Sync one existing
consumer test with the precise new failure phase and predicate.

## Verification

- Genuine parent RED: the real missed-then-complete verifier test failed
at the original attachment-row guard.
- API owner tests: 60 passed. Direct CLI, exporter, reporter, and
retained-reader consumer tests: 31 passed. Node 26.4.0.
- Permanent missing evidence reaches twelve polls and eleven waits, then
fails. An elapsed 120-second deadline stops after the first page.
Malformed IDs and inherited rows still fail immediately. Incorrect byte
counts never pass. Closed diagnostics exclude private fields and return
detached observation copies.
- Three Node syntax checks and `git diff --check` passed.
- Two review reproductions failed on the first PR head: a null row lost
its controlled invalid-ID error, and a final-GET deadline crossing lost
its exact readiness predicate. The corrected head preserves both
diagnostics. Null rows still fail immediately; no deadline or acceptance
condition changed.
- No local app, database, provider, native build, or new evaluation ran.
The MJS change needs no TypeScript emission.
- [Normal CI
41269715187](https://github.com/paperclipai/paperclip/actions/runs/41269715187)
passed on exact head `4e77c1220b0ba81e971591c1c7d28f9064e992cc`: 55
successes, three skipped checks, and one neutral review. Both required
checks passed. Greptile is 5/5 and review threads are resolved.
- The controlled normal TestOps-launched confirmation is pending merge.
The family unit roster runs the local controls; normal PR CI uses
separate runner suites, so CI green alone does not claim that roster ran
there.

## Risks

- A missed file may remain missing. The observer fails if complete
evidence does not arrive inside the original allowance.
- This is readiness handling, not a claim that `missed` caused the
historical failure. Prior passed case grades and failed reporting
workflows remain retained.
- The previous fixed retained diagnostic intentionally pins the original
helper. Its completed receipt remains valid; after this helper changes,
that old diagnostic fails closed instead of silently replaying a
different observer.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with reasoning, code editing, shell
tools, and independent source review. The host does not expose the
context window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 22:54:28 -05:00
DottaandPaperclip 9dbbfa4fb2 fix(qa): wait for task document controls after reload (#18503)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task documents keep saved work and its revision history with each
task.
> - The browser document journey must reopen the saved task and read the
revised document after reload.
> - Reload can finish before the task controls mount.
> - The helper checked visibility once and could wait for a tab launcher
inside a panel it had never opened.
> - This pull request waits for the existing usable controls before it
selects the normal UI path.
> - The saved content, revision, ownership and no-agent-work checks stay
unchanged.

## Linked Issues or Issue Description

Refs: #18356.

**What happened?**

The document case in QA run 41253428446 passed document creation and
revision-history checks, then failed during reopen or readback. The
preserved screen shows the revised document and revision 2 in chat. The
original result has the generic `journey_operation_failed` code. Its
exception stack was intentionally excluded, so the exact historical
failing instruction is not known.

A separate Chromium control reproduces a concrete navigation race in the
same helper. If task controls mount 200 ms after reload, the helper can
select `Open a new tab` before it opens the properties panel. That
control never becomes visible. The same race affects a delayed classic
document editor or an existing Artifacts tab.

**Expected behavior**

The helper waits for the current task's normal authoring or panel
controls. It then opens Artifacts through the same visible controls. A
task without document authoring must still fail. A stale body, stale
title or damaged revision history must still fail.

**Steps to reproduce**

1. Open a task from the Backlog list and reload it.
2. Delay mounting the task controls by 200 ms.
3. Run the unchanged document reopen helper with its properties panel
closed.
4. Observe that it waits for `Open a new tab` while `Show properties` is
visible.

**Paperclip version or commit**

Frozen source base: `b889ac39b7fbed558c5f4cfbbc2b73c4ca916810`. No
duplicate document reopen PR was found. The related document feature is
#18356.

## What Changed

- Wait for an existing authoring, properties, Artifacts or launcher
control before choosing the navigation path.
- Wait for usable panel content after opening properties.
- Add five credential-free Chromium controls for delayed collapsed,
Artifacts, launcher and classic layouts, plus missing-authoring
rejection.
- Keep the existing Backlog navigation test compatible with the new
readiness probes.
- Register the browser regression in the existing support suite. No
product code, model, budget, run cap or campaign deadline changed. The
existing document contract needs no documentation change.

## Verification

- Original failure is preserved. The [sanitized QA
report](https://pages.paperclip.ing/evals-qa-smoke-41253428446-1/)
records both partial checks and the failed journey. This PR does not
change that grade.
- Before the fix, the real Chromium control failed for delayed
collapsed, Artifacts and classic controls. The launcher path and
missing-authoring rejection passed. A 750 ms action timeout bounded this
diagnostic; final tests use the existing suite timeouts.
- Final Chromium: `node node_modules/@playwright/test/cli.js test
--config tests/runner-e2e/playwright-support.config.ts
task-document-navigation.spec.ts` — 5 passed.
- Document units: `node node_modules/vitest/vitest.mjs run --config
tests/runner-e2e/vitest.config.ts
tests/runner-e2e/product-journeys/task-document-flow.test.ts
tests/runner-e2e/product-journeys/task-document-evidence.test.ts
--maxWorkers 1` — 23 passed. This includes 19 negative content,
ownership and revision controls.
- Scoped strict TypeScript, map checks, token gates and diff checks
passed.
- Node 24 normal QA import preflight passed with network disabled.
- The entire `taskDocumentPersistence` function and the canonical
evidence module are byte-identical to the base. The existing exact
title/body checks, independent API reads, revision pointers and
no-agent-work checks remain in force.
- Repository-wide build, typecheck and tests were not run locally for
this four-file harness change. [Canonical CI
41255897484](https://github.com/paperclipai/paperclip/actions/runs/41255897484)
passed on exact head `ffc04500cb0728f6fbc8b3bc2e704c547015641d`: all 59
checks are terminal (55 success, 3 skipped, 1 neutral), with no failed
or pending checks. Greptile and Paperclip each gave this head 5/5 with
no findings. All review threads were checked; none are open and there is
no next page. The branch is CLEAN and MERGEABLE.
- Actual QA measurement now passes in [workflow
41266385118](https://github.com/paperclipai/paperclip-cloud/actions/runs/41266385118),
campaign `journey-1793502283113-8f658807`. The measured harness
`5c0830f693da2ccef062612146b76629a0177049` contains the three exact
reviewed document source/test blobs and unchanged canonical evidence
module from this head. The target was the QA cloud instance on App
`756599e4ea069c9338c320fe8846523d3dfb92a0`. All four canonical checks
and all five phases passed; the manifest is COMPLETE with evidence
cleanup complete and nothing pending. A positive no-agent-work check
establishes zero native work despite omitted raw run IDs. A separate
read-only verifier reread the exact original final grade and confirmed
the retained-result validator. Raw document snapshots were not retained;
content, revision and author proof comes from the executed unchanged
exact UI/API predicates. The full 14-case launch remains failed because
hiring failed separately; no aggregate pass is claimed.

## Risks

The historical exception was intentionally sanitized. The local control
proves this helper race, but cannot prove which instruction failed in
the prior QA attempt. The current staging measurement passes this
document case; the exact historical failing instruction remains
unproven. The new readiness waits use the existing assertion timeout and
campaign deadline. They do not accept missing controls or weaken
document evidence.

## Model Used

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

## Checklist

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

Live qualification: the document case is verified on QA with complete
cleanup. Historical failed results remain unchanged.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 22:30:05 -05:00
DottaandPaperclip 987e0932bf test(testops): inspect a fixed retained chat result (#18477)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The chat feature evaluation checks a real task request on AWS.
> - The case passed, but its final TestOps reader rejected attachment
metadata.
> - The later browser view passes the same check. It uses a different
identity and time.
> - Another model run cannot explain that difference.
> - This pull request adds a fixed read-only check of the retained
measurement with the reporting API identity.
> - The check separates its own executor from the original measurement
and preserves the original grade.

## Linked Issues or Issue Description

Refs #18470 and #18462.

**What happened?**

The real chat case passed all ten checks and cleanup in [run
41217990335](https://github.com/paperclipai/paperclip/actions/runs/41217990335).
Final verification failed at `attachment_page / attachment_rows`. The
reader had already accepted the source, run, case, status, page counts,
and unique attachment IDs. Later interactive metadata had valid IDs and
false attachment flags. That later view does not explain the original
API caller failure.

**Expected behavior**

A read-only operation can inspect the same retained result with the
existing protected reporting identity. It must report the exact current
attachment flags without running a model, uploading results, or changing
the original grade.

**Steps to reproduce**

1. Read the closed failure from the linked evaluation run.
2. After this workflow is reviewed and deployed, dispatch its fixed
no-input operation on master.
3. Inspect its closed receipt. It records both the new executor and the
original measurement.

**Paperclip version/commit**

The retained measurement used
`e40de0c9e88210dc476dcf651461c0a8d1b98a59`.

**Deployment mode**

GitHub Actions metadata job with the existing protected reporting
environment. No app, database, provider, or AWS worker starts.

## What Changed

- Add one manual no-input workflow for the fixed retained measurement.
- Admit the live executor and the original run separately. Verify exact
selection and sanitized export artifact hashes before TestOps
authentication.
- Read only the five existing TestOps metadata routes with the existing
client. Its normal API-token session exchange is the only authentication
POST.
- Record closed per-row attachment types and flags. Replay the unchanged
verifier against the captured responses using historical context as
data. Keep the actual process environment unchanged.
- Add nine mock and archive-safety tests to the existing Node unit
roster.

## Verification

- `node --test
tests/runner-e2e/chat-feature-testops-retained-verification.node-test.mjs`:
9 passed on Node 26.4.0.
- Three Node syntax checks, actionlint, the relevant workflow policy
check, and `git diff --check` passed.
- The real pinned sanitized export ZIP passes the new safe-export
extractor and existing bound reader. The first local attempt used a
noncanonical `/var` temporary path and hit the existing canonical-path
guard; the canonical `/private/tmp` attempt passed without a source
change.
- Corrected a review finding in failure attribution. Only actual
authentication or protected GET errors now receive `apiFailure`.
Historical replay failures retain their original phase and predicate
diagnostics.
- Initial test run: eight passed and one test expected the generic
upload error instead of the existing specific job-run error. Corrected
that test expectation. No verifier behavior changed.
- Tests exercise separate identities, foreign source and actor
rejection, origin and artifact integrity, exact five GETs, all three
attachment-row refusals, secret redaction, wrong job/run/source, and
real archive traversal/symlink rejection.
- The unchanged API and export readers are source-pinned. Existing
evaluation and acceptance code is unchanged.
- [Normal CI
41220476243](https://github.com/paperclipai/paperclip/actions/runs/41220476243)
passed on exact head `b79e85f71567f662d6f3d680ec66ec49a132589a`: 55
successes, three skipped checks, and two neutral reviews. Both required
checks passed. Greptile is 5/5 and all review threads are resolved.
- The nine new controls are registered in the family unit command. The
separate normal PR-CI runner suites do not execute that roster, so their
green status is not proof these nine ran on Node 24. The manual workflow
explicitly runs them on Node 24 before any protected API read.
- The real protected API operation has not run. A separately approved
merge and metadata dispatch remain required. No model, app, database, or
native build ran locally.

## Risks

- The fixed artifacts can expire. Any absent or changed artifact fails
before TestOps authentication.
- The current protected response snapshot may differ from the original
failure-time state. The receipt states that limit and makes no
historical cause claim.
- This is a fixed diagnostic operation. It does not repair the original
workflow or grant authority to run another evaluation.
- The workflow uses the existing protected reporting token. It logs no
response body, unknown field, credential, or unknown URL. Only closed
receipts are retained.

## Model Used

OpenAI `gpt-6.1-sol`, through Codex, with reasoning, code editing, shell
tools, and source review. The host does not expose the context window
size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 22:16:20 -05:00
DottaandPaperclip d38cdf261a perf(ui): speed up Tasks and Inbox startup (#18492)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tasks and Inbox are the main entry points for that work.
> - Earlier changes made their data reads and row counts smaller.
> - Those changes remain, but shared controls now pull in the whole
task-detail bundle.
> - A cold open can also read a remembered organization before selecting
the one in the URL.
> - This pull request separates collection code and selects the
addressed organization first.
> - It warms task code after collection paint, so the next task open
stays fast.

## Linked Issues or Issue Description

Refs #17756, #18323, #16849, #17041, #17983, #17960, #18461.

**What happened?**

Tasks and Inbox still use their optimized index reads and row budgets.
However, small shared controls and hooks were placed in the task-detail
chunk. A collection had to download that whole chunk. The HTML also
preloaded it on every route. The original production profile loaded
about 6.5 MB of decoded JavaScript before useful rows, or 1.9 MB
transferred with compression.

Company bootstrap could select a different remembered organization
before Layout selected the URL's organization. This started unnecessary
company reads. A retained multi-company browser fixture reproduced two
attention-count requests for different companies.

**Expected behavior**

Show correctly scoped, stable collection rows without waiting for
task-detail code. Keep compact reads, bounded rendering, direct task
preloading, immediate New Task input, and fast follow-on navigation.

**Steps to reproduce**

1. Use a production UI build with Coordinator enabled and two active
organizations.
2. Remember one organization, then cold-open Tasks or Mine in the other.
3. Inspect startup script and company requests before the first useful
row.

The baseline UI revision is `91fdf02e95`. This is a UI change. It has no
API, schema, migration, or authorization changes.

## What Changed

- Group the static collection dependency trees above the task-detail
group. Keep the existing startup and task grouping strategy.
- Preload task detail and its static dependency closure early on direct
task and agent-chat URLs. Keep collection aliases out of that preload.
- Fetch the immutable task chunk at low priority after a collection
paints, or on a same-origin task-link hint. After a successful immutable
response is fully read, module-preload the cached chunk so it can
compile without executing. A failed HTTP probe skips module preload.
- Prefer an addressed active organization during bootstrap. Preserve
manual selection, archived-company handling, and account-scoped company
lists.
- Preserve a task reading anchor when a programmatic scroll event
reports an unchanged offset during restore reflow. Strengthen the Back
journey to wait for a completed collection navigation.
- Add production-browser checks for delayed indexes, correct company
scope, stable row geometry, failed speculation, and early direct-task
preload. Update collection verification notes and the feature map.

## Verification

Final source: `e402ab7fc6`; baseline UI: `91fdf02e95`.

- All **234 focused unit cases** and **44 production-browser journeys**
passed on the final source: 33 task journeys and 11 collection journeys.
Coverage includes compact history, saved cards, draft persistence,
avatar continuity, failed-probe recovery, delayed data, pagination, deep
links, desktop/mobile and reading-position restoration through Back.
Desktop and mobile screenshots were inspected.
- Workspace typecheck, full production build, map checks, token gates
and diff checks passed. The default local `pnpm test:run` still stops
before executing tests because the existing chat-test line selector
reports `No test found` (1,816 skipped). This is not a passed full local
test suite. Focused tests and remote CI remain separate evidence.
- Greptile reviewed the exact final commit at **5/5**, with zero open
review threads. Final code CI passed. The complete check inventory is
**55 successful, 3 skipped, 1 neutral**. The neutral result is the
separate Paperclip Review: its agent finished without completing an
assessment, so it is not a passing review score.

Five alternating baseline/candidate pairs per scenario, Chromium
151.0.7922.34, 1440×900, 4× CPU, 50ms latency, approximately 9Mbps down
/ 1.5Mbps up. Cold cases use fresh browser contexts with normal cache
writes enabled; warm cases use the same context and normal application
query cache. Both previews use the server's immutable hashed-asset cache
policy and uncached HTML, with real local feature settings and no
request interception. All task-owned builds and suites were stopped
during timing; other host activity was uncontrolled. Readiness requires
useful rows and editable search, or the readable task thread and
editable composer, followed by two animation frames.

| Journey | Baseline median (range) | PR median (range) | Median paired
saving |
| --- | --- | --- | --- |
| Cold Tasks | 3239 ms (3189–3333) | 2545 ms (2441–2682) | +752 ms |
| Cold Inbox | 3207 ms (3203–3268) | 2679 ms (2502–3062) | +541 ms |
| Warm Inbox | 717 ms (701–917) | 760 ms (745–768) | -47 ms |
| Warm Tasks | 1150 ms (1126–1207) | 1136 ms (1119–1174) | +18 ms |
| First task click | 943 ms (932–1008) | 1007 ms (976–1098) | -74 ms |
| Back to Tasks | 584 ms (568–617) | 566 ms (559–575) | +10 ms |
| Cold direct task control | 3389 ms (3377–3402) | 3415 ms (3395–3896) |
-13 ms |

All five pairs improved for each cold collection. The signed saving is
baseline minus candidate for each pair; it is distinct from the
difference of medians. Warm navigation is broadly similar. First task
click was 74ms slower by median paired difference. Direct-task median
paired difference was 13ms slower, with one slower 3.90s candidate
sample retained in the range; this is not a claimed direct-task speedup.

Completed script transfers by collection readiness fell from about
**1.91MB to 1.14MB** (Tasks), and **1.90MB to 1.14MB** (Inbox). Task
code warms after rows paint. At the test bandwidth, the removed 0.77MB
critical transfer represents roughly 0.65s of download time; CPU and
network overlap, so their savings are not added. Unthrottled loopback
API control medians stayed about 17–18ms in both variants. All 30 cold
samples had zero browser errors.

Rejected experiments remain separate: automatic splitting produced over
200 startup requests; disabling recursive grouping slowed direct tasks;
HTTP-only warming improved collection startup but slowed first task
opens. The final correction preloads direct dependencies and compiles
successfully cached code after paint. Routing disables HTTP caching, so
intercepted runs were kept as diagnostic evidence rather than used for
warm-cache acceptance; see [Playwright's cache
behavior](https://playwright.dev/docs/api/class-page#page-route). Vite
preview's default asset `no-cache` policy was also corrected to match
the shipped server before final measurement.


## Risks

- Bundle placement affects shared consumers. Browser checks cover
collections and task navigation; the full PR checks also cover other
routes.
- Code warming still transfers the task chunk if the user stays on a
populated collection. It moves that download past first paint and does
not execute it. This is a startup latency improvement, not a claim that
all eventual bytes disappear.
- A direct click before warming finishes still loads code on demand.
Direct task and chat URLs retain early module preload.
- Local browser evidence does not establish a deployed staging speedup.
This PR does not merge or deploy itself.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, tool use and local code execution.
The context-window size is not exposed in this environment.

## Checklist

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

---------

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

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

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 14:54:01 -05:00
DottaandPaperclip 5bc029bf6c test: wait for native work and accounting before Stop redirect (#18463)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Product E2E journeys test the browser, native work and saved
outcomes on a selected deployment.
> - The Stop journey must interrupt real work before it sends a new
direction.
> - Its old boundary accepted a turn-start event before any command or
usage report.
> - A stopped attempt with incomplete usage correctly blocks later work
under the existing budget policy.
> - This pull request waits for a live native command and bound usage,
then checks actual accounting settlement before it sends the redirect.
> - The provider reports first usage after its initial command
completes, so the fixture finishes a harmless readiness call before the
long interruptible hold.
> - The benefit is a stronger test of Stop and continuation with the
same three-run limit.

## Linked Issues or Issue Description

Refs: #18098, #18345, #18354. Related accounting work: #18035.
Integrated upstream prerequisites: #18387, #18465 and #18409. Duplicate
selector PR #18472 was closed as superseded by actual merged #18409.

**What happened?**

A QA attempt clicked Stop soon after a native turn started. The owned
event stream had no command or usage report. Its cancelled run retained
incomplete accounting. The saved redirect received a skipped wake, and
no third run started. The budget guard must keep that missing usage
visible.

**Expected behavior**

The journey must first prove that actual native work is active and that
its current turn has reported complete usage. The fixture must finish a
harmless readiness command before it starts a separate bounded hold.
After Stop and physical cleanup, it must verify a complete accounting
receipt and saved settlement before sending the redirect.

**Steps to reproduce**

The fresh staging attempt failed before Stop because its first 90-second
command ended before the provider emitted its first complete usage. Its
only later eligible commands lasted less than one second. The controlled
browser sequence reproduces that ordering without accepting it.
Completed readiness usage followed by a separate still-active hold
qualifies under the unchanged oracle. Startup alone, command alone,
usage alone, partial usage, incomplete accounting and a missing
settlement timestamp still hold the next action.

## What Changed

- Request a harmless `printf` readiness command first. Wait for its
result, then request `sleep 90` exactly once in a separate shell call
before file edits. This gives the provider an opportunity to emit
current-turn usage before the interruptible hold.
- Reuse the strict native-command observer. Require a bound current-turn
complete usage report with valid nonzero token counts. Reject stale,
partial, foreign and semantic-tool evidence.
- Wait for the stopped run's complete accounting receipt,
`accountingReceiptReady: true`, `costAccountingPending: false` and a
valid saved settlement time before redirecting. A receipt already ready
before Stop is intentional only when the exact cancelled run is actually
accounted with no pending debt; no source/sequence advance or callback
clock order is assumed.
- Exclude canonical raw, partial and complete `item.completed` usage
only when the API row and PRP envelope match the authoritative owned
run, company and agent, and their source event ID, instance ID and
positive sequence agree. Missing context keeps the strict work check. A
self-consistent accounting source can change after Stop. Keep the
original snapshot and reject real tools, turns, messages and other item
events, including productive output from a new source.
- Retain private boundary and accounting proof. Source and sequence
observations do not impose unsupported controller or clock order.
Include the new oracle in the suite definition hash. Keep existing
success-check IDs, exact three runs, model, budget, deadline, Stop proof
and final outcome checks.
- Reuse one binding validator in the active-work boundary and post-Stop
filter. Pre-Stop keeps its current Runner/current-turn restriction. Add
focused evidence tests and a standalone Chromium/control-API sequence
check. The optional pre-Stop hook leaves existing classic callers
unchanged; they do not call the accounting filter.

## Verification

- Current source is `47578138ad357fc11b8b346bfada36d6aa5ab484`, one
narrow fixture commit on reviewed
`b9668ccfba61c59eb496ba18269aee06e2921d8f`. Only the prompt constant,
two ordering controls, the existing Chromium sequence and the journey
documentation changed. All oracle functions, run counts, model, budget,
deadline and check IDs are byte-identical to b966. There is no new
upstream merge or app change.
- Fresh staging failure is preserved in the [sanitized
report](https://pages.paperclip.ing/evals-qa-smoke-41227920892-1/). It
measured harness `5d3f143d0aed4dc7cf472b7891ea3d4d95ab843b` against app
`b7f1c3769c00a107ffe4128b48b0ef8cc452cf3f`; the reviewed Stop helpers
and its flow were unchanged in that harness. The original grade has
`stop_boundary_already_settled`, two succeeded native runs, and complete
cleanup. Authentication, setup, collection and cleanup passed; the
journey failed. This attempt remains failed.
- Causal timing evidence: the first shell command started at event108
and completed at111 about 90 seconds later. The first structured
complete current-turn usage arrived at113, after the hold ended.
Replaying the exact retained event metadata never qualifies that hold.
The only later eligible command intervals lasted about 0.90 and 0.18
seconds. The emitter publishes positive usage when the provider sends
its assistant-message usage update. The fixture now completes a harmless
first call before requesting the long hold; no usage is supplied or
invented by setup.
- On current source, all 137 focused tests and journey contracts passed.
Use `node node_modules/vitest/vitest.mjs run --config
tests/runner-e2e/vitest.config.ts
product-journeys/stop-redirect-evidence.test.ts
product-journeys/agent-evidence.test.ts
product-journeys/active-followup.test.ts native-event-envelope.test.ts
product-journeys/contracts.test.ts --maxWorkers 1`. New controls reject
every prefix when first usage arrives only after the hold completes.
They accept the same-turn sequence of completed readiness, genuine
complete usage and a separate active hold, and reject it after that hold
completes.
- Manual Chromium qualification passed: `node --import
./cli/node_modules/tsx/dist/loader.mjs
tests/runner-e2e/stop-redirect-boundary.browser.mjs`. The browser does
not click Stop for the failed ordering or completed readiness alone. It
clicks once for a separate active hold with bound usage. It sends one
redirect only after actual settlement. Foreign usage, productive output
and missing accounting still fail. This isolated control uses controlled
responses and does not call a model or the deployed app.
- Strict scoped TypeScript, maps, diff and secret checks passed. The
official credential-free Node24 QA runtime-import preflight passed
without network access. Full local E2E typing previously encountered old
borrowed workspace declarations; clean CI typecheck passed on b966. A
full local repository build/test was not repeated for this four-file
fixture change. Fresh canonical CI must supply the clean full gates.
- Historical binding proof remains valid: the exact old d499 filter
failed 17 of the final61 Stop tests. The shared validator checks
authoritative run/company/agent plus consistent row/envelope source
identity. Bound raw/partial/complete accounting is allowed after Stop,
including a consistent source change; productive output remains strict.
Pre-Stop still requires its current Runner and turn, complete nonzero
usage and a running command.
- Historical b966 CI `41224054720` passed all59 terminal checks, with
exact-head Greptile and Paperclip Review each5/5 and no open findings.
These are not approvals of current475. Current475 has fresh exact-head
Greptile5/5 and Paperclip Review5/5, with zero unresolved findings and
no omitted thread pages. Canonical CI
[`41229185200`](https://github.com/paperclipai/paperclip/actions/runs/41229185200)
passed on exact475. All59 checks are terminal:55 success,3 expected
skips and1 optional neutral review, with zero failed or pending checks.
No old job was retried. Fresh normal staging run41229965802 passed. Its
[sanitized
report](https://pages.paperclip.ing/evals-qa-smoke-41229965802-1/)
agrees with the independently read final original grade:11 checks, all5
phases, exactly3 native runs and cleanup passed. The final manifest is
complete, with cleanup complete and no pending evidence. Smoke, report
publication and Slack outcome jobs all succeeded.
- The live pass measured harness
`6be20bef6d0c5077adc1ae99562ad84e756ab167` against app
`b7f1c3769c00a107ffe4128b48b0ef8cc452cf3f`. Its Stop oracle, flow,
shared binding validator, unit cases and Chromium control are
byte-identical to reviewed475. The shared agent-flow file adds only the
hiring import and early hiring dispatch; all remaining bytes match. This
records the actual harness and app identities separately.
- Canonical run readback confirmed the first run succeeded, the second
was cancelled and the third succeeded. The cancelled run had a ready
native-producer accounting receipt, no pending accounting and a saved
settlement time. After verified file copyback, Core queued final
destruction and followed its normal five-minute cleanup backoff. The
exact lease naturally reached expired/cleanup-success with a bound
destroyed receipt before the third run started. No operator cleanup,
source change, timeout extension or workflow retry was used. The earlier
failed staging attempt remains failed.
- Current475 is ready for the normal reviewed merge and QA admission
process. Source stays frozen; merge and configuration changes belong to
that process.

## Risks

- Some provider profiles may not expose a valid current-turn usage
report while the command runs. The stronger boundary fails closed in
that case.
- Accounting may remain incomplete after Stop. The redirect stays unsent
within the original deadline. This change does not waive missing debt,
treat it as zero, raise a budget or change provider behavior.
- This repairs the test boundary. It does not prove or repair a general
provider shutdown-usage issue. A separate local late-usage ordering
control is not attributed to this QA incident.

## Model Used

- OpenAI Codex, GPT-6 family. The exact deployment variant and
context-window size are not exposed in this session. Used code
reasoning, repository tools, test execution and browser automation.

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

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

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

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

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, source inspection, browser
testing, and code execution. The host does not expose the exact
underlying model version or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with available version and
capability details
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
related work above
- [x] I have described the issue in-PR following the bug template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket or instance-derived details
- [x] I have run the selected tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented risks
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-10-31 13:16:40 -05:00
DottaandPaperclip 91fdf02e95 perf(tasks): defer completed transcripts on compact opens (#18461)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations must show the saved instruction and recent
replies quickly.
> - Compact task reads already limit the saved message window.
> - The conversation still waits for completed run transcripts even when
a saved reply contains the result.
> - Removing that wait alone can insert activity after the reader starts
reading.
> - This pull request defers that output until the reader opens history
and keeps required output in the initial reveal.
> - The benefit is a useful conversation sooner, with a stable first
layout and a working composer.

## Linked Issues or Issue Description

Refs #17593, #18092, #18312, #18358, #18422.

**What happened?**

Opening a task with a long saved investigation can wait for native
events or legacy logs before showing its existing replies. A slow
transcript request can hold the conversation behind the loading screen
until the 15-second fallback.

**Expected behavior**

Show the bounded saved conversation without reading completed output
that already has a usable saved reply. Keep that output available
through the existing history controls.

**Steps to reproduce**

1. Create a task with many completed runs and long saved agent replies.
2. Delay its run events and logs.
3. Open the compact task directly. Before this change, the transcript
read blocks the saved replies and composer.

## What Changed

- Defer completed successful run transcripts on compact task opens when
a usable saved reply is present. Load that output through the existing
history controls.
- Keep required output on the initial path: live and failed runs,
yielded runs, pending interactions, placeholder/progress-only replies,
explicit anchors, chats, and full history. Retain output already
selected during this visit when its run completes.
- Keep saved plans visible when their owning run output is deferred or
still loading.
- Keep the same composer and draft through history expansion. Offer
**More run output** when a single saved run has deferred output.
- Position same-task comment links after their target arrives. Wait only
for a missing target, with a 15-second limit. Unrelated stalled metadata
cannot block an available target after the reveal deadline.
- Preserve the reading anchor when a queued scroll event arrives during
a properties-pane width transition.
- Add a 200-reply/200-run PostgreSQL browser fixture with a saved plan,
covering both task views on desktop and mobile. Correct stale browser
setup for current routes and the shared mobile scroller.
- Remove a random company-prefix collision in the isolated privacy test
fixture that failed during CI.

## Verification

- Final revision `fba3f2fcbb`: 386 focused thread/scroller unit cases
and all 32 production-browser journeys passed. The browser cases cover
both task views on desktop/mobile, saved plans, delayed transcripts,
history, comment links, Back, drafts, retry, avatar continuity, media
and pane resizing. The 25 privacy fixture cases also passed against
PostgreSQL.
- Workspace typecheck and full build passed with Node 24. A broader
local UI run passed 10,220 cases across 849 files before the final
navigation/plan review fixes; the changed components were then rechecked
in the 386-case focused run.
- Five alternating pairs compared master `12b0cc6304` with this
revision, using 200 long saved replies and 200 completed native runs.
Both production UI builds used the same loopback API/database, Chromium
151.0.7922.34, 1440 × 900, fresh browser contexts, service workers
blocked, no CPU throttle, and a controlled 3-second events/log delay.
Builds and other suites were stopped during measurement. No page errors
occurred.

| Useful conversation + editable composer | Baseline median (range) |
Fixed median (range) |
| --- | --- | --- |
| Cold direct open | 3.570s (3.538–3.616s) | 1.056s (1.022–1.141s) |
| Task-list navigation | 3.373s (3.342–3.394s) | 0.899s (0.885–0.915s) |
| Back | 22ms (22–25ms) | 25ms (25–28ms) |

- Median paired savings: 2.519s cold, 2.470s from the list.
Completed-output requests: two per baseline sample, zero per fixed
sample. Recent-comments API control medians were 13.6ms for both, with
ranges 12.1–18.7ms and 11.6–50.8ms. No Back improvement is claimed; an
earlier revision's run also included one 1-second Back outlier, retained
in the local evidence.
- The full local default test command did **not** pass: it stopped on
the existing chat test line-selection error. After restoring embedded
PostgreSQL library symlinks omitted by an install with scripts disabled,
Node 24 passed 672 cases in the first two chat shards, then failed to
select the third. This is separate from the passing focused suites and
remote CI.
- Earlier CI failures were addressed: the privacy prefix collision is
fixed; the delegated task-completion reply case passed locally after
merging master's reply-recovery fix (#18465). Browser fixture
corrections retain the original behavior assertions. Red tests
reproduced the loading, navigation, resize and saved-plan regressions
before their fixes.
- Map, module-boundary, token-gate and added-line token checks passed.
The full-tree token scan still finds pre-existing active-username
fixtures; this PR adds zero forbidden token lines.
- Greptile: **5/5**, final revision, all four review threads resolved.
The final-revision PR CI workflow passed, including build, typecheck,
all server/chat/workspace test shards, all eight E2E shards, and every
Runner lane. GitHub reports 55 successful checks and three skipped
checks. The separate **Paperclip Review** check remains queued with
**Waiting for the assigned agent**; it has not produced an assessment
and has not been bypassed. The branch has no merge conflicts.

## Risks

- The default compact task omits completed transcript details when the
saved result is sufficient. The reader must open history to inspect
them.
- Required structural data remains inside the initial reveal boundary.
Slow server responses for that data remain visible latency.
- Link positioning falls back after 15 seconds when its target never
arrives. The conversation remains readable.
- The measurements use a controlled local delay. They do not establish a
deployed staging speedup.
- No API, schema, authorization, or migration changes.

## Model Used

OpenAI Codex, GPT-6, with tool use and code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [ ] I have run tests locally and they pass (focused suites pass; the
full default wrapper has the existing selection error documented above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green (code CI passed; the separate
assigned-agent Paperclip Review remains queued)
- [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 12:56:06 -05:00
DottaandPaperclip bacbab2bc1 test(testops): retain safe verification failure predicates (#18470)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat feature evaluations send their original results to TestOps.
> - A final reader checks the stored case, run, source, status, and
attachments.
> - Two real chat cases passed, but the final reader returned a generic
mismatch.
> - Later server responses passed the same reader, so they do not
explain the earlier failure.
> - This change records the exact failed predicate without recording
field values.
> - The next failure can be diagnosed in its actual caller context.

## Linked Issues or Issue Description

Refs #18462, #18394, and #18322. The current base includes the
independent browser-fixture fix in #18409.

**What happened?**

The post-upload reader returned `chat_testops_upload_mismatch`. Its
closed artifact had no phase or field detail. The original evaluation
and TestOps case passed. Later responses from the same five endpoints
passed the unchanged reader. Those later interactive responses do not
prove what the protected API caller received at failure time.

An earlier CI run also exposed a flat-text browser-fixture mismatch.
Current master independently fixes that assertion in #18409. This branch
adopts that complete upstream test; the final PR diff contains only the
two diagnostic files.

**Expected behavior**

Keep every report-reader acceptance check. Report a fixed phase, failed
predicate names, match booleans, and field type names. Do not record
response values, credentials, unknown URLs, or traces.

**Steps to reproduce**

1. Supply a missing case ID, a conflicting job ID, or a wrong export
field to the reader.
2. Project the failure with `failureProjection`.
3. The parent returns only the generic error code. This change also
identifies the failed check and distinguishes a missing field from a
value of the wrong type.

**Paperclip version or commit**

The latest retained failure used
47f81e850b. The branch now includes
current master `3ee4c5b6138da82d0b1f51aa010540561bf43c22`. The upstream
API is unchanged.

**Deployment mode**

GitHub Actions and AWS, with TestOps reporting.

## What Changed

- Add private diagnostics to the existing same-code failure throws.
- Emit only fixed names, booleans, and closed type names through the
existing failure projection.
- Copy projected metadata so a caller cannot change the stored
diagnostic.
- Add failure-path, missing-versus-conflicting-field, and
secret-redaction controls.

## Verification

- Five new controls fail against the original parent module. A combined
early-mismatch/null-entry control also fails against the first
diagnostic implementation. Null-safe diagnostic traversal preserves that
known failure.
- `node --test tests/runner-e2e/chat-feature-testops-api.test.mjs`: 53
passed.
- The existing CLI, reporter facade, and exporter tests: 22 passed.
- Both changed MJS files pass `node --check`. `git diff --check` passes.
- The earlier browser-fixture failure remains recorded. The owning test
is now byte-identical to the independently shipped base fix in #18409.
No browser-test or production-file delta remains in this PR.
- Removing the private diagnostics and restoring the ten original throws
reconstructs the entire parent API file byte for byte. Acceptance
expressions, API order, deadlines, and successful output are unchanged.
- All five retained current server responses still produce VERIFIED.
Successful output matches the parent output byte for byte. These
responses used interactive authentication at a later time; the original
protected-token failure remains unexplained.
- Local checks used Node 26.4. Normal CI
[41213493964](https://github.com/paperclipai/paperclip/actions/runs/41213493964),
attempt 1, passed on 78a40d6b67. Both
required checks passed, including browser e2e. The adopted upstream
browser shard passed. Greptile is 5/5 on this head, and all review
threads are resolved.
- Full local typecheck, build, app, database, native SDK, provider, and
model runs were not run. The diagnostic slice uses pure tests, mocks,
and file-system controls.
- No public command or user-facing behavior changes. No documentation
update is needed.

## Risks

- A diagnostic must not expose a sensitive value. A private WeakMap,
fixed field names, boolean checks, and closed type names limit the
output. Tests include synthetic secret strings and mutation attempts.
- Diagnostic checks mirror validation to keep the original guards byte
for byte. Future validation edits must update the paired diagnostic and
its targeted controls. This is a known maintenance tradeoff.
- This patch does not explain or erase either historical reader failure.
It changes no Product E2E grade, model, retry, source guard, API route,
workflow, or deadline.
- Live failure diagnostics remain unqualified until a later authorized
run uses this code.

## 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 11:04:56 -05:00
DottaandPaperclip 3ee4c5b613 Make saved execution receipt recovery react to durable work (#18409)
Reviewed and verified at 8f306e0a6e.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 10:03:59 -05:00
DottaandPaperclip 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