Commit Graph
6012 Commits
Author SHA1 Message Date
DottaandPaperclip f99b15b0df docs(cloud): define separate runtime handoff prerequisites
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:42:49 -05:00
DottaandPaperclip 206e241174 test(cloud): verify startup order and package dependency comparison
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:39:16 -05:00
DottaandPaperclip c190103824 feat(cloud): record configuration migration and package qualification
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:37:04 -05:00
DottaandPaperclip 9dcf3f9904 docs(config): name secret storage fallbacks outside runtime migration
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:36:59 -05:00
DottaandPaperclip d8f920ce7e fix(config): defer runtime validation until saved Cloud configuration loads
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:36:25 -05:00
DottaandPaperclip 4bb9e10296 test(config): isolate adapter settings startup prerequisite
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:36:25 -05:00
DottaandPaperclip cc42171101 fix(config): persist managed Cloud runtime choices in Postgres
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:36:25 -05:00
DottaandPaperclip cd328c1e51 fix(cloud): honor managed plugin floors and provider origins
Align shipped provider package versions with their manifests and preserve the registry origin of self-hosted npm workers.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:29:37 -05:00
DottaandPaperclip e645a9ebc4 fix(cloud): disable legacy package development watchers
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:18:14 -05:00
DottaandPaperclip 3f8cd9c1c0 fix(plugins): retain full registry identity for image upgrades
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:18:14 -05:00
DottaandPaperclip 10d8a9ce89 fix(cloud): resolve bundled plugins from current image identity
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:18:14 -05:00
DottaandPaperclip b826940a69 test(adapters): allow cold route setup to complete
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:17:58 -05:00
DottaandPaperclip 1dadec7627 test(adapters): use a typed fixture marker
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:17:58 -05:00
DottaandPaperclip e6346dbfe6 fix(adapters): restrict Cloud to release image implementations
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:17:58 -05:00
DottaandPaperclip d7f63370e5 fix(adapters): preserve save results when audit handling fails
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:17:31 -05:00
DottaandPaperclip 33a5c04797 fix(cloud): persist adapter settings in PostgreSQL
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 11:03:46 -05:00
DottaandPaperclip 1511c92965 fix(evals): account for superseded delegation wakes (#18319)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

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

**Deployment mode**

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

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

## What Changed

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

## Verification

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

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

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 10:40:00 -05:00
DottaandPaperclip b31ec0a2dc feat(ui): link routines to a filtered task list (#18317)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Routines create tasks that people need to inspect and manage.
> - The routines list sends its View all runs link to Audit.
> - Tasks already supports routine origin filters in its API, but the
page has no control for them.
> - This pull request adds a Routine tasks checkbox and links to that
selection.
> - People can inspect routine work in the normal task list, search, and
board views.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The routines list link and the Tasks filters.

**Current behavior**

View all runs opens Audit. People cannot select routine-created tasks in
the Tasks filter menu.

**Proposed behavior**

View all tasks opens `/issues?view=all&originKind=routine_execution`.
Routine tasks is selected. People can toggle or clear it from Tasks.

**Reason and benefit**

People can use normal task controls to inspect work created by routines.
The filter includes manually started routine runs. It excludes manual
tasks and other automatic work.

**Breaking changes**

The routines list link changes its label and destination. No API,
schema, authorization, or routine execution contract changes.

## What Changed

- Add Routine tasks under Visibility in the current, streamlined, and
legacy Tasks filters. Keep Live runs only in the same group and use Show
agent-created tasks with proper capitalization where that control is
available.
- Keep the selection in the URL through reload, search, task navigation,
and checkbox changes.
- Apply the existing API origin filter before pagination. Include
routine tasks even when other automatic tasks are hidden.
- Keep source filtering in the shared task filter module and collection
owners. Reuse the existing company-scoped issue-list contract. Hide the
live-run control in the design sandbox, which does not load live-run
IDs.
- Update regression coverage, product docs, feature/access maps, and the
toolbar preview.

## Verification

- All 58 final-head checks are complete with no failures for
`f46c2e409b20fa372d166f4721601a0471894fb0`, including successful `ci /
verify` and `ci / e2e` gates. Greptile and Paperclip Review rate this
commit 5/5 with no actionable findings or unresolved review threads. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/41078093110).
- Local checks pass: full repo typecheck/build for the feature, UI
typecheck/build after the final refinements, token gates, feature-map
checks, and Storybook catalog generation.
- Regression coverage exercises both real list implementations, filter
grouping and selection, search and all board columns, URL/pagination
state, and mixed pending-decision batches. The Visibility update passed
all 89 relevant tests across separate runs. The final sandbox correction
passes all 10 filter-menu tests, including three cases that reproduced
the bug before the fix. The earlier broad UI run passed 10,043 tests
across 845 files.
- Browser proof used the actual local app with disposable PostgreSQL
data: three tasks created through the routine-run API and one manual
task. Followed View all tasks; verified the selected Routine tasks
checkbox under Visibility, toggling, reload, search, and board view.
Checked current, streamlined, and legacy filter presentations.
Screenshots show the link, routine-only results, and requested
capitalization/grouping.
- Failure accounting: the initial broad UI run found two preference
expectations that needed the new false default; those were corrected
before the full UI pass. Scrolling tests hit five-second timeouts in
combined runs and passed in isolated reruns without timeout changes. A
duplicate full local UI run was stopped after the earlier final-commit
CI UI lanes passed, with no failures reported in that stopped run.
- Full local `pnpm test:run` could not complete because native
PostgreSQL initialization exhausted the host semaphore pool. A direct
initdb probe confirmed `could not create semaphores: No space left on
device`. Browser verification used a disposable container; no host
settings or other workspace processes were changed.
- Review found that the newly exposed live-run control could empty the
design sandbox, which has no live-run IDs. The sandbox now disables that
unsupported control; its regression test failed before the fix and
passes after it.

## Risks

- Low risk. The change uses the existing routine origin and read
permissions. A routine task remains automatic work, including when a
person starts it manually.
- The routine checkbox is exposed only on the Tasks collection. Other
filter consumers retain their controls and normalize the new field to
false.
- Routine histories and Audit run links inside routine details keep
their current behavior.

## Model Used

- OpenAI GPT-6, through Codex, assisted with implementation and
verification. The exact runtime model ID and context window are not
exposed in this session. Capabilities used: repository editing, command
execution, tests, and browser interaction.

## 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 10:28:58 -05:00
DottaandPaperclip 5c807d11fa fix(github): prevent duplicate review score headings (#18321)
Clarify the shared GitHub review submission contract for new and existing bots.
Remove copied score headings while preserving the structured score and saved assessment.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
canary/v2026.1030.0-canary.13
2026-10-30 10:19:31 -05:00
DottaandPaperclip 59e191c368 Limit first onboarding to Claude and Codex (#18309)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - First onboarding helps a new user connect the first agent.
> - Its provider picker currently includes GitHub Copilot.
> - The first setup should offer only Claude and Codex.
> - This pull request limits that picker to those two providers.
> - Users can still choose other providers when they add more agents.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The model-source picker in first-agent onboarding.

**Subsystem affected**

`ui/` — the onboarding wizard and its tests.

**Current behavior**

First onboarding offers GitHub Copilot. It can also expose other
providers when their display metadata marks them as recommended.

**Proposed behavior**

Show only enabled Claude and Codex choices in first onboarding. Keep
their automatic native-runner routing on qualified execution
environments and the silent legacy fallback on native Windows, with the
same provider UI. Keep all supported providers in the later Add Agent
flow. Require a visible provider choice when an old draft names a
provider that is no longer offered.

**Reason and benefit**

Keep the first setup focused while preserving provider choice for an
existing company.

**Breaking changes**

Old Copilot or other provider drafts require a new choice in first
onboarding. Existing agents, provider APIs, and the Add Agent flow keep
their current behavior.

**Additional context**

Related provider setup work: #15562. This change only narrows the
first-onboarding picker. Searches for onboarding/Copilot and
first-onboarding PRs found no duplicate change. This is a small
improvement to the existing setup flow, consistent with ROADMAP.md.

## What Changed

- Limit first-onboarding adapters to Claude and Codex, with existing
availability checks.
- Remove the Copilot tile, login card, connection state, model
discovery, and creation guards from first onboarding.
- Retain only migration handling for old Copilot drafts: clear the
retired selection/model/flag, restore automatic runner choice, and avoid
reusing GitHub bindings when the user selects Claude or Codex. This also
works when both onboarding providers are disabled.
- Update coverage for provider choices, disabled adapters, and old
Copilot and Gemini drafts.
- Clear the model when an unavailable saved provider changes to Codex.
- Explain how to proceed when both first-onboarding providers are
unavailable.
- Update the onboarding feature and access maps.
- Document the Windows fallback beside automatic runner discovery, with
an explicit note to default Windows to native when its runner support is
qualified. This inline migration note is an explicit requirement of the
change.
- Extend both providers' setup coverage for native and legacy
availability without forcing a runtime from the browser.

## Verification

- 282 tests passed across all onboarding component/route tests and
`NewAgentDialog.test.tsx`. This includes the separate adapter-draft
suite that CI identified as still expecting Copilot in first onboarding.
- The existing server runner-selection suite passed: 231 tests,
including native Claude/Codex runtime translation and Windows legacy
fallback. This is automated routing coverage; no native Windows
end-to-end run is claimed.
- UI TypeScript checks and the production UI build passed.
- Token gates, feature/access map validation, module-boundary checks,
and `git diff --check` passed.
- Reviewer command from `ui/`: `pnpm exec vitest run
src/components/OnboardingWizard.test.tsx
src/components/OnboardingWizard.adapters.test.tsx
src/components/OnboardingWizard.step.test.tsx
src/components/OnboardingWizardVariant.test.tsx
src/components/NewAgentDialog.test.tsx
src/lib/onboarding-route.test.ts`.
- A separate browser walkthrough on staging completed the Add Agent flow
with Codex and confirmed Copilot remained available. That walkthrough
used an existing deployment; it does not prove this branch's
first-onboarding change.
- Ponytail Paperclip Review and Greptile both scored the latest commit
`b470f7023ecb6657bd77edefbcaf2ab12fd89414` 5/5. All review threads are
resolved.
- All latest-head PR checks are complete: 55 passed and 3
neutral/skipped, with no failures or pending checks. Two server shards
passed on a single retry after an unchanged timing-sensitive test
exceeded its limit and a self-hosted runner lost its connection. No code
or test changes were made for the retry.

## Risks

- Low scope: the provider filter belongs only to the onboarding wizard.
Native Windows runner support is still unmerged (#18250 is only its
build/CI baseline), so automatic selection must retain the existing
legacy fallback. Platform selection is based on the execution target,
not the browser OS.
- Users with an old draft for another provider must choose Claude or
Codex. Existing agent configuration is not removed.
- Instances that disable both providers have no first-onboarding choice.
The wizard explains how to enable a provider or use New Agent from the
Agents page.

## Model Used

OpenAI GPT-6 through Codex. The exact runtime model ID and
context-window size are not exposed in this session. Capabilities used:
reasoning, repository edits, shell commands, and browser UI
verification.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 10:04:38 -05:00
Nicky Leach fba0ab8162 fix(runner): preserve GitHub helpers and Codex probe policy (#18212) 2026-10-30 07:42:10 -07:00
e345b9217d fix(runner): paginate native task searches without hidden truncation (#18282)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents search tasks to find work that already exists.
> - The search schema permits 200 results, but the server returns at
most 100.
> - The response does not tell the agent that more results exist.
> - This pull request adds pages and reports the page size and
continuation cursor.
> - Agents can read the full accessible inventory before they decide
that a task does not exist.

## Linked Issues or Issue Description

**What happened?**

A native `search_tasks` request with `limit: 200` returns only 100
tasks. Historical scans recovered 167 and 173 tasks with status
partitions. This proves missing inventory and extra work. It does not
prove duplicate task creation.

**Expected behavior**

Honor the declared limit. Report more results and give the caller a
continuation cursor.

**Steps to reproduce**

Create 205 matching tasks in a test company. Call `search_tasks` with
`limit: 200`. The baseline returns 100. The fixed path returns 200, then
five when the caller uses `nextCursor`.

**Paperclip version or commit**

Baseline: `81ebe479e8db8a3d59c86cdfb894bd917734492f`.

Related changes: #16979 changes UI status filters before pagination.
#13699 adds public task URLs. Neither repairs this native limit. An
exact `search_tasks` plus pagination PR search returned no result.

Pattern: [Task searches omit cases beyond the first
hundred](https://www.braintrust.dev/app/Paperclip/p/Paperclip%20Staging/patterns/c20462d6-05fd-4862-bfbd-7bec1f2bc159).

### Hypothesis and thesis for a fix

The native authority uses `boundedLimit` with its default maximum of
100. The tool schema permits 200. The response contains only `tasks`.
The raw request and result counts agree with this cause.

Fix the native authority and its canonical tool contract. Keep the
existing `tasks` field. Add `limit`, `returnedCount`, `hasMore` and
`nextCursor`. Use ascending task IDs so task activity does not move
results between pages. Apply current company, privacy and Muse read
checks before each page. A cursor grants no access. Callers must keep
the same filters and read every page. Concurrent task changes require a
fresh scan.

## What Changed

- Honor the native search limit of 1 to 200, with a default of 50.
- Add ID cursor pagination and page metadata.
- Describe complete inventory reads in the tool contract and access map.
- Refresh the generated semantic contracts and seeded catalog identity.
- Add regression coverage for complete inventories and access-filtered
pages.

## Verification

- Red: the database integration test requested 200 of 205 persisted
tasks. Baseline returned 100.
- Green: the same regression returns pages of 200 and five without
duplicate IDs.
- The native authority and Muse suites cover company exclusion, status
filters, empty pages, invalid cursors and readable-only metadata.
- Command: `pnpm --filter @paperclipai/server exec vitest run
src/services/native-runtime/paperclip-runner-tool-authority.test.ts
src/services/native-runtime/muse-native-visibility.test.ts`.
- The test uses the real run-bound native authority and disposable
PostgreSQL. It does not use an external model or change a deployed
scanner.
- Both native authority and Muse suites pass: 71 tests. Server direct
`tsc --noEmit`, Runner `typecheck:typescript`, `node
scripts/check-maps.mjs` and generated semantic contract checks pass.
- Full typecheck and build cannot finish here because `cargo` is absent.
The full local test command was stopped after about five minutes when
the complete CI matrix was running. It has no complete verdict.
Current-head CI passed, including typecheck, build, all
general/serialized/Runner test suites and E2E. Greptile is 5/5 with no
actionable findings at `392cb7424a1fa0ec73401d5e8a10a22b504fde32`.
Optional Storybook and manual Docker workflows were skipped and are not
executed coverage. The success-example correction also passed all 82
contract tests locally.

## Risks

Task order changes to ascending ID. Pagination is not a snapshot. New or
changed tasks can require a fresh scan. Each page retains the existing
full company-list read and Muse authorization cost. This change adds no
database query loop or new background work. Existing callers can still
read `tasks`, but must follow `nextCursor` for a complete inventory. No
scanner implementation was supplied. No migration or deployment is
included.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The exact
provider deployment ID and context limit 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)
- [ ] 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

The task requires the supplied branch to stay unchanged. All applicable
CI and review checks pass at the current head. Unmerged and not
deployed.

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 09:23:10 -05:00
DottaandPaperclip 6da112ab40 perf: avoid flushing separate Git cache seed archives (#18308)
## Thinking Path

> - Paperclip manages work done by AI agents.
> - Native sandbox runs prepare a workspace before the agent can
respond.
> - A shared seed cache avoids repeated Git copies and archive
preparation.
> - Cache publication also flushes a branch-neutral Git seed that is
separate from recovery archives.
> - This cache can be rebuilt. Each reader checks the archive bytes
before reuse.
> - This change omits that separate cache file flush and measures the
remaining preparation gaps.
> - The benefit is less work before agent execution and clearer timing
evidence.

## Linked Issues or Issue Description

Refs #18240.

**What existing behavior does this improve?**

Workspace seed cache publication and latency diagnostics for native
sandbox preparation.

**Current behavior**

Publication flushes both cache archives to disk under the company lock.
Slow storage can delay the publishing run and cache readers. A cache hit
also combines private copying, hashing, and last-used bookkeeping in one
span. Early controller preparation has gaps before environment
selection.

**Proposed behavior**

Keep the existing flush for recovery-backed workspace and Git archives.
Omit the flush only for a separate branch-neutral Git cache archive.
Reject an alternate cache file that is the recovery file or its
hardlink. Keep archive checksums, private copies, atomic publication,
quotas, and company locking. Measure cache read steps and the existing
early preparation operations.

## What Changed

- Skip the flush only for the separate branch-neutral Git seed used by
the company cache.
- Preserve the existing flush for recovery-backed archives, including
hardlink storage. Reject cache-only files that alias recovery bytes
before or during publication.
- Add a regression with a blocked cache-only Git flush. The deployed
code waits; the new code publishes verified cache bytes without waiting.
Test storage failure for both recovery-backed archives and same-path,
hardlink, and replacement alias cases.
- Add cache copy, hash, and bookkeeping spans beneath seed lookup.
- Add timing around existing agent, conversation, runtime, issue,
identity, trust, and task context preparation. Keep their execution
order.
- Update the trust-order guard to recognize the timed call while
continuing to assert trust resolution precedes workspace selection and
credential setup.
- Document the cache contract and the new spans. Keep the old flush span
in the allowlist for compatibility with older observations.

## Verification

- The blocked-flush regression fails on the old code and passes with
this change.
- Focused tests (`vitest run` on the six affected cache, timing, and
native-sync suites) cover cache corruption, private-copy integrity,
quota and eviction races, branch binding, per-run recovery, native
workspace synchronization, trace parentage, and tracing disabled or
failing.
- 115 focused tests and both typechecks pass after rebase on current
master. The tests include recovery storage failures and an archive
replaced with a recovery hardlink during verification.
- All seven trust tests pass with the actual service and migrations,
using a fresh database on an existing local PostgreSQL server. The local
embedded server could not allocate host semaphores, so only its test
startup helper was substituted; assertions and service code were
unchanged.
- A real SDK export with a retained public seed verifies that cache-read
detail spans have the lookup as their parent. The endpoint-off control
produces no spans.
- Current revision `28dea63432d462cad160906f8dfc2d21c81d3446`: all 53
checks pass, two optional checks are skipped, Greptile is 5/5, and no
review threads are open.
- No new staging latency claim is made by this PR. Hosted measurement
remains necessary after delivery.

## Risks

A crash or power loss can discard the cache-only Git seed. A later read
rejects missing or corrupt cache bytes and prepares the workspace again.
Recovery-backed archives retain their previous flush behavior. The
change adds no flush to warm per-run persistence. Hashes and
private-copy checks remain required. The new spans use the existing
opt-in exporter and closed names; they record no task content.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The session does not expose the exact model SKU 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 09:13:08 -05:00
Dotta 65554ee596 refactor(adapters): remove dead vitest setup from hermes-gateway shim (#18281)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The `packages/adapters/hermes-gateway` package is a deprecated
compatibility shim. It forwards to
`@paperclipai/hermes-paperclip-adapter/gateway`.
> - The shim carries a `vitest.config.ts` file and a `test` script. The
package contains no test files. It has contained none since it was
created in #8543.
> - The root Vitest project list does not select this package. No
workflow and no repository command runs its `test` script. The script
starts Vitest with no test files, so it can only fail.
> - This pull request deletes the dead Vitest config file and the broken
`test` script line. The package code, its exports, and its
release-manifest entry stay unchanged.
> - The benefit is less dead test support and one less broken entry
point in a deprecated package.

## Linked Issues or Issue Description

**Current behavior**

The deprecated `@paperclipai/adapter-hermes-gateway` shim has a
`vitest.config.ts` file and a `test` script. The package has no test
files. No CI lane and no repository command selects the package for
tests. The script cannot pass, because Vitest exits with an error when
it finds no test files.

**Proposed behavior**

Delete the unused Vitest config file. Remove the `test` script from the
package manifest. Keep the published code and the release-manifest entry
unchanged.

**Reason and benefit**

This is dead test support. It protects no contract, because no test
exists in the package. The `test` script misleads a reader: it looks
like a test entry point, but it always fails. The real Hermes Gateway
coverage lives in `packages/adapters/hermes`, which the default test run
selects. This change came out of a test-suite maintenance audit. (Refs
#8543, which added the shim with this config.)

**Breaking changes**

None. No command, workflow, or package invokes the removed script or
config. The published package code does not change. The `vitest` dev
dependency stays, because pull requests may not edit the lockfile.

## What Changed

- Deleted `packages/adapters/hermes-gateway/vitest.config.ts`. The
package has no test files, so the config selects nothing.
- Removed the `test` script from
`packages/adapters/hermes-gateway/package.json`. The script ran `vitest
run` with no test files and could only fail.

## Verification

- Searched the repository for references to the deleted config and the
removed script. The search `rg
'hermes-gateway/vitest|vitest.*hermes-gateway'` returns no match outside
the lockfile. No workflow, script, or document names them.
- Confirmed that the root Vitest project list (`vitest.config.ts`) and
the shard runner (`scripts/run-vitest-stable.mjs`) do not select this
package.
- Confirmed that no open pull request changes these two files. The check
read the file list of every open pull request.
- Ran locally, without an install: `node --test
scripts/release-package-map.test.mjs`. It passes. It asserts the shim's
release-manifest entry. `node scripts/release-package-map.mjs check`
also passes: "30 enabled for CI publish, 5 disabled pending bootstrap".
- Parsed `packages/adapters/hermes-gateway/package.json` with Node. The
JSON is valid.
- Not run locally: `pnpm -r typecheck`, `pnpm test:run`, `pnpm build`.
The execution workspace has no installed dependencies. The pull request
CI runs these lanes against this change.

## Risks

- Low risk. The deleted config file is outside the package
`tsconfig.json` include list (`["src"]`), so typecheck output does not
change.
- If a future change adds tests to this package, it must add a test
script again. The removed config held only default settings, so a new
one is trivial to write.
- The `vitest` dev dependency remains. Removing it would change
`pnpm-lock.yaml`, which pull requests may not edit.

> 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`](CONTRIBUTING.md).

## Model Used

- Z.ai GLM-5.3 served through OpenRouter. Exact model ID: `z-ai/glm-5.3`
(route `openrouter/z-ai/glm-5.3`).
- Standard agent mode with tool use: file search, file edit, shell, and
GitHub CLI in a sandboxed Linux workspace.
- Context window size: not independently verified. The change did not
rely on a large context.

## 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 (release-package-map tests;
broad suites run in PR CI — see Verification)
- [x] I have added or updated tests where applicable (not applicable:
test-support deletion only; the retained release-manifest test still
covers the manifest contract)
- [x] I have updated relevant documentation to reflect my changes (not
applicable: no document references the removed script or config)
- [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
2026-10-30 09:09:29 -05:00
DottaandPaperclip 5a7a6b32ba fix(ui): restore compact Coordinator task loading and responder continuity (#18312)
## Thinking Path

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

## Linked Issues or Issue Description

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

**What happened?**

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

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 09:03:03 -05:00
DottaandPaperclip ac4f13d205 fix(e2e): report committed child blockers promptly (#18306)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

## Thinking Path

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

## Linked Issues or Issue Description

**What existing behavior does this improve?**

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

**Current behavior**

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

**Proposed behavior**

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

**Reason and benefit**

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

OpenAI GPT-6 through Codex. The runtime did not expose a more specific
model ID or context window size. Used reasoning, code editing, shell
commands, and browser automation.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 07:52:15 -05:00
Devin FoleyandClaude Opus 5.5 2a221e8e80 fix(sentry): keep scheduled native model capacity retries out of run-failure reports (#18295)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The run-failure reporter sends terminal run failures to Sentry when
an operator sets `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected`
> - In `unexpected` mode, the reporter skips failures that a bounded
automatic retry already owns. The Codex ACP model capacity failure
(`codex_transient_upstream`) is one of these
> - The native runner has the same capacity failure: Codex
`serverOverloaded` ("Selected model is at capacity"). Native
finalization schedules a bounded automatic retry for it (#15347)
> - The reporter has no matching exclusion for the native path. Each
scheduled capacity retry also sends a Sentry error, even when the retry
recovers the task
> - This pull request skips the report only when the native failure has
typed capacity evidence, a committed retry decision, and the retry run
that the decision created
> - The benefit is that Sentry shows capacity failures only when
automatic recovery stops (retries are exhausted, held, or not scheduled)

## Linked Issues or Issue Description

Refs #15347 (native capacity retry). Refs #16407 (Codex ACP capacity
exclusion).

**What happened?**
A native Codex run failed with "Selected model is at capacity. Please
try a different model." (`native_provider_overloaded`). Native
finalization scheduled the automatic capacity retry. The retry run
succeeded and the task completed. The run-failure reporter still sent a
Sentry error event for the first run.

**Expected behavior**
When the automatic capacity retry owns recovery, the run failure stays
in the local run log and does not go to Sentry. This is the same as the
Codex ACP capacity path. When retries are exhausted or held, or when no
retry is scheduled, the failure goes to Sentry.

**Steps to reproduce**
1. Set `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected` with a backend Sentry
DSN.
2. Run a native Codex agent turn that ends with a Codex
`serverOverloaded` terminal error.
3. See that native finalization creates a `scheduled_retry` run with
`scheduledRetryReason=native_provider_overloaded`.
4. See that Sentry also receives a run-failure event for the failed run.

## What Changed

- `server/src/services/run-failure-report.ts`: add
`isScheduledNativeCapacityRetry`. In `unexpected` mode it skips the
report only when all of these are true:
- the run is native, `failed`, has
`errorCode=native_provider_overloaded`, and has a native task
(`nativeIssueId`);
- `resultJson.nativeProviderFailure` is the closed
`codex`/`server_overloaded` diagnostic;
- `resultJson.finalizationPhase` is `committed` and
`finalizationReasonCode` is `native_provider_overloaded`;
  - the report is not from setup, and the run has no signal;
- a successor run for the same task exists with `retryOfRunId=run.id`
and `scheduledRetryReason=native_provider_overloaded`. The same status
transaction creates this run.
- The successor lookup filters on `company_id`, `context_snapshot ->>
'issueId'` and `created_at >= run.createdAt`, so the existing
`heartbeat_runs_company_ctx_issue_created_idx` bounds it to that task's
runs since the failure. No migration is needed.
- A failed read of the retry evidence logs a warning and reports the
failure.
- `doc/observability.md`: document the new exclusion in the run failure
context section.
- Unit tests: the exclusion, and twelve cases that must still report
(exhausted, held, no retry run, another retry lane, successor for
another task, run with no native task, finalization not committed, wrong
or missing diagnostic, legacy run, signal, timeout). Also setup phase,
`all` mode, and an unreadable retry record.
- Integration test (real native finalizer): no Sentry event for retries
1 and 2, one event when retries are exhausted, and one event when
reassignment prevents a retry.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/services/__tests__/run-failure-report.test.ts
src/services/native-runtime/native-provider-overload.integration.test.ts
src/services/native-runtime/native-provider-failure.test.ts
src/services/__tests__/status-arbiter.test.ts`: 359 tests pass.
- Red/green: before the fix, the new unit test captured 2 events, and
the integration test captured an event on the first scheduled retry.
After the fix, both pass.
- `EXPLAIN` on the migrated schema: `Index Scan using
heartbeat_runs_company_ctx_issue_created_idx` with company, context
issue and created time in `Index Cond`.
- CI provides the full workspace typecheck.

## Risks

- Low risk. The change applies only in `unexpected` mode and only to
native runs with typed capacity evidence and an existing retry run.
`all` mode still reports every failure.
- The check adds one index-bounded read of `heartbeat_runs` for runs
that match the in-memory capacity checks. Other runs do not do this
read.
- If a scheduled retry later fails, that retry run reports its own
outcome. When retries are exhausted, the final failure reports.

> 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

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic. Agentic coding with
tool use (shell, file edits, test execution) and extended thinking.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
canary/v2026.1030.0-canary.12
2026-10-30 05:42:43 -07:00
DottaandPaperclip 8f50704135 fix(e2e): wait for pending native recovery (#18298)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.1030.0-canary.11
2026-10-30 06:55:41 -05:00
DottaandPaperclip 8035f8b245 test: require saved onboarding approval cards (#18292)
## Thinking Path

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

## Linked Issues or Issue Description

Refs #18288 and #18266.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

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

**Deployment mode**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

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

## Linked Issues or Issue Description

Refs #18266 and #18258.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

The branch starts from `965184d2968f40b1183803529b88f288264c832f`.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.1030.0-canary.9
2026-10-30 04:01:33 -05:00
DottaandPaperclip 965184d296 fix(runner): reuse accepted confirmations on native continuation (#18283)
## Thinking Path

> - Paperclip coordinates agent work and human decisions.
> - Native agents receive accepted confirmations when their task
resumes.
> - A resumed run can repeat the original confirmation with the same key
and scope.
> - The interaction service rejects that replay because the source run
changed.
> - This PR returns the original acceptance only to its bound native
continuation.
> - Changed requests and newer proposals keep their existing approval
gates.

## Linked Issues or Issue Description

**What happened?**

A native agent received a human acceptance, then repeated the same
confirmation key and request. Paperclip returned a conflict because
`sourceRunId` differed. The agent then used a new key and created a
second pending confirmation. The task waited for another answer.

**Expected behavior**

An exact replay from the native run that received the accepted response
returns the original accepted record. It creates no request or wake.
Changed scope, another creator, an unrelated continuation, and a newer
proposal must still fail.

**Steps to reproduce**

1. Create a confirmation from a native run.
2. Accept it as a human.
3. Resume the same task with that accepted response in its saved native
input.
4. Repeat the original confirmation key and request.

Before this fix, step 4 returns `409 Interaction idempotency key already
exists for a different request`.

**Paperclip version or commit**

Reproduced against source `81ebe479`. The deployed failure was also
confirmed against Core `6a674716`.

**Deployment mode**

The failure occurred on Cloud. The regression uses the real native tool
authority and PostgreSQL 17 with synthetic data. The full fresh Cloud
journey is not yet verified with this fix.

No duplicate open PR or issue was found in the related
confirmation-replay and interaction-idempotency searches.

## What Changed

- Let the current run's parsed, identity-bound accepted response
nominate an internal replay of a plain confirmation or checkbox. Exclude
governed tool, secret, connection, and quality-review cards.
- Reuse the original accepted record only when the key, creator, and
full normalized request match. Preserve its source run. Reject a newer
confirmation.
- Keep ordinary source-run comparison and mutation receipts. Recheck
accepted cross-run reuse on cached calls and lost-ack recovery. An
absent original cannot create a replacement.
- Add real database regressions and document the replay contract.

## Verification

- Real PostgreSQL regression: the original replay failed with the
observed conflict, then passed.
- Cached replay regressions: two controls first returned stale
acceptance. Both now reject it.
- Final replay and recovery suite: 27 passed. This covers both plain and
checkbox confirmations, governed-payload exclusion, identity, company,
request changes, newer proposals, revised plans, absent receipts, absent
originals, and tool-key conflicts.
- Existing native-tool and onboarding admission suites passed with the
first 24 replay controls: 109 tests at `3cfd58e7`. The scope follow-up
reran all 27 replay controls.
- Existing interaction service and policy suites: 122 passed.
- Full `pnpm build` and `pnpm -r typecheck` passed at `3cfd58e7`. After
the scope follow-up, the focused 27 tests and server TypeScript check
passed. Required full Linux CI passed on the final head `eabdbd6b`.
- The full local Vitest suite was not repeated because the macOS
embedded PostgreSQL bootstrap failure is already documented. Relevant
suites used the supported external test database paths. Required Linux
CI remains pending.
- Final-head CI attempt 1 failed only the unchanged Antigravity login
success fixture. Its implementation and test match a previous passing
head. The exact failure cause is not retained. The original [failed
job](https://github.com/paperclipai/paperclip/actions/runs/41014308876/job/123927423551)
is preserved. The one failed-jobs-only retry request passed on the
unchanged final head. This confirms recovery, not the cause of the
original failure, and is separate from the Cloud journey.
- Full fresh Cloud onboarding and its dependent journey remain
unverified at this revision.

## Risks

An approval replay must not authorize new work. The service keeps exact
request and creator checks under the task lock. Newer confirmations and
ordinary downstream task and target checks remain effective. Normal API
callers cannot supply the internal replay nomination. No database
migration or public request-schema change is included.

## Model Used

OpenAI `gpt-6.1-sol`, ultra reasoning, with repository and shell tools.
The parent runtime metadata supplies this model identity. The context
window is not exposed. Independent review 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>
nightly/v2026.1030.0-nightly.0 canary/v2026.1030.0-canary.8
2026-10-30 01:53:45 -05:00
DottaandPaperclip 81ebe479e8 fix(evals): bind rendered Markdown replies to saved run evidence (#18264)
## Thinking Path

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

## Linked Issues or Issue Description

Refs: #18248, #18255.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 00:57:59 -05:00
Nicky LeachandClaude Opus 5.5 fa760dbce4 fix(runner): reuse image packs only with matching contract digest (#18237)
## Thinking Path

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

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

## Checklist

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

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

---------

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

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

This change is based on public master
`b3c2172d417ea6b783e0c796aaed4a91e1f9d381`.

**Deployment mode**

Scripted Product E2E against a live Cloud testing workspace.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 00:13:37 -05:00
DottaandPaperclip 7df1656dda fix(server): continue retention pages after overdue grace deadlines (#18270)
## Thinking Path

> - Paperclip manages AI agents and their shared work.
> - Skill snapshots need safe cleanup after their retention grace
period.
> - The retention worker scans large directories in pages.
> - Another company's grace deadline can expire while a page is still
running.
> - The shared deadline helper then uses the worker's 30-second failure
retry for successful continuation.
> - This pull request gives this worker a one-second continuation delay.
> - Directory scans keep moving while failure retries retain their
existing delay.

## Linked Issues or Issue Description

Refs #18266. Its unrelated fixture checks exposed this scheduling bug.

**What happened?**

A successful directory page can wait 30 seconds before the next page
when another company's grace deadline becomes overdue during the scan.

**Expected behavior**

Continue successful paging within one second. Process the overdue
company. Stop scheduling when all work settles. Keep the existing
30-second failure retry.

**Steps to reproduce**

Hold the second successful page with a deferred promise. Advance the
fake clock past another company's saved five-second deadline. Release
the page. Before this fix, the next wake is still 25 seconds away. The
regression also requires all pages, the overdue rescan, and an idle
worker after settlement.

**Paperclip version or commit**

Reproduced on `b3c2172d417ea6b783e0c796aaed4a91e1f9d381`.

**Deployment mode**

Core retention worker. The deterministic test uses the real coordinator,
deadline helper, and retention worker with controlled service results.
It needs no external database or provider.

## What Changed

- Set `continuationMs: 1000` on the skill retention worker.
- Add a controlled regression for a grace deadline that expires during a
successful page.
- Keep the shared deadline helper and the worker's failure retry
unchanged.

## Verification

- Red: the new regression fails on unchanged production code with a
25,000 ms remaining delay. The existing control passes.
- Green: retention worker, deadline worker, and scoped deadline worker
suites pass: 7 tests.
- `pnpm build` and `pnpm -r typecheck` pass. All required checks pass on
the current head. Greptile reports 5/5 with no review threads.
- The full local test suite is not complete. The bundled macOS
PostgreSQL runtime lacks `libzstd.1.dylib`, as confirmed in the existing
host diagnostic. The deterministic worker tests do not need PostgreSQL.
Full repository tests must pass in CI.
- No live Cloud, provider, model, or deployment test is selected.

## Risks

Successful overdue continuation can run sooner. The existing one-second
page interval still applies. The test requires the remaining pages, the
overdue rescan, and no more work after settlement. Failure retry remains
30 seconds. This change adds no schema, API, or product command.

## Model Used

OpenAI `gpt-6.1-sol`, ultra reasoning, through Codex. Parent runtime
metadata confirms this model. The context window is not exposed.
Terminal tools assisted source review and testing. A separate agent
reviewed the source and regression.

## 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>
canary/v2026.1030.0-canary.6
2026-10-29 23:50:08 -05:00
DottaandPaperclip b3c2172d41 fix(evals): verify native protected-action outcomes (#18255)
## Thinking Path

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

## Linked Issues or Issue Description

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

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

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

Refs #17940. Refs #18228.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Paperclip version or commit**

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

**Deployment mode**

Cloud testing with the scripted Product E2E harness.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

Refs #18222 and #18244.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 21:35:15 -05:00
Nicky Leach a8e07500db fix(runner): preserve runtime activity through the native bridge (#18239) canary/v2026.1030.0-canary.3 2026-10-29 18:36:04 -07:00
DottaandPaperclip 8941db9ce6 fix(evals): accept editor escapes and cancel sensitive QA requests (#18244)
## Thinking Path

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

## Linked Issues or Issue Description

Refs #18222.

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.1030.0-canary.2
2026-10-29 20:14:56 -05:00
DottaandPaperclip ed8fae8dbb fix(workspaces): preserve completed shallow sandbox exports (#18221)
## Thinking Path

> - Paperclip coordinates agent work and preserves its results.
> - Remote execution copies completed workspace changes back to the
host.
> - An agent can fetch a published branch with shallow Git history.
> - A full Git bundle omits the shallow boundary metadata and can fail
host connectivity checks.
> - This pull request carries the boundaries through the full-bundle
fallback and imports through normal Git fetch.
> - Recovery must also recognize completed native work on a reusable
lease without treating it as ordinary executor reuse.
> - Completed work can be saved without another provider turn, while
existing host history remains connected.

## Linked Issues or Issue Description

**What happened?**
Sandbox finalization can fail with a missing parent commit after an
agent checks out a separately fetched shallow branch. Re-exporting a
full bundle repeats the failure because Git bundles do not encode
shallow boundaries.

**Expected behavior**
Import the completed branch and saved files. Preserve existing host
ancestry and concurrent host edits. Keep normal Git connectivity and
workspace merge checks.

**Steps to reproduce**
1. Prepare a sandbox from one host commit.
2. Fetch a different published branch with depth one and check it out.
3. Save a result file and restore the sandbox workspace.

**Paperclip version or commit**
Reproduced against master before this repair. The regression fails with
the missing-parent error before the production change.

Related public context: #15268 covers rewritten history integration.
This repair handles shallow bundle transport before integration.
Searches found no equivalent open repair.

## What Changed

- Export shallow boundaries beside the full bundle when the delta import
lacks history.
- Unpack into a temporary shared bare repository. Keep parent
connections already available on the host and import with Git's shallow
fetch protocol.
- Reject malformed boundary values and retain existing connectivity,
branch, and concurrent-work merge guards. Keep boundary probes within 15
seconds without consuming the separate 60-second Git import budget.
- Let source-bound preservation recover reusable leases only for the
finalizer-selected, accepted successful native result and matching
completion contract. Retain provider-stop, physical ownership and
host-writer checks; ordinary reusable sources remain blocked.
- Classify invalid Git metadata separately from omittable unsafe
archives. Keep native finalization failed and preserve service-owned
file recovery; carry the sender's dedicated rejection across the command
boundary without transient retries.
- Share the failure allowlist across bounded run/activity projections
and cancelled-preservation selection. Migration `0416` rebuilds the
matching partial index; task chat retains the non-retryable recovery
notice.
- Add real Git, filesystem sandbox and database recovery regressions.
Update execution semantics and affected verification maps.

## Verification

- Red: real filesystem sandbox restore failed with the same
missing-parent/revision-walk error before the export repair.
- Green: 240 focused Git, workspace restore, sandbox transport and
native-finalization tests pass. Coverage includes both transfer paths,
malformed/oversized metadata, a genuinely shallow host with its original
boundary intact, and concurrent host work with both merge parents
verified.
- Red/green: a 14-second simulated probe left the final real Git fetch
only 45,893 ms before the budget split. It now retains over 55 seconds
after the probes; a 16-second probe exhausts its own budget before host
import.
- Red/green: an oversized read progress report was retried three times
before its distinct metadata classification. It now aborts the first
read before payload consumption, leaves the host tip unchanged and does
not retry.
- Red/green: the real metadata error was swallowed by best-effort export
and native finalization incorrectly returned success. Both regressions
now pass; all 240 focused Git/restore/native-finalization tests pass. A
PostgreSQL/filesystem fault-injection test also verifies retained files,
failed run, service-owned recovery barrier, no preservation receipt and
no new wake.
- Red/green: duplicate metadata produced 47 Git process starts before
deduplication; the bounded-work regression now passes. Oversized byte
and boundary inputs fail before Git probes.
- Recovery red: both reusable lease policies exhausted recovery despite
a selected accepted successful result. The assembled
PostgreSQL/filesystem path now passes for retained and both reusable
policies, including idempotent re-admission after exhausted automatic
recovery, saved files, no agent wake, and once-only existing-result
finalization.
- Source verification controls reject ordinary reusable leases,
rejected/failed/unselected results, another physical allocation owner,
and an active host writer without changing recorded state.
- The 78-test PostgreSQL/filesystem recovery/source suite passed before
the metadata classification correction. Its new persisted
metadata-failure regression also passes. Full workspace typecheck and
build pass at final head `69f10daab2`.
- `node scripts/check-maps.mjs` and `git diff --check` pass.
- Full local `pnpm test:run` attempts did not finish. They are not
counted as passes. Early focused runs exceeded 5-second and 30-second
fixture deadlines; the final serial suite passed all 176 tests with a
30-second per-test budget in 56.8 seconds.
- Red/green: both bounded PostgreSQL projections dropped the new code in
oversized results. All 19 source/projection cases now pass, plus an
actual index-predicate test that excludes a metadata repair hold and
still selects ordinary cancelled work.
- Red/green: an oversized sender `.git/shallow` lost its error type
before host validation. The real transport test now verifies one typed
rejection, no shallow-payload read, and an unchanged host tip. All 465
command/sandbox/task-chat tests pass, and token/migration gates pass.
- Full typecheck/build pass after these final contract corrections at
`69f10daab2`; all 20 PostgreSQL source/projection/index contracts pass.
All current-head CI checks passed; Greptile is 5/5 with no unresolved
review threads. Merged #18230 supplies the CI-cache and Linux
shell-fixture baseline repairs; their duplicate changes have been
removed from this PR. The final Runner lane passed after one justified
rerun of an unchanged authentication fixture timeout (all 11 fixture
tests also pass locally). Previous CI failures and incomplete local runs
remain recorded; live deployment and retained-run recovery remain
separate verification.

## Risks

- The fallback creates a temporary shared bare clone. Metadata is
limited to 64 KiB and 256 unique boundaries, duplicate/parent probes are
cached, and Git import has a 60-second command budget plus a separate
15-second boundary-probe budget. It runs only after a missing-history
import failure.
- Incorrect boundaries could hide real host ancestry. The importer
retains available parent connections, and regressions cover that case.
- The full-bundle fallback can transfer a bundle twice. This preserves
the existing fast delta path; removing that extra transfer is outside
this correctness repair.
- Preservation eligibility expands only for completed native exports on
reusable leases. It creates no provider turn and leaves ordinary
reusable leases ineligible. Database/filesystem regressions cover result
selection and competing physical/host ownership.
- The migration rebuilds one partial index; no tables, columns or user
records change. There are no agent execution admission, model, trust,
recovery permission, workflow or lockfile changes.

## Model Used

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

## Checklist

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

---------

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

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

## Linked Issues or Issue Description

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

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

---------

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

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

## Linked Issues or Issue Description

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

**Agent or provider**

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

**Why this adapter is useful**

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

**How the agent is invoked**

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

## What Changed

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

## Verification

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

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

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 19:51:32 -05:00
Nicky LeachandPaperclip 1d571de5f9 Add shared native turn attribution boundaries (#18213)
## Thinking Path

> - Paperclip manages work performed by AI agents.
> - Native execution crosses the plugin worker, Runner, sidecar, and
durable event boundaries.
> - Existing outer spans leave repeated preparation and admission work
unattributed.
> - Optimizations need a common baseline with accurate ownership and
event meanings.
> - This change extends the existing opt-in tracing contract with
bounded timing receipts.
> - It preserves execution policy and keeps provider internals opaque
where the API provides no timing proof.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Attribution of native task preparation, retained/cold Runner handoff,
and completion-to-text work.

**Current behavior**
Worker spans use a flat provider contract. Workspace calls lack a
consistent dispatch envelope. Submitted-to-started timing is named as a
provider queue even though it includes other work. The transport does
not expose a shared breakdown of its waits.

**Proposed improvement**
Add invocation-scoped nesting, bounded numeric remote receipts,
current-run transport timing, durable receipt intervals, and distinct
completion/text milestones. Reuse the existing exporter. No latency
optimization is included.

Related public work: #17842 consolidates existing startup tracing tests;
it does not add this runtime coverage.

## What Changed

- Extend the optional SDK tracer with nested async scopes and completed
timing receipts. Keep the host responsible for parent identity,
capability checks, attributes, clocks, depth, and count limits.
- Add dispatch and bounded host-read timings for environment and
workspace providers.
- Resolve transport parents on each call so retained sessions do not
retain an earlier run's trace.
- Split cold/resume/attach/prepare/registration/command/started-event
waits. Add opt-in numeric ACPX Runner/sidecar status and prompt-start
receipts.
- Distinguish first completion request, validated tool receipt, final
result commit, first nonempty text, and event persistence. Rename the
submitted-to-started interval to match its meaning.
- Link completed earlier remote lifecycles to their host-owned observer
rather than placing them under a later polling request. Preserve
sampling, timestamp limits and budgets.
- Document the versioned coverage map, causal clock limits, and baseline
acceptance requirements.

## Verification

- Current head: GitHub CI is fully green. Standard Greptile and Apex are
both 5/5, with no unresolved review threads. Full-suite validation was
performed in CI; follow-up local validation was limited to affected
packages and tests.

- Review follow-up: early rejection, missing provider capability and
startup-parent regressions were reproduced and fixed. The affected
worker/SDK/timing set passes 128 tests; 28 timing/context tests, SDK
typecheck and direct server TypeScript checking pass. The server
typecheck wrapper reached an unrelated Runner rebuild and stopped
because Cargo was absent from PATH; full Runner/image validation remains
in CI.

- CI failure accounting: the earlier Turbo cache/force conflict and
Linux OpenCode shell assertion were reproduced and diagnosed. A direct
proc probe ruled out permissions; a portable shell comparison identified
Bash skipping BASH_ENV with stripped SHLVL and socket stdin. Upstream
#18230 now supplies the CI and ignored-stdin fixture fixes; this PR
adopts them without duplicate CI changes. The strict Linux OOM assertion
passed before this source-equivalent merge.
- Retry follow-up: the three insertion/replay/failure timing cases and
server typecheck pass. The existing database regression now asserts a
single marker across identical result replay; the current-head CI
integration gate passes.
- Upstream CI alignment: all three real-Turbo 2.11.10 integration cases
pass. The repository policy gate rejected committing a generated
lockfile; the final PR contains no lockfile edit and uses the maintained
inline stale-lockfile recovery.
- Linked-lifecycle follow-up: 44 focused host/export tests pass (three
optional SDK-dependent cases skip); SDK and server typechecks pass. The
API contract test verifies an explicit root context, host-owned observer
link and unsampled suppression.
- SDK typecheck and focused worker/invocation tests: 30 passed,
including clock changes, bounded legacy IPC, and manual-span
creation-scope parentage.
- Focused reviewed host/native/transaction-boundary checks: 44 passed.
The 86-test worker-manager suite passes after updating its exact
assertions for the host-owned timing budget found by CI. Earlier
preparation/first-text checks also passed.
- Affected server and Runner TypeScript checks pass after building local
workspace declarations.
- Merge follow-up: the profile/candidate startup subset passes 94 tests,
the four Grok source-identity checks pass, and Runner TypeScript
checking passes. A subsequent execution-factory merge passes 21 focused
timing/trace tests and server TypeScript checking.
- Pinned Rust build and the ACPX Rust subset pass. The hostile receipt
projection test passes. Source profile compatibility checks: 127 passed,
one existing skip. Grok identity checks: four passed.
- Broad transport/ACPX suite: 410 passed after building all fake
provider binaries. Earlier attempts failed on missing
Runner/fake-provider outputs; building the required fixtures resolved
those failures.
- The first CI run correctly rejected stale source attestations. After
integrating current master, Grok advances 13→14 and Copilot 84→85;
master’s historical fixtures and Pi 35 stay byte-identical. Provider
dependencies, models and permission defaults are unchanged. Identity
generation/checks now pass.
- The added real-Postgres result lock regression could not initialize
its local embedded cluster. The insertion/replay/failure unit
regressions pass. The current-head CI integration gate passes.
- Comprehensive repository checks and image builds are delegated to CI,
as requested for this instrumentation pass. No deployment, model run,
collector-ingestion proof, or latency improvement is claimed.

## Risks

The new SDK methods are optional. Legacy span calls and endpoint-off
behavior remain supported. The host accepts only closed timing names and
bounded attributes. Remote durations are anchored at local receipt;
transport/scheduling uncertainty remains explicit. Trace trees have
count/depth limits. The first rollout must inspect actual collector
exports before treating the baseline as accepted. Fresh live
qualification for the new source identities remains a rollout
requirement. Revert these commits to remove the new measurements; no
schema migration is required.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and local code/tool
execution. The exact runtime 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 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 issue
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] Standard Greptile and Apex are both 5/5, with no unresolved
findings
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 17:45:56 -07:00
DottaandPaperclip 2aa3ea47e3 Reduce restored workspace overhead and trace cache publication (#18240)
## Thinking Path

> - Paperclip runs agents in isolated workspaces.
> - A native sandbox turn must restore its workspace before the provider
starts.
> - Restored Git metadata can cause expensive work in the provider's
first snapshot.
> - Cache replay also hashes the same archives twice, and workspace
helpers open sessions that do not need output.
> - This pull request removes that repeated work and refreshes the
restored index before OpenCode starts.
> - It also adds cache-publication timings so the next measurement can
separate quota checks, lock waiting, and archive IO.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Native sandbox workspace preparation and copyback.

**Current behavior**

Cache replay validates shared archives, copies them, and validates them
again. Exit-status-only helpers use persistent sessions. A restored
checkout can make OpenCode's first snapshot recheck much of the
repository. Cache publication has an unexplained interval after archive
verification.

**Proposed behavior**

Validate the private archive copy that staging will consume. Use the
existing one-shot command path for helpers that only need an exit
status. Refresh the Git index after workspace transfer for a new native
OpenCode sandbox. Keep the refresh inside the awaited inbound barrier
and use the existing command timeout. Add nested publication spans.

**Reason and benefit**

Two matched local component pairs reduced preparation plus provider time
from 8.563/8.553 seconds to 7.313/7.511 seconds, including the refresh
cost. Two alternating remote copyback pairs reduced the median from
9.110 to 7.943 seconds. These are component results. They do not
establish an end-to-end hosted improvement.

Related: #18181 and the earlier closed #18195. This implementation uses
the existing fully awaited transfer boundary. It does not use an
optional preparation deadline.

## What Changed

- Materialize cache hits into caller-owned staging and validate those
exact bytes once. Remove incomplete copies on failure.
- Select the existing one-shot path for exit-status-only run and removal
helpers. Output-reading helpers keep their existing behavior.
- Refresh restored Git stat metadata before OpenCode starts. Enable this
only for newly acquired native OpenCode host-current workspaces. Skip
recovery and retained sandboxes. Keep dirty files unstaged, accept Git's
dirty-worktree status, and propagate real command errors.
- Trace cache capacity checks, eviction, the body after lock
acquisition, archive copy, sync, and hashing. Keep the operator endpoint
gate and bounded phase names.

## Verification

- On the rebased branch: 202 focused tests pass: 152 workspace
seed/cache/runtime tests, 27 managed command tests, and 23 native
workspace/tracing tests. Adapter TypeScript build and server typecheck
pass.
- Tests cover corrupted copies, cache changes after private
materialization, dirty working trees, quoted paths, recovery, the
awaited refresh barrier, real command failure, and company-lock
contention.
- A real-filesystem probe through the server phase mapper verified
parentage and endpoint-off behavior. A controlled lock wait stayed
outside the locked-publication span. No external export was used.
- A full local Core/Daytona replay on the pre-rebase implementation
saved its synthetic reply. It retained the pinned large public
workspace, all 209 skill files, positive Git context, and 66 tool
schemas. Both model calls stayed on sandbox loopback. Index refresh took
0.644 seconds and the first provider snapshot took 0.499 seconds. The
run took 162.004 seconds, including large laptop uploads; it is not a
hosted acceptance result or a matched end-to-end comparison. The failed
installer attempt remains recorded separately. Normal cleanup removed
all owned sandboxes.
- The current head passed 53 CI checks, with two optional skips.
Greptile is 5/5 on the exact head, with no open review threads. No
deployment or hosted latency claim is included.

## Risks

- Index refresh adds one awaited command. It uses the existing timeout.
A real Git failure stops preparation.
- Cache hits need temporary disk space for a private copy. Existing
corruption fallback and per-run recovery archives remain.
- One-shot command transport must preserve exit status and timeout
behavior across providers. The agent's native session and output-reading
helpers are unchanged.
- Local component gains are small relative to the remaining hosted
latency. Batch the fixes with the diagnostic spans; measure the actual
deployed path before claiming success.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 19:32:28 -05:00
DottaandPaperclip 6a67471644 Require publication for explicit JSON file outputs (#18228)
Extend the native file evidence rule to explicit JSON creation and publication requests, with conservative input and destination handling and a real PostgreSQL completion regression.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
canary/v2026.1030.0-canary.1
2026-10-29 19:17:46 -05:00
DottaandPaperclip d3f2a60e79 test(e2e): reuse core journeys across deployment targets (#18222)
## Thinking Path

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

## Linked Issues or Issue Description

**What existing behavior does this improve?**

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

**Current behavior**

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

**Proposed behavior**

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

**Reason and benefit**

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

**Breaking changes**

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

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

## What Changed

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

## Verification

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

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

## Risks

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

## Model Used

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

## Checklist

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

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 18:58:26 -05:00
DottaandPaperclip fe3e0f2d5f Preserve rejected native completion reports as failures (#18227)
Keep rejected declared completion reports on the existing permanent native failure path. Preserve rejection across restoration and order permanent failure ahead of terminal goal facts, goal results, and continuation while retaining the original provider terminal.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-29 18:49:01 -05:00