Commit Graph
323 Commits
Author SHA1 Message Date
Devin FoleyandPaperclip cd8c9cd07c Merge master and check registered failover cursors
Use the registered controller state when checkpoint persistence replaces the local journal with an external marker. The new regression follows registration and real checkpoint conversion before remote preparation, reproducing the stale-copy bypass on the prior guard. Current backups retain the existing integrity checks. Resolve the workflow fixture conflict by keeping each normal-route input once.

Verified 1,192 native session/execution-driver tests, ten workflow checks, fresh server declarations and the workflow project typecheck. Maintained preflight, module boundaries, whitespace and secrets/PII checks pass. Fresh CI and exact-head Apex review remain required.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-06 13:23:39 -08:00
DottaandClaude Opus 5.5 586caa5f49 fix(native): hand a shutdown-interrupted startup to the next controller (#19596)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The native Runner path runs an agent turn through a runnerd process
that the control plane owns
> - A restart of the control plane must keep the task going without a
click, if that is safe
> - A graceful shutdown closes the HTTP listener first and then drains
the heartbeat runs
> - A native run that was between provider dispatch and runnerd backend
setup in that gap failed with `local_runtime_api_listener_unavailable`,
so the drain did not see it as running and did not suspend it for the
next boot
> - This pull request makes that failure a restart detach: the run stays
running with its claim, the drain suspends it, and the next controller
adopts it
> - The benefit is that a SIGTERM in this window no longer spends a
failure and a same-run retry, and the task continues by itself

## Linked Issues or Issue Description

Refs #19530 (the same restart window, before provider dispatch).

**What happened?**

In a restart chaos replay (ACPX Claude, local runner), a
restart-recovered run got SIGTERM while
`createRunnerdBackendWithinSessionClaim` built the runnerd backend.
`resolveLocalRuntimeApiUrl()` threw
`local_runtime_api_listener_unavailable` because shutdown had already
closed the listener. The run settled `failed`. The drain then logged
`restartSuspendedRunIds: []`. The next boot used the one bootstrap
retry. A second SIGTERM hit the same window, and the task stopped at a
manual Retry.

**Expected behavior**

A run that this process cannot continue because it is shutting down is
handed to the next controller. It is not settled as failed.

**Steps to reproduce**

1. Start a native Runner task and restart the server (K1) so that
startup recovery resumes the run.
2. Send SIGTERM while the resumed run sets up its runnerd backend.
3. See the run fail with `local_runtime_api_listener_unavailable` and
the drain report no suspended runs.

## What Changed

- `server/src/runtime-api.ts`: `resolveLocalRuntimeApiUrl()` throws the
new `LocalRuntimeApiListenerClosedError` when this process had a
listener and closed it (the `listening` flag is false or the `close`
event fired). The error message stays
`local_runtime_api_listener_unavailable`, so the existing classifiers do
not change. A listener that never started still throws the plain error.
- `server/src/services/native-runtime/native-session-executor.ts`: for a
local Runner, the startup failure handler treats
`LocalRuntimeApiListenerClosedError` like a restart detach. It stops
lease renewal, keeps the claim and throws
`NativeControllerDetachedForRestartError`. Heartbeat already keeps such
a run `running`. A remote Runner keeps the same-run bootstrap retry from
#19462, because startup recovery has no process evidence to adopt a
claimed remote startup
(`native-runner-restart-preparation.integration.test.ts` still covers
that path).
- `doc/execution-semantics.md`: describe the new rule.
- Tests: a heartbeat regression that closes the real runtime API
listener before backend setup, then drains and restarts; a unit test for
the closed versus never-started listener; two `vi.mock` factories keep
the real module exports.

## Verification

- Red before the fix: `pnpm exec vitest run
src/__tests__/heartbeat-native-restart-suspension.test.ts -t listener`
failed with `restartSuspendedRunIds: []` and the run `failed`
(`local_runtime_api_listener_unavailable`, `bootstrap_retry`).
- Green after the fix: the same test passes. The drain suspends the run,
the run stays `running` with `awaiting_runner_reattach`, and the next
controller claims it and reaches the backend once.
- `pnpm exec vitest run
src/__tests__/heartbeat-native-restart-suspension.test.ts
src/http/server.test.ts
src/__tests__/server-startup-feedback-export.test.ts
src/services/native-runtime/native-session-executor.test.ts
src/services/native-runtime/native-recovered-owner-followup.test.ts`:
1333 tests pass. One timing test in `native-session-executor.test.ts`
failed once under host load average ~30 and passed alone.
- `pnpm exec tsc --noEmit -p server/tsconfig.json`: pass.
- Live, restart chaos harness, local ACPX Claude (`claude-sonnet-5`),
`--rc06-masked`, this branch at a35ec8b845 (before the remote-scope
commit 5dc63f24fb, which does not change the local path). The original
replay schedule no longer reached the window, because the task now ends
before the second fault. So I moved the faults earlier: K1 at 10 s, then
K2 as soon as the recovered server is ready.
- K1 + K2, 2 runs: both runs PASS with **R1 pass**. Each drain logged
`restartSuspendedRunIds: [<run>]` (before: `[]`). The next boot
classified the run `resume_dead_runner` and the same run completed. No
`local_runtime_api_listener_unavailable` failure.
- K1 + K2 + K2, 2 runs: each drain suspended the run. The fourth boot
blocked the run with `native_restart_recovery_blocked`, because three
restart claims used the three-attempt recovery budget. Retry then
completed the task (R3 pass). That budget count is a separate open item.
This pull request does not change it.

## Risks

- Low. The new path applies only after this process closed its own
listener, which happens only during shutdown. The run then waits for the
drain or the next boot, as for the other restart detaches.
- If shutdown does not reach the drain (for example SIGKILL after the
listener closes), the run keeps its live claim until the claim expires.
Then startup recovery handles it as a hard restart. This is the same as
any run that is running at a hard kill.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, through Claude Code
with tool use (shell, file edits, GitHub CLI). Extended reasoning on.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:10:44 -06:00
github-actions[bot]andlockfile-bot e28158b353 chore(lockfile): refresh pnpm lockfiles (#19617)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-06 21:08:43 +00:00
PaperclipandClaude Opus 5.5 0048595610 Reject failover backups behind the accepted event cursor
Check supported controller journals before copying a verified backup to a replacement sandbox. Preserve native_event_replay_conflict when a runner exit wraps the error, so stale state does not enter a retry loop. Also supply the normal image-only input in the workflow target fixture used by current master.

Verified 1,171 native session tests and nine workflow target tests. The new stale-cursor and classification cases fail on unchanged master; the workflow fixture reproduces and fixes the unset input error. Broader CI and exact-head Apex review remain required.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:58:01 -08:00
DottaandPaperclip 4d554f0821 test(runner): set default inputs in workflow target fixture (#19602)
## Thinking Path

> - Paperclip manages work performed by AI agents.
> - Its Runner support tests verify workflow authorization and target
pinning.
> - The workflow now passes two Boolean inputs to its shell guard.
> - The target fixture runs that guard with `set -u` but omits those
inputs.
> - Five cases stop on an unset variable before they reach their
assertions.
> - This change supplies the workflow's normal false defaults in the
fixture.
> - The production guard and all target-pinning assertions remain
unchanged.

## Linked Issues or Issue Description

Refs #19537, #19576.

**What happened?**

The required Runner support suite fails five `workflow-target.test.ts`
cases with `IMAGE_ONLY: unbound variable`. The real workflow supplies
`IMAGE_ONLY` and `TESTOPS_REQUESTED`. The test fixture does not supply
either value.

**Expected behavior**

The fixture uses the normal workflow defaults and reaches the target
authorization assertions.

**Steps to reproduce**

Run `pnpm exec vitest run --config tests/runner-e2e/vitest.config.ts
workflow-target.test.ts` on master
`4938a930d66846094810cbed45d2fd33c0d14c2d`.

## What Changed

- Set `IMAGE_ONLY` and `TESTOPS_REQUESTED` to `false` in the target
fixture's child environment.

## Verification

- RED: the unchanged current-master fixture had five failures and four
passes. Bash stopped on `IMAGE_ONLY: unbound variable` before target
authorization ran (220ms).
- GREEN: all nine cases pass after the one-line fixture repair (168ms).
Existing checks still reject a custom bounded target and preserve the
queued commit for scheduled and bounded manual runs.
- Local evidence uses the actual test and workflow files with installed
Vitest 5.0.3 and a temporary focused config. It omits the unrelated
provider-bundle global setup. No provider, external service, or paid
workflow runs.
- The [original required CI
failure](https://github.com/paperclipai/paperclip/actions/runs/42288042001/job/128134318743)
has the same five Bash failures. Its evidence is retained; no unchanged
retry was used.
- Whitespace checks pass. Exact head
`f1d178ad483a49f8dd087a1c6d22bf43c06a39e4` has 56 successful checks,
three expected skips, one neutral advisory status and successful Snyk.
No check is pending or failed. The [full Runner support
suite](https://github.com/paperclipai/paperclip/actions/runs/42289536842/job/128139308510),
typecheck, build and [aggregate
verification](https://github.com/paperclipai/paperclip/actions/runs/42289536842/job/128145908574)
pass. Greptile and Paperclip Review both rate this exact head 5/5, with
no findings or unresolved threads.
- Environment: macOS arm64, Node 26.4.0, Vitest 5.0.3.

## Risks

Low risk. This changes only fixture inputs for normal target selection.
It does not change the production workflow guard, branch policy,
credentials, paid execution, timeouts or assertions. Product
documentation needs no update for test-only default inputs.

## Model Used

OpenAI Codex, GPT-6 family, with repository analysis, code editing and
tool execution. The exact runtime model ID and context window are not
exposed in this session.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-06 14:52:38 -06:00
DottaandClaude Opus 5.5 02214b1a3c fix(evals): treat a job-less TestOps plan row as unassigned during registration (#19601)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Runner E2E cases run from Allure TestOps plans through
`runner-full-stack-e2e.yml`
> - #19549 added a sibling "Reliability — staging soak" plan and a
one-shot registration workflow
> - The first live `register` dispatch created the seven cases and the
plan, then stopped with `plan_job_conflict`
> - Live TestOps lists a new plan's uncovered cases as one row without a
job, and the code read that row as another job
> - This pull request treats a job-less row as "not assigned"
> - The benefit is that a second `register` dispatch can assign the plan
to the standing GitHub job and finish registration

## Linked Issues or Issue Description

Refs #19549

**What happened?**
The `runner-e2e-testops-registration.yml` `register` run on master
failed with `reliability_testops_registration_plan_job_conflict`. It had
already created the seven cases and the plan. `GET
/api/testplan/<id>/job` for that plan returned `[{"testCasesCount":7}]`.
The row has no `job` field.

**Expected behavior**
Registration treats a plan with only a job-less row as unassigned. It
assigns the plan to the standing Product regression GitHub job and reads
the assignment back.

**Steps to reproduce**
1. Dispatch `runner-e2e-testops-registration.yml` on master with
`operation=register` when no Reliability plan exists.
2. The new plan reports one job-less row.
3. Registration fails with `plan_job_conflict` before the assignment
step.

**Paperclip version or commit**
master at 744056ecc8 and later.

## What Changed

- `tests/runner-e2e/reliability-testops-registration.mjs`: add
`jobAssignments()`. It keeps the array check and ignores rows without a
`job`. Inspect, the pre-assignment conflict check and the
post-assignment read-back use it.
- `tests/runner-e2e/reliability-testops.test.mjs`: the fake TestOps now
returns the live job-less row for a new plan. A new test reproduces the
half-registered plan and checks that `register` assigns the standing job
and that the receipt becomes complete.

## Verification

- `node --test tests/runner-e2e/reliability-testops.test.mjs
tests/runner-e2e/product-regression-testops.test.mjs`: 28/28 pass.
- Red before the fix: with the old registration module, 4 tests fail,
including the new one. Green after: 13/13 in the reliability file.
- Live check after merge: dispatch `register` again. The cases and plan
already exist, so it only assigns the plan to the standing job.

## Risks

- Low risk. The change touches only the one-shot registration helper and
its tests. It does not change provider cells, launch selection or
reporting.
- A plan assigned to another job still fails with `plan_job_conflict`.
The existing test still covers that case.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code with tool use
(shell, browser read of the TestOps API response), standard 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
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:36:26 -06:00
DottaandClaude Opus 5.5 b7e28eb2f7 fix(evals): let an allowlisted manual dispatch authorize its private evidence (#19599)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Chat-feature evals run in the trusted `runner-full-stack-e2e`
workflow and keep their evidence in private history
> - A manual chat run needs authority to write that private evidence
> - Today that authority is a stored approval for the exact run ID in
`RUNNER_E2E_MANUAL_PRIVATE_APPROVALS_JSON`
> - The run ID exists only after dispatch, so every manual run stops
until a person writes the record
> - The dispatcher is already checked against
`RUNNER_E2E_ALLOWED_ACTOR_IDS`, so the second step adds friction without
a new decision
> - This pull request lets an allowlisted manual dispatch authorize its
own private evidence, as the TestOps admission already does
> - The benefit is that an allowlisted operator can start a chat eval
and it runs, while scheduled runs still never touch chat evidence

## Linked Issues or Issue Description

Refs #18134, Refs #18170

**What existing behavior does this improve?**
A manual `runner-full-stack-e2e` run with chat-feature IDs fails at
private evidence transfer unless a person first adds an approval row for
that run ID to a repository variable.

**Subsystem affected**
Runner E2E manual workflow private evidence authorization
(`manual-private-transfer.ts`, `runner-full-stack-e2e.yml`).

**Proposed change**
Derive the evidence authority from the dispatch itself, with the same
checks the TestOps chat admission uses.

## What Changed

- New `tests/runner-e2e/manual-dispatch-authority.ts`:
`authorizeManualDispatch` admits private evidence only when all of these
are true:
- The event is `workflow_dispatch` of `runner-full-stack-e2e.yml` on the
default branch, with the `manual` cadence.
  - The run attempt is `1`.
- The actor is in `RUNNER_E2E_ALLOWED_ACTOR_IDS`, the event sender is
that actor, and the triggering actor is the same person.
  - The trusted cell selection equals the dispatch's own `id` input.
- The authority binds the workflow SHA, the target SHA from the
authorize job, the run ID and the cells. Every job derives the same
identity hash.
- `manual-private-transfer.ts`: uses the TestOps authority first, then
the dispatch authority, then the stored approval. With the dispatch
authority, `prepare` records the target launcher digest instead of
comparing it with an approved digest.
- `runner-full-stack-e2e.yml`: the 14 steps that read
`RUNNER_E2E_MANUAL_PRIVATE_APPROVALS_JSON` now set
`PAPERCLIP_MANUAL_DISPATCH_AUTHORITY: v1` and pass
`RUNNER_E2E_ALLOWED_ACTOR_IDS`.
- `doc/manual-e2e-private-evidence.md`: describes the dispatch
authority. The stored-approval shape stays documented for the TestOps
catalog case workflow.
- The new file is separate on purpose. `manual-private-retention.ts` and
the other protocol files must match each target byte for byte, so
existing candidate branches keep working.

## Verification

- `vitest run tests/runner-e2e/manual-dispatch-authority.test.ts
tests/runner-e2e/manual-private-transfer.test.ts
tests/runner-e2e/manual-private-report.test.ts
tests/runner-e2e/manual-private-report-integration.test.ts
tests/runner-e2e/manual-private-policy.test.ts`: 57 tests passed.
- New tests cover one valid dispatch and rejection of: a scheduled run,
a bounded cadence, a non-allowlisted actor, an empty allowlist, a rerun
by another person, a second attempt, a non-default or different workflow
ref, a sender who is not the actor, a missing target SHA, a missing
authority switch, and cells that differ from the dispatch input. The
eight-cell limit still applies.
- A `prepare` test runs the real transfer script: a non-allowlisted
actor produces no outputs, and an allowlisted dispatch produces the
session policy and an identity that records the target launcher digest.
- Negative control: with the previous `manual-private-transfer.ts`, the
new `prepare` test fails.
- Workflow tests that read this workflow: 111 of 116 passed. The 5
failures in `workflow-target.test.ts` (`IMAGE_ONLY: unbound variable`)
also fail on unchanged `master`. `paid-runner-routing.test.mjs` passed
(7 tests).
- I did not run a live dispatch. The first live proof is a manual
dispatch of chat IDs after merge.

## Risks

- The dispatcher now vouches for the target branch. A target branch with
a changed launcher can write private evidence if an allowlisted operator
dispatches it. The protocol files must still match the trusted copies
byte for byte.
- The eight-cell limit is unchanged. The report job has eight fixed read
slots, and each read policy must fit the 2,048-character session policy
limit. Lifting the limit needs a separate change to the report sessions.
- The `runner-e2e-paid` environment still has required reviewers. That
is a repository setting and this change does not touch it.
- The authority uses `RUNNER_E2E_ALLOWED_ACTOR_IDS`, not `CODEOWNERS`.
Keep that variable aligned with the people who may start paid runs.

> 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, with tool use and code
execution in Claude Code.

## Checklist

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:26:31 -06:00
DottaandClaude Opus 5.5 744056ecc8 feat(evals): run the staging-soak reliability cases from a TestOps plan (#19549)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner full-stack E2E lane runs real Paperclip work against real
agents, and TestOps launches its standing plans
> - PR #19455 added seven staging-soak reliability cases, but no TestOps
plan or workflow lane selects them, so they run only by hand with
personal keys
> - These cases catch restart, interrupt, queue and lost-runner
regressions, so they must run from TestOps before a release with the
standard reports
> - This pull request adds a sibling "Reliability — staging soak"
TestOps plan on the existing plan-2 lane, with native OpenCode and
DeepSeek 1017 through OpenRouter as the plan profile for six of seven
cases
> - The benefit is a cheap, repeatable pre-release reliability launch
with the same Allure/TestOps results, retained report and dashboard as
plan 2

## Linked Issues or Issue Description

Refs #19455

**What existing behavior does this improve?**
The staging-soak reliability cases from #19455 run only by a manual
local command.

**Subsystem affected**
Runner full-stack E2E (`tests/runner-e2e/`) and its TestOps lane in
`.github/workflows/runner-full-stack-e2e.yml`.

**Current behavior**
No TestOps plan includes the cases. The workflow cannot select them from
TestOps. Every cell uses native Codex (`gpt-5.6-sol`) or an ACPX facade
on Daytona, which is expensive.

**Proposed behavior**
A TestOps launch of the Reliability plan runs seven cells (six DeepSeek
1017, one native Codex for steering) through the standing plan-2 path
and reports them like plan 2.

**Reason and benefit**
The cases become a first-class, low-cost, pre-release check with
retained evidence. Plan 2 keeps its 20-case qualification semantics.

**Breaking changes**
None. Plan 2 selection, reporting and history identities stay the same.

## What Changed

- **Plan choice: a sibling plan, not an extension of plan 2.** Plan 2 is
bounded at 20 standing IDs. Its `full-run` / `test-plan-2` tag needs a
complete 20-case attempt, and subset runs do not qualify it. Adding
seven cases would change that denominator and the qualification history.
The sibling plan shares the same TestOps GitHub job, selection,
admission, projection, upload and verification code. A launch selects
cases from exactly one plan (`plan_mixed` fails), and each plan has its
own full-plan size (20 or 7).
- `tests/runner-e2e/reliability-testops.mjs` (new): the mapping module.
It has seven cases, full names `paperclip.Product
E2E.everyday-workflows.<case>`, execution IDs, soak signatures and an
empty `reliabilityRegistration`. A partial, duplicate, plan-2 or
malformed registration is rejected. An empty registration makes
selection fail closed before any spend
(`product_regression_testops_reliability_unregistered` for a bootstrap,
`case_mismatch` for a TestOps launch). No TestOps IDs are invented.
- `product-regression-testops.mjs` / `-cli.mjs`: select a plan by its
case identities or by the new bootstrap input. The projection binds each
cell's own environment (`local` or `daytona`) instead of a fixed
`local`. It adds a `soak-<signature>` tag and reports `plan` and a
per-plan `fullPlan`. Plan-2 history IDs, parameters and results do not
change.
- Catalog: `runner-opencode-deepseek-1017` is now one shared fixture
with `supportedEnvironments: ["local", "daytona"]`. The OpenCode server
driver already runs on Daytona for `runner-opencode` (task-workspaces,
core-compatibility, rolling deployment); only the model differs. The
chat-feature suite stays local, and its definition hash does not change.
`everyday-workflows` gains exactly six DeepSeek plan cells (definition
version 12, 52 + 13 + 3 cells).
- Cell matrix (plan), DeepSeek 1017 on native OpenCode:
`interrupt-redirect`, `reassign-midrun` and `tree-pause-release` run on
`local`. `three-turn-revise` runs on Daytona with the per-turn lease
(S49). `long-silent-command` (S52/S52b) and `queued-across-restart`
(S55/U9) run on the Daytona warm lease.
- `queue-steer` is the one exception. It must steer an active turn, and
the OpenCode server driver declares `steering: false`, so the route
answers `steering_unsupported` and the case cannot pass. The plan uses
the existing steering-capable
`everyday-workflows.runner-codex.daytona.queue-steer` cell for it
(Greptile finding). No DeepSeek `queue-steer` cell exists. The other
native Codex Daytona cells and the ACPX facades stay selectable through
`--group reliability`, but they are outside the plan.
- `runner-full-stack-e2e.yml`: adds the `testops_plan` bootstrap input
(`product-regression` by default), sets the plan-specific bootstrap
launch name and tags, and renames two jobs to plan-neutral names. The
OpenCode steps now match `startsWith(matrix.profileId,
'runner-opencode')`, so the DeepSeek profile gets the pinned OpenCode
binary, runner TypeScript, the local Node check and the remote provider
pack. Before this change, the DeepSeek profile could not run in this
workflow. `OPENROUTER_API_KEY`, `OPENAI_API_KEY` (only for
`queue-steer`) and `DAYTONA_API_KEY` come from the same
`matrix.credentialName` and `matrix.environmentId` gates that other
cells use.
- `runner-e2e-testops-registration.yml` +
`reliability-testops-registration.mjs` (new): a trusted, master-only,
allowlisted-actor, idempotent `workflow_dispatch`. `inspect` only reads.
`register` reuses cases with the same full name, creates missing cases
and the plan, and assigns the plan to plan 2's GitHub job with plan 2's
job parameters. It writes a receipt with a ready-to-commit
`reliabilityRegistration` snippet. Only this job gets `ALLURE_TOKEN`,
and it never runs a provider cell.
- **No schedule and not per PR.** The plan runs only from a TestOps
launch or a manual dispatch. It is not in the daily or weekly cron
(`scheduledSelection` excludes it). A weekly run would add a paid
50-minute Daytona cell every week, but these signatures move with
release-risky changes, not with time.
- Docs: `EVERYDAY-WORKFLOWS.md` (matrix, environment reasons, local
coverage limits, registration steps), `README.md`, `doc/evals.md`.

### Registration still needed (requires TestOps credentials)

1. Dispatch **Runner E2E TestOps registration** from master with
`operation=inspect`.
2. Dispatch it with `operation=register`.
3. Commit the `reliabilityRegistration` snippet from the run summary
into `tests/runner-e2e/reliability-testops.mjs` in one reviewed PR.
4. Launch the plan from TestOps. Tag only a complete seven-case attempt
`full-run`.

### What local plan cells cannot reproduce

The local cells do not reproduce the Daytona-only variants: the remote
`workspace_busy` save after Stop (S47), remote stop settlement during
reassignment (S48), and a lost or replaced remote runner during a tree
hold (S50). S51 (lost runner) has no case yet. The explicit-only native
Codex Daytona extras still cover S47, S48 and S50 on a sandbox.

## Verification

- `node --test tests/runner-e2e/product-regression-testops.test.mjs
tests/runner-e2e/reliability-testops.test.mjs`: 26 pass. These tests
cover fail-closed selection, partial or duplicate registration, plan
mixing, environment binding, per-plan denominators, preserved failure
classes, the CLI select → project → verify flow for a seven-case launch,
registration idempotency and job checks, and the workflow inputs and
credential gates.
- `vitest` for `reliability-testops-catalog`,
`product-regression-testops-catalog`, `everyday-reliability` and
`catalog.test`: 98 pass. These tests bind the mapping to real catalog
cells (profile, model, environment, credentials, single attempt). They
also check that the cells stay out of `--all`, the suite, profile and
environment selectors and the daily/weekly cron. Real grader output must
survive projection.
- `pnpm test:e2e:runner:typecheck`: pass.
- `pnpm test:e2e:runner -- --list --suite everyday-workflows --group
reliability` lists 16 cells: 6 DeepSeek plan cells, 7 native Codex cells
(one is the `queue-steer` plan cell) and 3 ACPX extras. `--matrix-json`
for the DeepSeek plan IDs emits `needsDaytona=true` and three Daytona
OpenCode cells with `credentialName=OPENROUTER_API_KEY`.
- Full `pnpm test:e2e:runner:unit`: the remaining failures happen the
same way on an unchanged master checkout. They are in
`workflow-security` (3), `controller-outage`, `operating-receipts`,
`pi-*`, `private-framework-report` and `remote-native-bootstrap`. #19529
tracks that drift. This PR adds no failures.
- Not run: paid cells, a TestOps registration and a TestOps launch. They
need provider and TestOps credentials, which exist only in protected CI
environments. Catalog and projection tests are not live qualification.

## Risks

- The registration script calls TestOps APIs (`POST /api/testcase`,
`/api/testplan`, `/assign`, `/jobparameter`) through the same endpoints
as the chat catalog reconcile. Tests use fakes, not the live API.
`inspect` comes first, and `register` is idempotent.
- DeepSeek 1017 on Daytona has not run before. The first launch is the
acceptance step for those three cells.
- If a later case needs another capability that OpenCode lacks, it must
use a capable profile in the same way as `queue-steer`. The catalog test
pins the single exception.
- The OpenCode workflow conditions now match any `runner-opencode*`
profile. Today this covers `runner-opencode` and
`runner-opencode-deepseek-1017` only.
- If someone commits a bad `reliabilityRegistration`, module load fails
for both plans. A unit test rejects any committed registration that is
not empty or complete.

## Model Used

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

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:19:58 -06:00
DottaandClaude Opus 5.5 840838476a perf(runner-e2e): cut the Daytona image build critical path (#19545)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Runner Full-Stack E2E workflow tests the Runner in Daytona
sandboxes from a signed, content-addressed image
> - Every change to an audited Runner input needs a new image before a
Daytona cell can test it
> - The image job took 10 to 16.5 minutes today, and a restart chaos
campaign waits on it after each runner-side fix
> - Measurement shows two serial waits: a full Rust dependency compile
(about 5 of 6.6 minutes) and a 3.5 to 4 minute download of cached base
layers that starts only after the builder stages finish
> - There is also no way to build only the image: every dispatch reaches
a paid gate that the operator must reject
> - This pull request removes both serial waits and adds an `image_only`
dispatch input
> - The benefit is a shorter fix-to-Daytona-test loop, with every image
security check unchanged

## Linked Issues or Issue Description

**What happened?**

The `Publish verified Daytona image` job is on the critical path of the
control-plane restart chaos campaign. Builds today took 16.5 min (run
42240434011), 15 min (42253920727), 10.5 min (42259118276) and 16 min
(42265637650). Run 42264611573 failed: its RunsOn runner lost
communication with GitHub 7.6 minutes into the build step, during the
Rust compile. GitHub has no log for that job.

**Expected behavior**

A Runner source change should not recompile the locked third-party Rust
graph. Cached image layers should download while the builder stages
compile. An operator should be able to publish only the image, without a
paid gate.

**Steps to reproduce**

Read the BuildKit timeline in the logs of job 127970125495 (run
42240434011). See the stage table below.

## What Changed

- `docker/daytona-runner/Dockerfile`: compile the locked Rust dependency
graph in its own layer against placeholder targets. The layer depends
only on `Cargo.toml`, `Cargo.lock` and the crate manifest. The step
deletes the placeholder outputs and fingerprints, so the next step
always compiles the real Runner sources. The final stage still receives
only the stripped executable.
- `docker/daytona-runner/Dockerfile`: move the content-ID /
source-revision check above the two `COPY --from` steps. It does not
depend on either builder stage, so BuildKit now downloads the cached
base and CLI layers in parallel with the compile. Both copies use `COPY
--link`.
- `.github/workflows/runner-full-stack-e2e.yml`: add the boolean
`image_only` dispatch input. `authorize`, `target_lock`, `catalog` and
`daytona_image` run unchanged. Every other campaign job gets `&&
inputs.image_only != true`. `authorize` rejects `image_only` together
with TestOps inputs.
- `tests/runner-e2e/workflow-image-only.test.ts` (new): pin the job
classification, the top-level guard on each campaign job, the guard on
every protected environment, and the TestOps rejection.
- `tests/runner-e2e/README.md`: document the layer layout and the
`image_only` command.

## Verification

Measured on the same RunsOn `m7i-flex.xlarge` (4 vCPU, 16 GiB, native
x64) runner class. "Before" is master job 127970125495 (run
42240434011). "After (cold)" is this branch, job 128077687214 (run
42271236140), with no dependency layer in the registry cache yet. Its
paid gate was rejected.

| Stage | Before | After (cold dependency cache) |
|---|---|---|
| Whole image job | 16.5 min | **11.6 min** |
| Rust dependency graph | 311 s (inside one 399 s step) | 395 s (own
layer; reused from cache after a master build) |
| `paperclip-runner-core` compile | ~87 s | 65 s |
| Cached base and CLI layer download | 236 s, **after** cargo finished |
257 s, **in parallel** with cargo |
| Copy runnerd + provider pack | 20 s + 50 s | 9 s (`--link`) |
| Provider pack stage | 143 s (parallel) | 152 s (parallel) |
| Export + push | 82 s + 10 s | 81 s + 11 s |
| Dependency layer size | n/a | `target` 852 MB + registry 333 MB
(builder stage only) |

With a warm dependency cache, a Runner source change compiles only the
65 s crate step. The critical path then becomes the ~4 min cached-layer
download or the provider pack. The expected job time is about 7 to 8
min. I measure this after merge with an `image_only` dispatch (master
first, to write the cache, then a Rust-only branch change).

Disk: the instance starts with 38.76 GiB free. The dependency layer adds
about 1.2 GB uncompressed to builder storage. The final image does not
change.


- `vitest run tests/runner-e2e/workflow-image-only.test.ts
tests/runner-e2e/workflow-security.test.ts
tests/runner-e2e/daytona-image.test.ts`: the new test and all image
tests pass. Three tests in `workflow-security.test.ts` (`gates every
provider-secret job with stable actor IDs`, `keeps provider credentials
inside explicitly gated paid workflows`, `isolates private archive trust
from workflows that execute target-branch code`) fail on `origin/master`
without this change, because of `chat-catalog-testops-case.yml`. This
pull request does not change them.
- `node --test tests/runner-e2e/product-regression-testops.test.mjs`:
15/15 pass.
- No local Docker build. The Dockerfile is measured with a
branch-targeted CI dispatch whose paid gate was rejected.

## Risks

- The dependency layer keeps the Rust `target` and registry trees in a
builder-stage layer, and default-branch builds export it to the registry
cache. This adds builder disk and cache upload when `Cargo.lock`
changes. The build prints the size (`du -sk target
/usr/local/cargo/registry`).
- The dependency cache helps only after a default-branch build writes
it. Branch builds read it but never write it. This is the existing cache
policy.
- `image_only` changes the workflow, so it works only after merge to
master.
- No check is removed. Lockfile verification, cosign sign and verify,
the anonymous pull check, the provider-pack manifest match, the
default-branch-only cache write and the actor allowlist are unchanged.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, through Claude Code
with tool use (shell, GitHub CLI). Extended reasoning on.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:15:16 -06:00
Nicky LeachandClaude Opus 5.5 79c724b292 ci: run the Runner support suite as a required PR check (#19537)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner support suite (`pnpm test:e2e:runner:unit`) checks the
code behind paid Runner runs: workflow security policy, evidence
oracles, cost receipts and controller recovery.
> - Only a manual Docker Runner check ran this suite. PR CI did not run
it.
> - So changes on master broke 16 of its tests, and nobody saw it.
#19527 and #19529 fix those tests.
> - This pull request runs the suite in PR CI and makes the `verify`
check require it.
> - The benefit is that a change that breaks the suite fails on its own
pull request, before merge.

## Linked Issues or Issue Description

Refs #19527 and #19529 (both merged; they repair the suite). Also
accounts for #19533, which added the sandbox provider job.

**Merge order:** #19527 and #19529 have merged, so the suite now passes
on master. This PR can merge.

**What existing behavior does this improve?**

PR CI for `pr-trusted.yml`.

**Current behavior**

`pnpm test:e2e:runner:unit` runs only in `docker-runner-check.yml`, by
manual dispatch. Master changes broke 12–13 tests by Nov 3 and 16 by Nov
6, with no signal on any pull request.

**Proposed behavior**

A required "Runner support suite" job runs the suite on pull requests.

**Reason and benefit**

Drift fails on the pull request that causes it. Authors update
deliberate pins (profile versions, suite hashes, workflow policy) in the
same pull request.

## What Changed

- `pr-trusted.yml`: new job `verify_runner_e2e_support` ("Runner support
suite"). It uses the same steps as other trusted jobs: checkout without
credentials, setup-node directly before pnpm, the npm overrides, the
shared `setup-ci-dependencies` restore, and CI profiling. Then it runs
`pnpm test:e2e:runner:unit`. It has no secrets. Timeout: 20 minutes.
- `pr-trusted.yml`, job `verify`: the job now needs the new job and
checks its result. A failed, cancelled or wrongly skipped run fails
`verify`.
- `turbo.json`: new routing task `ci:runner-e2e-support`. Its inputs are
`server/**`, `cli/**`, `packages/**` and `ui/**`. Changes to `tests/**`,
`scripts/**` and `.github/**` already force full CI, so they also run
the job.
- `.github/ci-task-matrix.json`: one lane for the new job.
- Tests: `ci-plan.test.mjs`, `ci-profile.test.mjs`, `e2e-shard.test.mjs`
and `workflow-security.test.ts` now include the new job. A UI component
change now selects this one Runner task. The suite imports UI modules
and checks that catalog-listed UI files stay tracked in git, so UI
changes can break it.
- CI profiling: when `PAPERCLIP_CI_PROFILE` is on, the suite's Vitest
config adds `scripts/ci-profile/vitest-reporter.mjs`, and `run-unit.mjs`
runs the Node tests through `scripts/ci-profile/node-test.mjs`. So the
job uploads per-test timings, like the root and Runner package suites.
The launcher loads the profiling helper only after its "Vitest is not
installed" check.
- `tests/runner-e2e/README.md`: says that PR CI runs the suite, and that
deliberate pin changes go in the same pull request.

## Verification

- `node --test .github/scripts/tests/*.test.mjs scripts/ci/*.test.mjs
scripts/__tests__/e2e-shard.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs
scripts/__tests__/runner-release-crate-cache.test.mjs`: 830 passed, 3
failed. The same 3 fail on the base branch without this change. They
need local tools that are not on this Mac.
- A local run with `PAPERCLIP_CI_PROFILE=true` wrote per-test and
per-file timing records for Vitest and for Node. Without profiling,
output and exit codes do not change. Both `unit-launcher.test.mjs` tests
pass.
- The aggregate test now covers the new job: `verify` rejects it when it
fails, is cancelled, or is skipped while selected.
- The pnpm bootstrap policy tests in `workflow-security.test.ts` pass
with 10 setups in `pr-trusted.yml`.
- On this PR's merged tree (`80b526d697`, master plus this PR): `pnpm
test:e2e:runner:unit` passed, Vitest 320 files (6,830 tests) and
node:test 373, in 58s. It also passes on master `4c1f629c31`.
- Suite runtime on a 10-core Mac: 43–63s. With `--maxWorkers=4`: Vitest
118s, about 490s of CPU in total. On a 4-vCPU GitHub runner I expect
about 3–4 minutes for the tests and 1–2 minutes for setup. The job runs
in parallel with the longer test shards, so it should not lengthen CI.
- `pr.yml` calls `pr-trusted.yml@master`. This PR's own CI does not run
the new job. The first real CI timing comes from the first pull request
after merge.

## Risks

- More runner minutes: one extra job on most pull requests (all except
documentation-only ones).
- The suite has not run on Linux CI recently: old `docker-runner-check`
logs have expired. A Linux-only failure would show up on the first pull
requests after merge. The job can be removed from the `verify` list
quickly if needed.
- #19229 removes `version: 9.15.4` from the pnpm steps in this file.
Whichever PR merges second needs a small rebase.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), by Anthropic, in Claude Code with
tool use (shell, file edits, git, 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-11-06 11:50:42 -08:00
Nicky LeachandClaude Opus 5.5 4c1f629c31 test(evals): repair the Runner support suite after master drift (#19529)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner support suite (`pnpm test:e2e:runner:unit`) tests the
code behind paid Runner qualification: workflow security policy,
evidence oracles, cost receipts and controller recovery.
> - PR CI does not run this suite. Only a manual
`docker-runner-check.yml` run does.
> - So deliberate changes on master broke its tests, and nobody saw it.
There were 12–13 failures on Nov 3 and 16 on Nov 6.
> - This pull request finds the master change behind each failure and
fixes the side that is wrong. No security check becomes weaker.
> - The benefit is that the suite passes on master again (with #19527),
so it can become a required check.

## Linked Issues or Issue Description

Refs #18516, #18625, #18983, #18325, #19265, #18994, #17009, #19195.
Companion PR: #19527 (the one workflow fix).

**What happened?**

At master `543aa4d331`, `pnpm test:e2e:runner:unit` had 16 failures in 8
files. At `98ebeefbc9` I saw 15 in 7 files. The two embedded-Postgres
files passed in every run I made, and the 256MiB packaging test timed
out once.

**Expected behavior**

The suite passes on master. Each test still checks the rule it was
written for.

**Steps to reproduce**

Run `pnpm install`, then `pnpm test:e2e:runner:unit` on master.

## What Changed

Each failure, its cause, and the fix:

- **`workflow-security.test.ts`: chat catalog workflows hold provider
keys and use `runner-e2e-private-paid`.** This is a deliberate policy.
#18516 admitted guarded, pinned-source chat TestOps cells, with special
checks. #18625 removed the pilot workflows and their checks. It did not
move the checks to the full-catalog workflows from #18542 and #18647,
which use the same trust model. The fix adds `chat-catalog-testops.yml`
and `chat-catalog-testops-case.yml` to the provider-key allowlist. It
also brings back the #18516 checks, adapted to the caller plus
reusable-workflow layout:
- The cell is `workflow_call` only. Its single caller is the master-only
dispatcher.
- The trusted guard runs before the pinned candidate checkout.
`verify-selection` runs before each provider key.
- The paid job never sees `ALLURE_TOKEN`. The report job runs in
`runner-e2e-private-history` and has no candidate checkout. The upload
job has no private environment and no secret except `ALLURE_TOKEN`.
- Provider keys appear only in the two caller jobs. Those jobs need
`authorize, select, build` and pass the guard's `target_sha`.
- I mutation-tested this: an `ALLURE_TOKEN` in the paid job fails, and a
second caller workflow fails.
- **`workflow-security.test.ts`: `ref: ${{ github.sha }}` 6 vs 4,
`persist-credentials: false` 12 vs 10.** #18983 added two trusted
TestOps jobs (`testops_selection`, `publish_testops`). Both check out
reviewed code next to the TestOps token. This is the safe direction. The
counts are updated. A new check makes sure both jobs check out only
`github.sha`, do not install the candidate lockfile, and use no secret
except `ALLURE_TOKEN`.
- **`pi-file-evidence.test.ts` (4 tests): "one observed provider
validation execution".** #19265 deliberately changed the ACPX tool
normalizer to keep the latest concrete title. Pi's shell call now goes
from `bash` to the exact command. The ACPX sidecar uses this normalizer,
so the oracle would also reject real Pi runs. The oracle now accepts one
change only, from `bash` to the exact validation command, with no change
back. It also counts every completed `execute` call, whatever its name.
This is stricter than before: a refined title cannot hide a second shell
command. New mutations cover a regressed name, a different command, and
an extra call that has its own command name. The retained 44-row real
stream still passes.
- **`pi-controls-evidence.test.ts`: Pi profile 37.** #18325 deliberately
reset Pi to profile 37. The pin and the `pi-native` suite hash are
updated. I checked that the old hash comes back exactly when the version
is set to 36. So the version is the only change.
- **`controller-outage.test.ts`: 1 continuity cell, not 2.** #18994
deliberately limited this lane to providers with managed warm sessions.
The test now expects exactly `runner-codex`.
- **`operating-receipts.test.ts` (3 tests): "Operating overhead
allowance needs review".** This is a time bomb from #17009. The fixture
allowance was valid from Oct 1 until Nov 1, 2026. `admitAttempt` reads
the real clock. The allowance window is limited to 31 days, so a longer
fixture is not possible. These tests now pin only `Date` to the fixture
time. Timers and the filesystem stay real. I ran the full suite with the
clock moved to Dec 15, 2026, and found no other date-bound failures.
- **New file `private-trust-workflow-security.test.ts`.** The private
archive trust test, the chat catalog checks and the full-stack TestOps
job checks moved here from `workflow-security.test.ts`. That file would
have crossed 1,000 lines. It is now 970 lines. The checks did not
change.
- **`remote-native-bootstrap.test.ts`: cannot load
`@paperclipai/plugin-sdk`.** Since #19195, server code under test
imports the built plugin SDK. `run-unit.mjs` now runs
`scripts/ensure-plugin-build-deps.mjs` first, as `test:run:general`
already does. This step is cached.
- **`private-framework-report.test.ts`: 256MiB packaging test timed
out.** It takes about 10s alone and more than 30s with the whole suite
running in parallel. It now has a 120s budget.
- **`controller-database.test.ts`,
`controller-recovery-observer.integration.test.ts`: no change.**
Embedded Postgres started and both files passed in all my runs. The
earlier failures look like local resource problems.

## Verification

- Combined check (this branch plus #19527, on master `5d25117ffa`):
`pnpm test:e2e:runner:unit` — Vitest 317 files passed (6,815 tests, 3
skipped), node:test 373 passed, 0 failed. It took 63s on a 10-core Mac.
- `pnpm test:e2e:runner:typecheck` — passed.
- This branch alone fails only the two pnpm-setup tests that #19527
fixes.
- Focused files: `pi-file-evidence` 75 passed, `pi-controls-evidence` 72
passed, `operating-receipts` 12 passed, `workflow-security` 14 of 16
passed (the other 2 pass with #19527), `private-trust-workflow-security`
3 passed, `remote-native-bootstrap` 71 passed.

## Risks

- Low risk. Only test files, one evidence oracle under
`tests/runner-e2e/`, and the suite launcher change. No product code
changes.
- The Pi oracle change affects how paid Pi file qualification is graded.
It accepts the old and new title shapes, and it is stricter about extra
shell calls. A live Pi qualification run would confirm it on real
Rust-normalized events. I did not run one, because it is paid.
- The chat catalog policy is the same as #18516. Under that design, the
pinned candidate source runs in `runner-e2e-private-paid` with
`id-token: write`. The guards above limit who can start it and which
source runs. This PR does not change that trust model.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), by Anthropic, in Claude Code with
tool use (shell, file edits, git, 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-11-06 11:26:44 -08:00
DottaandClaude Opus 5.5 7afb57c022 test(runner-e2e): repair restart-cell harness drift (#19538)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Runner Product E2E suite proves that agent work survives a
control-plane restart
> - A restart chaos campaign found three restart cells that fail in the
test harness, not in the product
> - A harness failure hides the real restart result, so the campaign
cannot classify these cells
> - This pull request repairs the harness drift in those cells and names
the one failure the harness cannot prevent
> - The benefit is that these cells now test restart behavior, or fail
with a clear cause

## Linked Issues or Issue Description

Refs #14811 (connector setup became one screen). Refs #19475
(completion-update restart fixture).

**What happened?**
1. `lifecycle-baseline.runner-codex.local.tool-review-restart` clicked a
"Save and continue" button. #14811 removed that button. The cell failed
during setup. After that fix, the cell also failed after the restart:
the expanded review card does not survive the post-restart reload, so
"Approve & run" was not visible.
2.
`local-session-integrity.runner-acpx-claude.local.structured-question-restart-resume`
failed with `page.goto: net::ERR_ABORTED` after the controller restart.
The old document's Vite client reloads when the replacement server
starts, and this aborts the test navigation. The code tolerated only
`TimeoutError`.
3.
`completion-updates.runner-acpx-claude.local.handoff-completion-restart`
waited for the source agent to run an instructed wait command. Claude
replied without the command (2/2 attempts), so the restart never
occurred. The cell then failed with a generic timeout.

**Expected behavior**
Each cell reaches its restart boundary and tests restart behavior. If
the boundary cannot be reached, the cell names the cause.

**Steps to reproduce**
Run `pnpm test:e2e:runner -- --max-parallel 1 --max-automatic-retries 0
--id <cell>` for each cell above on `master`.

## What Changed

- `tests/runner-e2e/connection-reviews.ts`: accept the one-screen "Check
link" step and the older "Save and continue" step. This uses the same
regex approach as `connection-flow.ts`.
- `tests/runner-e2e/runner.spec.ts` (tool review): click "Review
request" after the restart reload, on the document that acts on the
card.
- `tests/runner-e2e/chat-restart.ts`: add `gotoAfterServerRestart`. It
retries only `net::ERR_ABORTED`, within the caller's deadline and at
most 5 attempts. It still accepts `TimeoutError`. It rethrows all other
errors. The structured-question restart uses it. The existing sentinel
and durable-state assertions still prove the new document.
- `tests/runner-e2e/completion-updates.ts` and
`completion-update-flow.ts`: add `completionRestartGateSkipped` and
`completionRestartGateTimeoutDetail`. The gate poll stops at once with
`restart boundary not reached (agent skipped gate)` when no completion
turn is active and the turn that carries this task's Done facts
(`chatCompletionUpdates`, as in `completionDelivery`) succeeded or
published its reply before the gate reports `waiting`. A failed or
cancelled turn is not blamed on the agent, because delivery can retry
it; the timeout detail names it instead. The post-restart chat
navigation now uses `gotoAfterServerRestart`.
- A fixture-level gate is not possible without a product hook. The
native run finalizer publishes the completion reply inside its own
transaction, through the issue service closure. The isolated-server
entrypoint can patch only class prototypes and HTTP responses, and the
reply uses no tool call or HTTP request.
- `tests/runner-e2e/README.md`: document the skipped-gate failure.
- Docs: use `pnpm --filter @paperclipai/paperclip-runner run
build:runner-binaries` in `tests/runner-e2e/README.md`,
`tests/restart-chaos/README.md`, `tests/restart-chaos/main.ts` and
`doc/DEVELOPING.md`.
- No product code changes.

## Verification

- Unit: `pnpm exec vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/chat-restart.test.ts
tests/runner-e2e/completion-updates.test.ts
tests/runner-e2e/connection-reviews.test.ts` (36 passed).
- Typecheck: `node scripts/typecheck-test-projects.mjs tests/runner-e2e`
passed.
- Live cells, local, `--max-parallel 1 --max-automatic-retries 0`,
macOS, load average 35–65:
- `lifecycle-baseline.runner-codex.local.tool-review-restart`: PASS
(first run found the review-card reload drift, fixed in the second
commit).
-
`local-session-integrity.runner-acpx-claude.local.structured-question-restart-resume`:
PASS. A first attempt failed before the restart with `PRP command
session.open timed out` at load ~36 (environment).
-
`completion-updates.runner-acpx-claude.local.handoff-completion-restart`:
FAIL as designed, twice (before and after the review fix), with `restart
boundary not reached (agent skipped gate): completion turn … ended
succeeded without the reference gate reporting waiting`. Claude skipped
the wait both times, so this cell still does not exercise a restart.

## Risks

- Low risk. Test harness and docs only.
- The navigation retry could hide a real abort. It is limited to
`net::ERR_ABORTED`, 5 attempts and the deadline, and the test still
asserts that a new document loaded.
- The ACPX Claude completion restart cell still does not exercise a
restart when the agent skips the gate. It now reports this cause by
name.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edit, browser test runs).

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:59:54 -06:00
Devin FoleyandPaperclip fd4b197f83 fix(ui): hide runner selection during agent setup (#19517)
## Thinking Path

> - Paperclip lets people manage AI agents for work.
> - Agent setup connects a harness, model, account, and computer.
> - The system already selects a qualified runner for a new agent.
> - Setup still asks users to select that internal runner.
> - The runner dropdown can be the only field in Advanced.
> - This PR removes the dropdown and hides an empty Advanced section.
> - Users keep their saved execution settings and see fewer setup controls.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Agent creation, onboarding, built-in agent setup, company import, and agent configuration.

**Subsystem affected**

The UI, setup error messages, tests, and Storybook fixtures.

**Current behavior**

Users can select a runner from a dropdown. Some setup screens place only that dropdown in Advanced. Errors can direct users to that control.

**Proposed behavior**

Remove runner dropdowns from setup and configuration. Use the existing automatic selection for new agents. Retain saved runner settings. Show Advanced only when other fields remain.

**Reason and benefit**

Users can configure agents without an extra internal execution choice. Setup also avoids an empty Advanced section.

**Breaking changes**

Users can no longer select a runner through these UI dropdowns. The API and CLI retain their runner options. Existing agents keep their saved execution settings.

**Additional context**

Related: [Default new agents to the qualified runner for their harness](https://github.com/paperclipai/paperclip/pull/15422). This PR changes the existing setup UI. It adds no harness or runtime default. The master merge retains the custom gateway placement from [#19510](https://github.com/paperclipai/paperclip/pull/19510).

## What Changed

- Remove the shared runner dropdown and its setup/configuration callers.
- Hide Advanced when it has no remaining fields. Keep command and argument settings where supported. Preserve custom gateway setup under Advanced on the Claude and OpenAI API key paths.
- Keep setup failures visible and keep the retry action outside the removed control.
- Update errors and documentation that referred to the removed dropdown.
- Update component tests and Storybook fixtures for the new UI states.
- Make Legacy first-task evals resume an API-configured setup record. Record that path separately from fresh automatic onboarding.

## Verification

- Latest master integration (`187c0f6d6e5`): 276 onboarding/provider-connection tests passed across six files. UI typecheck and build passed. Token gates, query-error rendering checks, and the Storybook catalog check passed. The conflict resolution retains master's bounded connection tests and cancellation while removing the obsolete runner instruction. The first test command used the wrong working directory and failed before collecting tests; the corrected invocation from `ui/` passed.
- Earlier branch verification passed: full workspace build and typecheck, 1,037 focused UI/service tests, 49 heartbeat provider contract tests, eval typecheck, and 30 map/catalog tests.
- The full local `pnpm test:run` run passed all six chat integration shards (1,931 tests). It was stopped for the master merge before the complete suite finished. The [complete CI run](https://github.com/paperclipai/paperclip/actions/runs/42264662642) passed on the previous head `72e1699`.
- Current head `a097c8369d079c839e78661a2206cfa62c5210e0`: [full CI](https://github.com/paperclipai/paperclip/actions/runs/42273168268) passed. PR checks total 55 passed and 3 skipped, with none failed or pending. Greptile reviewed this head at 5/5 with no actionable findings or unresolved review threads.
- Live browser/provider evals have not run. The Legacy eval change has no live qualification claim.

## Risks

- Removing the dropdown changes the setup UI. Existing API and CLI runner choices remain available.
- Conditional Advanced sections must retain valid command and argument fields.
- Legacy first-task evals now prove setup resumption. They do not prove the fresh-agent automatic default.
- No schema change or data migration is included.

## Model Used

OpenAI `gpt-6.1-sol`, through Codex in T3 Code. Reasoning effort: `xhigh`. The model used file editing, shell commands, and test tools. The harness does not expose the context window size.

## Checklist

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-06 10:58:42 -08:00
DottaandClaude Opus 5.5 187c0f6d6e fix(runner-e2e): prepare the artifact oracle for every suite that runs it (#19518)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Runner Full-Stack E2E workflow runs paid Daytona restart cells
for the control-plane restart chaos campaign
> - Manual run 42243751291 failed
`daytona-restart-continuity.runner-codex.daytona.recover-controller`
before task creation: `docker version` timed out after 10 seconds in the
artifact oracle preflight
> - The everyday flow requires the Python artifact oracle by case alone
(`requiresEverydayArtifactOracle(caseId)`). The workflow step that
starts Docker and pulls the oracle image also filters by suite, so
suites that reuse `recover-controller` skip it
> - On a cold RunsOn host the first `docker version` takes about 20
seconds (the everyday cell in the same run shows this), so the 10-second
preflight fails when the workflow step did not run first
> - This pull request gates the oracle step by case only, which matches
the runtime requirement
> - The benefit is that the Daytona restart cell reaches task creation
instead of failing in setup

## Linked Issues or Issue Description

**What happened?**

Run https://github.com/paperclipai/paperclip/actions/runs/42243751291
job `daytona-restart-continuity.runner-codex.daytona.recover-controller`
failed with `Artifact sandbox qualification failed before task creation:
... docker version ... timed out after 10 seconds`. The job log shows no
"Prepare pinned Python artifact oracle image" step.

**Expected behavior**

Every cell whose flow runs the artifact oracle prepares Docker and the
pinned oracle image before paid execution.

**Steps to reproduce**

Enumerate `runnerMatrix` cells where
`requiresEverydayArtifactOracle(task.id)` is true. The cells in
`daytona-restart-continuity`, `rolling-web-deployment`,
`rolling-web-deployment-warm` and `remote-workspace-storage` do not
match the old workflow condition.

## What Changed

- `.github/workflows/runner-full-stack-e2e.yml`: the "Prepare pinned
Python artifact oracle image" step is now gated by `matrix.caseId` only.
The suite filter is removed.
- `tests/runner-e2e/codex-ci-sandbox.test.ts`: the oracle gate test now
checks every catalog cell, not only `everyday-workflows` cells, and
rejects a suite filter.
- `tests/runner-e2e/workflow-security.test.ts`: the pinned condition
string follows the new gate.

## Verification

- Red: with only the test change, `npx vitest run --config
tests/runner-e2e/vitest.config.ts
tests/runner-e2e/codex-ci-sandbox.test.ts` fails on `prepares the
artifact oracle for exactly the stories that execute downloads`.
- Green: with the workflow change, the same command passes (13/13).
- `tests/runner-e2e/workflow-security.test.ts` locally shows the same 5
failures before and after this change (`pr-trusted.yml` step counts and
`chat-catalog-testops-case.yml` credential checks). They do not involve
this step.
- Live proof: a narrow manual dispatch after merge.

## Risks

- Low risk. Cells in four more suites now run a Docker version check, a
pinned image pull and an inspect before paid execution. This adds about
20 to 30 seconds per cell. The image is pinned by digest. The step has
no secrets.

## Model Used

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

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:40:12 -06:00
Nicky LeachandClaude Opus 5.5 35280516c0 fix(ci): set up pnpm in the Vitest selection job like other trusted jobs (#19527)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Trusted CI workflows set up pnpm in a fixed way. Node comes first,
and npm audit, fund and update-notifier calls are off.
> - A policy test in the Runner support suite checks every pnpm setup in
`pr-trusted.yml` for this shape.
> - PR #18348 added a pnpm setup to the new Vitest selection job. That
setup did not have the npm overrides, and setup-node was not directly
before it.
> - PR CI does not run the Runner support suite. So the policy test
failed on master, and nobody saw it.
> - This pull request gives the selection job the same pnpm setup as the
other eight jobs.
> - The benefit is that every trusted pnpm setup follows one rule again,
and the policy test passes.

## Linked Issues or Issue Description

Refs #18348 (added the job). Refs #18625 (its description noted the
"nine bootstraps where eight are expected" failure). Related: #19229
also edits the pnpm steps in `pr-trusted.yml`.

**What happened?**

`pnpm test:e2e:runner:unit` fails on master in two tests: "keeps pnpm
bootstrap registry telemetry out of trusted workflow setup" and
"installs a modern Node runtime before every trusted pnpm bootstrap".
`pr-trusted.yml` has nine pnpm setups. The ninth, in `test_selection`,
has no `NPM_CONFIG_AUDIT`, `NPM_CONFIG_FUND` or
`NPM_CONFIG_UPDATE_NOTIFIER` override. The step directly before it is
the eligibility check, not setup-node.

**Expected behavior**

Every trusted pnpm setup has the three overrides, and setup-node is the
step directly before it.

**Steps to reproduce**

Run `pnpm test:e2e:runner:unit` on master. Read the two failures above.

## What Changed

- `pr-trusted.yml`, job `test_selection`: add "Setup Node.js for pnpm
bootstrap" directly before "Setup pnpm". Both steps use the existing
eligibility condition. The pnpm step now sets the three npm overrides.
Both actions keep their pinned SHAs, with version comments added.
- `tests/runner-e2e/workflow-security.test.ts`: the expected count of
pnpm setups is now set per workflow: 8 for `runner-full-stack-e2e.yml`
and 9 for `pr-trusted.yml`. The checks on each setup do not change.

## Verification

- On this branch, the two pnpm tests in `workflow-security.test.ts`
pass. Before this change, they failed with "expected 8, got 9".
- The other three failures in that file are fixed separately in the
companion PR that repairs the rest of the suite.
- `node --test scripts/ci/test-selection-workflow.test.mjs`: 4 passed.
- The workflow parses as YAML. The `test_selection` steps are now:
checkout, setup-node, eligibility check, setup-node for pnpm, setup
pnpm, restore dependencies, select, upload, publish.
- `pr.yml` calls `pr-trusted.yml@master`. So this PR's own CI runs the
master copy of this workflow. The change runs in CI only after merge.

## Risks

- Low risk. The new setup-node step runs again with the same Node 24
version. It adds about one second when selection is eligible. When
selection is not eligible, both steps are skipped, as before.
- `test_selection` has `continue-on-error: true`. If the new steps fail,
the original test matrix still runs.
- #19229 removes `version: 9.15.4` from every pnpm step in this file. If
both PRs merge, the second one needs a small rebase on this step.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), by Anthropic, in Claude Code with
tool use (shell, file edits, git, 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-11-06 10:14:44 -08:00
DottaandClaude Opus 5.5 a434edf991 fix(runner-e2e): treat macOS EPERM from a zombie-only process group as exited (#19470)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The runner E2E suite restarts the Paperclip server to prove that
agent work recovers after a controller restart
> - The restart supervisor in `tests/runner-e2e` owns the server process
tree and escalates to SIGKILL when graceful stop takes too long
> - On macOS, `kill(-pgid)` returns EPERM, not ESRCH, when every member
of the group has exited but is not reaped yet
> - The supervisor treated that EPERM as fatal, so a server that exited
at the same moment as the SIGKILL escalation aborted the restart with
"Owned tree cleanup incomplete: Error: kill EPERM"
> - This pull request makes the supervisor re-inspect the process table
on EPERM and skip the group only when no running member remains
> - The benefit is that restart recovery cases no longer fail on a
harmless exit race on macOS, while a real permission failure still fails
cleanup

## Linked Issues or Issue Description

No public issue exists. This describes the bug.

**What happened?**
The runner E2E cell
`everyday-workflows.runner-codex.local.recover-controller` failed on
macOS with failure class `cleanup_failure`: "Stopped waiting for
isolated server restart ...: Owned tree cleanup incomplete: Error: kill
EPERM". The server log shows that the graceful stop took 30 seconds, the
supervisor sent SIGKILL, and the server exited with code 0 in the same
instant. The restart did not start, so the case never checked recovery.

**Steps to reproduce**
1. On macOS, fork a child that calls `setpgid(0, 0)` and exits. Do not
reap it.
2. Call `killpg(child, SIGKILL)`. The kernel returns EPERM (errno 1),
not ESRCH. After the reap, it returns ESRCH.
3. In the runner E2E supervisor, any group that becomes zombie-only
between the `ps` inspection and the signal causes the same EPERM, which
the code rethrows.

**Expected behavior**
A group whose members have all exited counts as stopped, the same as
ESRCH. EPERM stays fatal while a running member remains.

**Environment**
macOS 26.5 (Darwin 25.5.0), arm64, Node 26.4. The behavior is the same
with and without the Claude Code sandbox.

## What Changed

- `tests/runner-e2e/process-tree-owner.ts`: on EPERM from a group
signal, read a fresh process table. Skip the group (as with ESRCH) only
when it has no running (non-zombie) member. Otherwise rethrow.
`signalSnapshot` is now async.
- `tests/runner-e2e/process-tree-owner.test.ts`: two regressions. One
covers a group that becomes zombie-only when signaled. One proves that
EPERM stays fatal while a running member remains.
- `tests/runner-e2e/README.md`: document the EPERM rule next to the
existing zombie rule.

## Verification

- Red before the fix: `node node_modules/vitest/vitest.mjs run --config
tests/runner-e2e/vitest.config.ts
tests/runner-e2e/process-tree-owner.test.ts` failed with `promise
rejected "Error: kill EPERM"`.
- Green after the fix: `process-tree-owner.test.ts`,
`server-stop.test.ts`, and `process-tree.test.ts` pass (35 tests). `pnpm
test:e2e:runner:typecheck` passes.
- Kernel behavior: a Python fork probe on this Mac shows that `killpg`
on an unreaped zombie group returns EPERM, both inside and outside the
sandbox.
- Live cell: `pnpm test:e2e:runner -- --max-automatic-retries 0 --id
everyday-workflows.runner-codex.local.recover-controller` on macOS. The
fixed revision passed. The server stop escalated to SIGKILL, the
replacement server started, and the run recovered. See the comment below
for the second rerun.

## Risks

- Low risk. The change is in the test harness only.
- EPERM is ignored only after a fresh inspection shows that no running
process holds that group ID. A process group ID cannot be reused while
zombie members still hold it, so the supervisor does not signal or skip
an unrelated group.
- The extra `ps` read runs only on EPERM.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edits). Default context window.

## Checklist

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:48:52 -06:00
DottaandClaude Opus 5.5 2b2004bf50 test(runner-e2e): gate completion briefs inside the run's own task directory (#19475)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent Chat returns delegated-task completions to the chat that
started them, and the runner E2E `completion-updates` suite checks this
with real providers
> - The restart cell
(`completion-updates.runner-codex.local.handoff-completion-restart`)
failed before its server restart with "Timed out waiting for worker
waiting while originating chat is idle"
> - Since project-optional task workspaces (#15749), a task in a project
without a workspace runs in its isolated task directory. A native chat
runs in its isolated conversation directory. Native Codex can read only
that directory.
> - The fixture still wrote its brief wait scripts into the managed
project workspace and the agent home. Codex got EPERM on both scripts,
wrote the note from the task record, and finished. The worker never
reached the gate, so the setup poll timed out.
> - This pull request makes the waits name only cwd-relative files and
publishes each brief into the run's own isolated task directory
> - The benefit is that the restart cell reaches its real boundary again
(durable Done, source provider held at the gate, server restart) and
tests restart recovery instead of a stale fixture path

## Linked Issues or Issue Description

**What happened?**
The runner E2E cell
`completion-updates.runner-codex.local.handoff-completion-restart` timed
out in setup. The run ledger shows both agents report
`permission_denied` (EPERM) for `node .../wait-for-brief-*.cjs`. The
worker run cwd was `<instance>/isolated-workspaces/<company>/<issue>`.
The fixture wrote the script to the managed project workspace and the
agent home.

**What did you expect to happen?**
The worker waits at the brief gate while the chat is idle. Then the cell
releases the brief, holds the completion reply at its gate, and restarts
the server.

**Steps to reproduce**
`pnpm test:e2e:runner -- --max-automatic-retries 0 --id
completion-updates.runner-codex.local.handoff-completion-restart` on
master `6cafcaf89b`.

**Classification**
Test defect. The failure happens before the restart. Workspace isolation
is the intended product behavior.

## What Changed

- `tests/runner-e2e/chat-stories.ts`: add `workspaceChatBrief(nonce,
timeoutMs)`. It returns a bounded `node -e` command that reads and
writes only cwd-relative files, plus `at(dir)` to find the gate and
ready files in a workspace.
- `tests/runner-e2e/completion-update-flow.ts`: the worker and
completion instructions use that command. The fixture reads readiness
from, and publishes briefs to, `isolated-workspaces/<company>/<issue>`
for each delegated task and the source chat. The setup poll state now
records the worker run cwd. Cleanup releases every wait that is still
open.
- `tests/runner-e2e/chat-stories.test.ts`: regression test. It runs the
command from a temporary cwd, checks that the command names no host
path, and checks the nonce and timeout bounds. It was red before the
helper existed.
- `tests/runner-e2e/catalog.ts`: bump the `completion-updates`
definition to version 28 and set `workerBriefWorkspace:
"run-isolated-task-directory"`.
- `tests/runner-e2e/README.md`: describe the new brief location.

## Verification

- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/chat-stories.test.ts
tests/runner-e2e/completion-updates.test.ts
tests/runner-e2e/catalog.test.ts`: 108 passed.
- Live cell, native Codex `gpt-5.6-sol`, local runner: `pnpm
test:e2e:runner -- --max-automatic-retries 0 --id
completion-updates.runner-codex.local.handoff-completion-restart`.
Results are in the Verification comment below.
- Two earlier local attempts in this worktree failed in setup with
`harness_test_failed`. The worktree did not have a built
`paperclip-runnerd`. After `pnpm --filter @paperclipai/paperclip-runner
build`, the cell passed.

## Risks

- Low risk. The change is in test fixtures only. No product code
changes.
- The idle, busy, and multiple cells share this flow. They now also use
the isolated task directory. That is the same directory the product
selects for these tasks.
- The agent must run the inline command from its cwd. The instructions
say this, and the command fails closed (no gate) if the agent runs it
elsewhere.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edits). Default context window. Extended reasoning
on.

## Checklist

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:32:50 -06:00
DottaandClaude Opus 5.5 a12fcb8f26 fix(runner-e2e): find saved slugify source in a workspace project folder (#19471)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runner E2E everyday `recover-controller` case proves that a task
survives a control-plane restart.
> - The case waits for an active run with a saved `slugify.py` before it
kills the controller.
> - The harness looked for `slugify.py` only at the workspace root.
> - The task brief asks for `slugify.py` "in the project workspace". It
does not ask for the root. ACPX Claude saved it in
`slugify-tool/slugify.py`.
> - The harness timed out before the restart, so the case did not test
restart recovery at all.
> - This pull request makes the harness find the saved source in a
bounded set of project folders.
> - The benefit is that the case reaches its real fault boundary for
agents that make a project folder.

## Linked Issues or Issue Description

**What happened?**
The local cell
`everyday-workflows.runner-acpx-claude.local.recover-controller` failed
with "Timed out waiting for active run with saved source". The agent
finished the task and delivered a correct ZIP. It saved `slugify.py` in
`<workspace>/slugify-tool/`. The harness read only
`<workspace>/slugify.py`, so it never saw the saved source. It also
recorded `saved-source-unavailable-at-final-capture`. The controller
restart never happened.

**Expected behavior**
The harness finds the source that the agent saved in the project
workspace. Then it kills the controller while the run is active and
grades the recovery.

**Steps to reproduce**
1. Run `pnpm test:e2e:runner -- --max-automatic-retries 0 --id
everyday-workflows.runner-acpx-claude.local.recover-controller` with a
provider that saves the project in a subfolder.
2. See the timeout before the `controller-restarted` timeline entry.

**Paperclip version or commit**
`master` at `6cafcaf89b` (also reproduced at `d87f6fa4c2`).

## What Changed

- Added `readWorkspaceSource` in
`tests/runner-e2e/everyday-interruption.ts`. It reads `slugify.py` at
the workspace root first. Then it searches subfolders to depth 2,
shallowest and alphabetical first. It skips hidden folders,
`node_modules`, `__pycache__` and `venv`.
- `recordSource` (the stop-redirect and recover-controller boundaries)
and the final local source capture in
`tests/runner-e2e/everyday-flow.ts` use this helper.
- The stop-redirect workspace snapshot (`workspaceFiles`) now includes
the same bounded project folders. A stop check therefore still sees
edits when the project is below the root.
- Added `tests/runner-e2e/everyday-interruption.test.ts`.

## Verification

- Red before the fix: `npx vitest run --config
tests/runner-e2e/vitest.config.ts everyday-interruption` failed 2 of 4
tests (the nested-folder cases returned `undefined`).
- Green after the fix: the same command passes 4 of 4.
- `pnpm test:e2e:runner:typecheck` passes.
- Live rerun of the cell after the fix (local, native ACPX Claude,
`claude-sonnet-5`): the harness observed the active run with saved
source, submitted the follow-up, and restarted the controller
(`source-saved-before-interruption` with `active: true`, then
`controller-restarted`). The original timeout did not occur.
- Two valid live reruns after the fix both reached the restart. Both
still did not pass. After the restart, the interrupted ACPX turn ended
as `native_provider_terminal_failed: Provider turn failed`. In the
second rerun the task stayed Blocked with the follow-up comment still
queued and a Retry offered. This is a separate product signature. It is
not in the scope of this harness fix. A follow-up handles it (see
Risks).
- One earlier rerun failed before the task started because the new
worktree had no built runner binary (`paperclip_runner_binary_missing`).
That was local setup only. The runner was then built with `pnpm --filter
@paperclipai/paperclip-runner build`.

## Risks

- Low risk. The change is test-harness only.
- If a workspace has several `slugify.py` files, the harness picks the
root copy, else the shallowest copy. A stale copy in another folder
could be chosen. The search depth and skip list keep this bounded.
- Known remaining failure in the same cell (separate signature): after a
hard controller restart, the ACPX runner restore path
(`acpx_provider_backend.rs`, `restore_session_if_needed`) closes the
in-flight turn with `code: acpx_active_turn_recovery_closed` and no
`error` object. The run shows the generic "Provider turn failed". The
Codex fix in #15297 gives Codex a recoverable
`provider_turn_lost_on_restore` cause and a same-conversation
continuation. ACPX does not have this yet.

> 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 (Anthropic), model ID `claude-opus-5-5`, used through
Claude Code with tool use (shell, file edit) for diagnosis, the
regression test, the fix, and live reruns.

## 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 (not
applicable: test-harness-only change)
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 09:24:33 -06:00
DottaandClaude Opus 5.5 7e6d882558 fix(runner-e2e): require Daytona image lock digest; name expired overhead allowance (#19467)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Runner qualification uses a Daytona runner image and a nightly
Runner Full-Stack E2E workflow
> - The nightly workflow fails at "Validate catalog and select cells",
and a local image build fails at `sha256sum -c`
> - Operators cannot build a current Daytona image for restart tests
until both failures are understood
> - This pull request removes a stale Dockerfile lock digest default,
fixes the local recipes, and makes the nightly failure name its real
cause
> - The benefit is that a local build fails clearly when the digest is
missing, and an expired overhead allowance is obvious from the log

## Linked Issues or Issue Description

**What happened?**
1. The nightly `Runner Full-Stack E2E` runs 41997383733 and 42190298486
fail in "Validate catalog and select cells". The log shows
`digest-mismatch: error`, but that line is only the input list of
`actions/download-artifact`. The real error is `Operating overhead
allowance needs review before paid admission`. The repository variable
`RUNNER_E2E_OPERATING_OVERHEAD_JSON` has `expiresAt:
2026-11-03T19:49:53Z`. `scheduledOperatingOverhead` rejects an allowance
that expires within 4 hours. Manual dispatch (run 42046147744) does not
use the scheduled overhead path, so it passed this job.
2. `docker/daytona-runner/Dockerfile` set `ARG
PAPERCLIP_RUNNER_LOCK_SHA256=342a01e4…`. That value went stale when
`pnpm-lock.yaml` changed (#19443). The local recipes in
`tests/runner-e2e/README.md` and `docker/daytona-runner/README.md` did
not pass the argument, so local builds failed with a confusing checksum
mismatch.

**Expected behavior**
A local build computes and passes the lockfile digest. A missing digest
fails by name. An expired overhead allowance tells the operator which
allowance expired and which variable to renew.

**Steps to reproduce**
1. Run `gh run view 42190298486 --log` and read the "Validate catalog
and select cells" job.
2. Follow the old "## Daytona image" recipe in
`tests/runner-e2e/README.md` on current master.

## What Changed

- `docker/daytona-runner/Dockerfile`: remove the fixed
`PAPERCLIP_RUNNER_LOCK_SHA256` default. Reject a missing or non-SHA-256
value by name before `sha256sum -c` and before installation. CI already
passes the real value.
- `tests/runner-e2e/README.md` and `docker/daytona-runner/README.md`:
compute `shasum -a 256 pnpm-lock.yaml` and pass
`PAPERCLIP_RUNNER_LOCK_SHA256` in the local build recipes. Replace the
text about a "fixed Dockerfile default".
- `tests/runner-e2e/daytona-image.test.ts`: new test. It requires a
default-free `ARG`, the shape check before the checksum, and the
argument in every documented local recipe.
- `tests/runner-e2e/operating-overhead.ts`: the scheduled admission
error now names the allowance reference, its validity window, the 4-hour
margin, and `RUNNER_E2E_OPERATING_OVERHEAD_JSON`. The check itself is
unchanged.

## Verification

- `node node_modules/vitest/vitest.mjs run --config
tests/runner-e2e/vitest.config.ts
tests/runner-e2e/operating-overhead.test.ts
tests/runner-e2e/daytona-image.test.ts
tests/runner-e2e/scheduled-operations.test.ts
tests/runner-e2e/cost-ledger.test.ts`: 55 passed.
- `pnpm test:e2e:runner:typecheck`: passed.
- `pnpm verify`: exit 2 (README is a global CI input). Required CI
supplies broad coverage.
- `tests/runner-e2e/workflow-security.test.ts` has 5 local failures on
files that this PR does not touch (`pr-trusted.yml`,
`chat-catalog-testops-case.yml`). They are not caused by this change.
- I did not run a Docker build or a paid campaign.

## Risks

- Low risk. Any external script that builds this Dockerfile without
`PAPERCLIP_RUNNER_LOCK_SHA256` now fails with a clear message. Before,
it failed with a checksum mismatch whenever the lockfile changed. Both
CI build paths already pass the argument.
- The Dockerfile is an image content-ID input, so the next image gets a
new content tag. Current master needs a new image anyway.
- The nightly workflow stays red until an operator reviews and renews
`RUNNER_E2E_OPERATING_OVERHEAD_JSON`. This PR does not renew the
allowance, because that is a reviewed spend decision.
- Scheduled runs set `needs_daytona=false`, so the nightly run does not
publish a Daytona image even when the catalog passes. A current image
comes from a manual dispatch that selects Daytona cells.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude
Code with tool use (shell, file edits, 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-11-06 09:08:59 -06:00
DottaandClaude Opus 5.5 d87f6fa4c2 test(runner-e2e): add staging-soak reliability cases to everyday workflows (#19455)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The paid runner E2E suite (`tests/runner-e2e`) drives the real
browser, server, native runner, provider and Daytona
> - A manual staging soak found about nine reliability bugs (S47–S55,
H2, U9). Each fix got unit or integration tests
> - The end-to-end journeys that exposed the bugs existed only as ad-hoc
browser scripts, so a regression could return without a signal
> - These journeys are expensive, so they must not run per PR or in
`--all`. They must run on demand before a release
> - This pull request adds the journeys to the existing
`everyday-workflows` suite as an explicit `reliability` group
> - The benefit is one command that runs the whole reliability set
before a release or after a risky runner change

## Linked Issues or Issue Description

**What is the problem?**
The staging-soak scenarios that found S47–S55, H2 and U9 are not
repeatable. They were ad-hoc browser scripts on staging.

**Why does it matter?**
Without a repeatable end-to-end case, a reliability regression (stalled
follow-ups, duplicate execution, dead Retry, hangs after silent
commands) can return without a signal.

**What is the proposed solution?**
Add the scenarios to the paid `everyday-workflows` suite as
explicit-only cases with independent graders and a selectable
`reliability` group.

Refs #19370, #19355, #19354, #19407, #19419, #19394, #19421, #19431 (the
related fixes).

## What Changed

- `everyday-reliability-cases.ts`: seven new cases
(`interrupt-redirect`, `reassign-midrun`, `three-turn-revise`,
`long-silent-command`, `tree-pause-release`, `queue-steer`,
`queued-across-restart`), their soak signatures, prompts, bounds and the
explicit matrix.
- `everyday-reliability-flow.ts`: browser and public-API drivers for
each journey. A shared watcher records `executionBlocker`,
`interruption` and execution projections while it waits. It uses an
offered Retry at most once (never while an automatic retry is
scheduled).
- `everyday-reliability.ts`: pure graders. They encode the product rule:
interrupted work resumes automatically or offers a Retry that works on
first use. A send-a-message blocker, a dead or repeated Retry, a silent
stall, or duplicate execution fails.
- `types.ts` / `selectors.ts`: new optional `explicitGroup` on a task.
Such a task is selected only by its group, `--case`, or an exact `--id`.
`--all`, the plain suite and generic selectors skip it. `--list` still
shows it.
- `catalog.ts`: the suite gets the reliability tasks, the released
Grok/Kimi/Pi facades (only for `long-silent-command`), a per-turn
Daytona override for `three-turn-revise`, the `reliability` and `slow`
groups, definition version 11, and a computed `expectedMatrixSize` (52 →
62).
- `everyday-flow.ts`: a narrow hook calls the scenario driver after task
creation. Riley is created for the reassign and tree cases. The
reliability checks are added after settlement.
- `everyday-observations.ts`: an allowed interrupted run may end
`operator_interrupted` or `issue_reassigned`. Lifecycle checks accept a
declared reassigned parent owner.
- `live-fixtures.ts`: reliability cells get the existing 1,000-cent
company and lead-agent hard stop.
- Tests: new `everyday-reliability.test.ts` (selection exclusion,
matrix, credentials, and calibrated pass/fail cases for every grader).
Updated counts in `catalog.test.ts`, `everyday.test.ts` and
`installed-cli.test.ts`.
- Docs: new "Staging-soak reliability group" section in
`EVERYDAY-WORKFLOWS.md` (cases, signatures, run commands, cadence,
coverage boundary) and a link from `doc/evals.md`.

`everyday-flow.ts` was already over 1,000 lines. This PR adds only about
20 lines of wiring there. The scenario logic is in the new modules.

Matrix (10 cells, all Daytona, single attempt): one `runner-codex`
(gpt-5.6-sol) cell per case, plus `runner-acpx-grok`, `runner-acpx-kimi`
and `runner-acpx-pi` for `long-silent-command`.

Run command:

```sh
pnpm test:e2e:runner -- --suite everyday-workflows --group reliability --max-parallel 2
```

## Verification

- `pnpm test:e2e:runner:typecheck` passes.
- `node node_modules/vitest/vitest.mjs run --config
tests/runner-e2e/vitest.config.ts everyday catalog installed-cli
selectors support.test`: 15 files, 362 tests pass.
- The full runner-e2e Vitest run has the same 14 failures with and
without this change (`controller-outage`, `operating-receipts`,
`pi-controls-evidence`, `pi-file-evidence`, `workflow-security`). These
fail on the base commit in this local environment too.
- `pnpm test:e2e:runner -- --list --suite everyday-workflows --group
reliability` lists exactly the ten cells.
- `--all`, `--suite everyday-workflows` (still 52 cells),
profile/environment selectors and the daily/weekly scheduled selections
contain no reliability cell. A test asserts this.
- Not run: the paid cells. They need provider and Daytona credentials.
The first paid run of the group is the acceptance step.

## Risks

- The drivers have not run against a live stack. A first paid run can
expose harness timing or selector issues (for example, how fast the
queued Interrupt control appears). The failure then names the stalled
step and keeps `reliability-observations.json`.
- `long-silent-command` does not inject a runner connection loss. The
named-cause contract is checked only if a loss happens naturally.
- The Grok/Kimi/Pi facades run as ordinary released profiles. If one
returns to pending qualification, it drops out of the group and the
matrix size follows.
- No product code changes. Existing everyday cells keep their selection
and checks. The suite definition hash changes because the suite
definition changed.

> 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, via Claude Code with
tool use (shell, file edit, code execution). Standard context window.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 08:37:22 -06:00
github-actions[bot]andlockfile-bot 523818ea9b chore(lockfile): refresh pnpm-lock.yaml (#19443)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-06 12:19:36 +00:00
DottaandPaperclip 8836a71113 test(testops): pin calibrated secret acknowledgment source (#19428)
## Thinking Path

> - Paperclip lets people manage agents and inspect saved work.
> - Protected chat evaluations use a fixed source and reviewed case
declarations.
> - The last four-case run produced one verified PASS and three original
FAILURES.
> - Review found narrow acknowledgment and partial-installation
assertion gaps.
> - Their local repairs preserve the original user goals and safety
evidence.
> - This PR pins the reviewed source for one bounded secret-pair
measurement.
> - A final uniform-ten measurement on that same source is still
required.

## Linked Issues or Issue Description

Refs: #19423, #19325, #19416, #19093, #19084, #19112.
The core and full-catalog PRs remain open and unmerged.

**What happened?**

Launch 3310 retains one original PASS and three original FAILURES. Case
53 used the
same undismissed form correctly. Company rejected a valid ordered
save/ACK card
before human entry. Personal rejected a canonical wake-on-accept/After
Saving
confirmation before private entry. Team rejected a truthful qualified
required-skill
partial-installation report. No original result is regraded.

**What did you expect to happen?**

Admit supported saved cards and truthful partial reports while
preserving actual
current-human save, immutable policy, acceptance, audit, continuation,
private
ownership, delivery and saved-resource evidence. Declined or canceled
actions and
false recovery claims must still fail.

**Steps to reproduce**

Inspect the original selected journeys from source
`5f74dc6545ea66ac71255ac8e6010f5215a1f257` against their actual cards,
responses and
saved state. The local repairs calibrate the assertions; they do not
establish that
the next native secret journeys will finish within their original
clocks.

## What Changed

- Pin immutable source `d68c00a3d78e5cd56b77aedb31f1e8a0f6d6f84e` and
its exact
242-row descriptor snapshot. Update only Company v17, Personal v16 and
Team v10
oracle-version leaves in the 244-row manifest and retained repair
metadata.
- Append the measured limits after the exact historical condition
prefix. Keep
  every runtime condition and dependency list unchanged.
- Keep all 244 YAML identities, queries, contexts, outcomes,
permissions,
human/native bounds, clocks and model unchanged. Cap 2 and zero retries
stay fixed.
- Plan only cases 578 and 580 next, with original 480,000 ms and 660,000
ms cells.
Team calibration is not a new native PASS. Final uniform ten remains
required.

## Verification

- All 40 local pin controls passed:
`node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs
tests/runner-e2e/chat-completion-testops-cli.test.mjs`.
- The exact source passed 352 fresh controls across ten files. These
cover current
confirmation, independent human accounting/history, contract, Team and
all
242 declarations with zero fixture callbacks. Full runner E2E types
passed.
- SDK506 synchronization passed unchanged with registry digest
  `efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`.
  No install, native build, SDK build or local model call was needed.
- Fresh master `7e3caa7bac3f2c1a560158b28ec42381a153dfff` matches the
accepted ten
protected helpers, five source-parity files, 67 dependency-graph inputs
and
report-lock policy. No private helper imports ran during this
preparation.
- Local qualification used Node `v26.4.0`. An initial pin test import
failed before
the qualified dependency link existed; that setup failure remains
retained.
- Remote ref `codex/chat-secret-ack-v17-qualified-d68c00a3-20261106` was
read back at
  the exact source above. Descriptor SHA256 is
  `3b62889da60db1c8daafcc23f0fefa7cfcda165224ba90214b2ac391215d3be0`.
- New-head CI and reviews remain pending at PR creation. No paid
evaluation ran here.

## Risks

This source is unmeasured. Company used 344,242 ms for its initial
native turn and had
only 86,070 ms left at the false gate. Measured API handlers do not
explain that time;
no avoidable latency defect or full-flow fit has been proved. The gate
repair does
not create a native completion or private-save claim. Personal must
preserve the
actual canonical card policy through real save, acceptance and
independent evidence.
Team's local assertion calibration does not regrade result 5242 or
qualify runtime
migration. Every saved-state, actor, privacy and delivery check remains
mandatory.

Case 53's verified 241,214 ms / 300,000 ms journey is carried on
unchanged code, not claimed
as a new measurement or reliability result. All older failures remain
retained.
Secret journeys require independent semantic safety review before pass
credit.
Core and full-catalog PRs stay unmerged; the 196/244 gate remains. Only
the secret
pair is planned next, followed by the required uniform ten on the same
source.
No merge override or retry is requested by this PR.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with reasoning, tool use and code
execution.
The context-window limit is not exposed in this session. The native eval
model
remains `openrouter/deepseek/deepseek-v4.1-flash-1017` and was not run
locally.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-06 03:47:43 -06:00
DottaandPaperclip b400914345 test(testops): pin calibrated four-journey fixture source (#19423)
## Thinking Path

> - Paperclip lets people manage AI agents and inspect saved work.
> - The protected chat evaluation uses a fixed source and a reviewed
case inventory.
> - The last four selected journeys all reported FAILED. Their originals
remain unchanged.
> - Review found one fixture attention-state mutation and three narrow
observation or assertion errors.
> - The source repairs passed model-free controls, but their next native
measurement has not run.
> - This PR pins that reviewed source without merging its core or
full-catalog overlays.
> - The benefit is one bounded measurement with honest conditions and
unchanged safety evidence.

## Linked Issues or Issue Description

Refs: #19418, #19325, #19416. The last two core PRs remain open and
unmerged.
The older open source pin #18740 targets a different historical
candidate.

**What happened?**

The multipart fixture dismissed a saved form before asking for its
walkthrough.
The Company guard rejected a bounded secure-page save instruction. The
Personal
route prefilter rejected a valid task citation beside the setup hint.
The Team
assertion rejected a truthful current unattached-skill report. Launch
3277 retains
zero reported passes from four cases; none is regraded here.

**What did you expect to happen?**

Measure the same user goals with the original form still undismissed,
supported
secure-entry directions, independently validated task links, and
truthful partial
installation reports. Require all real saved-state, actor and privacy
evidence.

**Steps to reproduce**

Run the protected selected journeys from source
`58449c4ecd7fd374f21f175411ef3249f55c18a3`. Inspect each original
failure against
its user-visible result and saved state. The new source is a local
calibration,
not a claim that these native journeys now pass.

## What Changed

- Pin immutable source `5f74dc6545ea66ac71255ac8e6010f5215a1f257`.
- Copy its exact 242-row descriptor snapshot. Update eight
oracle-version leaves
in the 244-row manifest and retained repair metadata. Dependency lists
stay fixed.
- Update the expected target assertion and append the new limits after
the exact
  historical condition prefix. Retain all existing runtime conditions.
- Keep all 244 YAML identities, queries, outcomes, human/native bounds,
clocks,
  model, cap 2, zero retries and trusted private interfaces unchanged.

## Verification

- All 40 local manifest, adapter, reconciliation and CLI admission
controls passed:
`node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs
tests/runner-e2e/chat-completion-testops-cli.test.mjs`.
- The exact source passed 375 affected controls across 20 files,
including explicit
installed-browser canaries and the 242-declaration gate with zero
fixture callbacks.
Full runner E2E typecheck passed. These component results are not native
passes.
- The 506-input SDK guard passed without refresh. The launcher, ten
protected
helpers, five source/controller parity files and 67 dependency-graph
inputs match
  the accepted baseline. No install or build was needed.
- Local qualification used Node `v26.4.0`. Earlier alias and
declaration-output setup
failures remain retained. The normal remote CI configuration is
unchanged.
- Verify remote ref
`codex/chat-four-fixture-v16-qualified-5f74dc65-20261106` resolves
  to the source above. The snapshot SHA256 is
  `913090f18cc4e0f7d997b99586618080f1b5c847b2b5d74984d3c480baf5318d`.
- New-head CI and reviews must finish before merge. No paid evaluation
ran for this PR.

## Risks

The source remains unmeasured. Removing the fixture dismissal does not
guarantee
that the agent will reuse the form: a later human comment still makes it
historical,
but it remains answerable and the latest human direction governs. The
same-form
fidelity check stays strict. The Company journey did not reach human
secure entry;
its later save, approval, binding and consumer delivery remain unproved.
Personal
setup hints are not trusted URLs; actual navigation and private
ownership checks
remain required. Team calibration gives no runtime-migration credit.

All original failures remain retained. Secret journeys still require
independent
semantic safety review before pass credit. No native reliability or
latency claim
is made. The core and full-catalog PRs remain unmerged; the 196/244 gate
stays fixed.
A later full-ten run is a separate measurement. Required CI and genuine
current-head
review are pending at creation; no merge override is requested.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with reasoning, tool use and code
execution.
The context-window limit is not exposed in this session. Native eval
configuration
remains `openrouter/deepseek/deepseek-v4.1-flash-1017` and was not run
locally.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-06 02:33:18 -06:00
DottaandPaperclip 4d49a31286 test(testops): pin reviewed four-case recovery source (#19418)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The protected TestOps workflow evaluates a fixed source commit.
> - The last five-case attempt retained two passes and three failures.
> - Reviewed fixture changes address observed admission and reporting
gaps.
> - Product denial guidance and closed diagnostics remain candidate
overlays.
> - This PR updates only the immutable source pin and its public
metadata snapshot.
> - A bounded four-case measurement can test this candidate without
merging catalog or core code.

## Linked Issues or Issue Description

Refs #19325, #19416, #19395.

**What happened?**
The current pin targets the prior five-case source. The next reviewed
source changes question fidelity context, Personal menu observation,
Company secure-save acknowledgment admission, and Team partial-install
reporting. The last attempt's original failures remain unchanged.

**Expected behavior**
The workflow must admit the exact reviewed source and matching
descriptors. It must preserve the selected model, native and human
bounds, clocks, credentials, and zero automatic retries.

**Steps to reproduce**
Compare the current manifest and descriptor snapshot with source
`58449c4ecd7fd374f21f175411ef3249f55c18a3`. Run the local manifest,
adapter, reconciliation, and CLI admission controls listed below.

**Paperclip version or commit**
Controller base `90b8190c33e8f8eae44cae1f57721251fe1e1343`; candidate
source `58449c4ecd7fd374f21f175411ef3249f55c18a3`.

**Deployment mode**
Protected AWS Product E2E through the existing TestOps workflow.

## What Changed

- Pin the reviewed immutable source and exact descriptor snapshot.
- Update four existing oracle-version leaves and Company/Personal
source-file provenance.
- Append current conditions while preserving the complete historical
conditions prefix.
- Retain all 244 case identities, YAML requests and outcomes, counts,
model, clocks, runtime conditions and policy gates.
- Change one expected target literal in the manifest test. No workflow,
lock, runtime, SDK or credential changes.

## Verification

- 40 local controls pass:
`node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs
tests/runner-e2e/chat-completion-testops-cli.test.mjs`
- Parsed all 244 rows. Only the four oracle versions and two source-file
arrays differ. Runtime conditions are identical. The candidate snapshot
matches committed source bytes.
- The source qualification includes focused positive/negative controls,
full runner E2E types, and unchanged SDK506 registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`.
Counts from overlapping component sets are not summed.
- All 67 controller dependency graph inputs match the accepted
frozen-install proof. No install, SDK build or runtime build was
repeated.
- The existing selector admits exactly cases 53, 578, 580 and 610 in the
native lane with cap 2. No workflow or settings change is needed. This
local admission control did not submit a run.
- Full repository build/typecheck/test commands were not repeated for
this metadata-only change. Normal PR CI and fresh review remain
required.

## Risks

- The candidate has no new native PASS. Launch 3244 retains two original
PASSES and three original FAILURES. Older failed and missing-original
results remain unchanged.
- Case 53 changes factual setup context to identify the existing visible
form and adds stricter request fidelity. Its YAML query and original
clock are fixed. This is not a latency fix.
- Personal v14 treats the inline code path as an imprecise hint. Actual
current-company UI links must establish navigation before private entry.
Save, owner isolation, consumer delivery and final confirmation remain
separate required proofs.
- Team v8 fixes truthful partial-report admission. It does not qualify
end-to-end runtime migration.
- Company v15 accepts completed-entry acknowledgment questions. Actual
current-human save, payload, source, continuation and governed-approval
proofs remain mandatory. The corrected 403 handoff guidance is a
recovery hypothesis. Closed diagnostics do not prove a native repair.
- Pinned OpenCode model-free tests preserve the tested finish types in
both directions. They do not prove real provider behavior or engine wait
authority.
- The next measurement selects only 53/578/580/610 once, with native cap
2, zero automatic retries and original bounds. A later uniform ten
remains separately unrun. The unchanged 585 pass is carried-forward
evidence.
- Core #19325 and #19416 must remain open and unmerged. This PR does not
merge the held full catalog or change its 196/244 gate. A maintainer
will perform any normal merge and actual measurement after required
checks.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`), with reasoning, code execution and
repository tools. The host did not report a context-window size. No
model inference was used for local fixture controls.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-06 01:16:57 -06:00
DottaandPaperclip b918ee165d test(evals): pin coherent chat feature follow-ups (#19411)
## Thinking Path

> - Paperclip manages agent work and its permission boundaries.
> - The chat catalog runs feature checks from an immutable source.
> - The last full-ten attempt had five reported passes, four failures
and one missing original.
> - Local evidence identified narrow assertion, setup and
evidence-retention repairs.
> - This PR updates the trusted source pin and its exact descriptor
snapshot.
> - The next five-case measurement can test the affected features under
the same model, clocks and native cap.

## Linked Issues or Issue Description

Refs: #19395, #19405, #19093, #19084, #19112.

The previous source remains preserved. This PR selects reviewed source
`f5692c57dafaf9afbef479c25fcd277815932516` on
`codex/chat-full-ten-coherent-qualified-f5692c57-20261106`, tree
`b9e302d2ea7b605a60125dec8c81672eac7a3c57`. The full catalog and all
core PRs remain unmerged. Core #19405 is included only as a source
overlay.

## What Changed

- Update the source target, exact descriptor snapshot and the matching
pin checks. Preserve historical conditions, frozen source anchors and
the prior query clarification.
- Record Company ACK handling and Company/Personal negation corrections,
plus the skill-update preview negation correction. A denied or unapplied
action still fails when the agent claims it completed.
- Disclose the Team setup change: a disposable catalog package selects
the approved OpenCode runtime and same-company account. Other file bytes
and non-runtime sidecar fields stay unchanged. Original and effective
package identities and hashes are recorded. A real PostgreSQL install
without caller overrides proves the saved runtime. This gives no
end-to-end runtime-migration or override-handling credit.
- Include defensive failed-turn evidence retirement and generic,
schema-valid human-input examples. The old case 53 missing-original
ENOENT cause is not diagnosed. The examples are a usability hypothesis,
not a schema repair or native-success claim.

All 244 YAML definition fields (query, assumed context and expected
outcome) remain byte-identical versus source 936c. The Team derived
runtime fixture and task setup context change is disclosed above.
Native/human bounds, clocks, DeepSeek 1017, credentials, SDK506/efa,
launcher, private interfaces, native cap two and zero automatic retries
remain unchanged. Only descriptor `sourceFiles` and oracle versions
change. The 196/244 gate stays unchanged.

## Verification

Pin-local checks:

```sh
node --test tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs tests/runner-e2e/chat-completion-testops-contract.test.mjs
```

- All 49 pin/admission controls pass locally. They join all 244
identities, historical query overrides, native bounds and the exact
242-row descriptor snapshot.
- Source qualification: 447 controls across 32 suites, full E2E
TypeScript checks and normal contract generators pass. The separate 21
core contract controls are carried-forward component evidence; they are
not added to 447. Local source checks used Node 26.4.0. AWS runtime
settings are unchanged.
- The selected source descriptor SHA256 is
`24fe88af167724c6fb120d3984296aab47c993a65782158e03d80a936fbd94ed`.
- The actual source launcher is byte-identical to 936c: SHA256
`2b9a6953ee51f0ea0dbbd475b0491d9a6c39a1d6835eeaa912e0dbb7cf987724`, Git
blob `c88df15f509b2ac8638af826647a97d45f16bd1f`.
- All 506 registered SDK inputs and the ten trusted helper bytes are
unchanged. Five required source-helper joins pass. No SDK renewal or
native build is part of this PR.
- The current controller's 67 dependency inputs match the qualified
frozen reporting graph. No reporting-lock, package, permission or
workflow change is included.
- Exact head `b833036fb477b55b05cbdf1f4feb2e2c5387b420` is green: CI run
42166216108 attempt 2 succeeded, Windows succeeded, and both current
reviews are 5/5 with zero unresolved threads. The check rollup has 56
successes, three configured skips and one neutral result. New
representative cases 53, 578, 580, 585 and 610 are unrun. A later
uniform-ten regression is separate.
- CI attempt 1 remains retained: one cloud-auth browser fixture read a
trailing health response after context teardown began, after all
task-recovery assertions had passed. One authorized rerun of only that
failed job and its dependent checks succeeded on the unchanged head.
This does not fix or qualify fixture reliability; no eval or model run
was retried.

The previous full-ten outcome remains five reported passes, four
failures and one missing-original/reporting gap. Case 585 reached only
its first preview before the false rejection; its update phase is
unqualified. Case 610's old noncompletion and runtime-override journey
remain unresolved. All original failures and evidence remain retained.
No old result is regraded or replaced.

## Risks

The local repairs may not produce a native pass. The new Team setup
tests installation with an already selected runtime package; it does not
qualify runtime migration. Failed-turn retirement has local regression
coverage but does not establish the cause of the old case 53 reporting
gap. The core guidance overlay remains unmerged and its native benefit
is unproved. Normal protected merge and a new authenticated measurement
are still required.

## Model Used

OpenAI `gpt-6.1-sol` through Codex. It used code inspection, local test
execution and GitHub tooling. The context window size is not exposed. No
model inference or provider call was made for this PR's local checks.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-05 23:32:34 -06:00
Dotta d8b0eae687 test(evals): pin completed timeline command account for full-ten measurement (#19395)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The chat catalog needs fixed source and explicit conditions for each
measurement.
> - The latest timeline run delivered a complete account within its
original deadline.
> - Its assertion missed ordinary exitCode notation and a command with
an omitted subject inside a named worker bullet.
> - The reviewed source corrects those bounded textual checks while
retaining independent history and command proof.
> - This pull request pins that immutable source for one full-ten
measurement.
> - Original failed grades and unresolved Company timing remain visible.

## Linked Issues or Issue Description

Refs: #19392, #19086, #19388.

This follows the prior source pin. The latest timeline response
correctly described requirements, a real failed command, saved pause,
human reassignment, repair and successful verification. Its original
grade still failed one narrative assertion. This pin carries the
reviewed correction without merging the full catalog or its production
overlays.

## What Changed

- Pin source `936c3bbe0e83ca15616254f23d9023b2065fc5fb`, tree
`e5c64d67935497164b098e31e995f87ba7875d06`.
- Advance only the timeline oracle from v11 to v12 in the candidate
snapshot and manifest.
- Retain all 244 current queries, contexts, expected outcomes, model,
credentials, clocks and human/native accounting.
- Record one planned full-ten bounded measurement at native cap 2 and
zero automatic retries.
- Change only the manifest, its target assertion and the exact candidate
descriptor snapshot.

## Verification

- I verified the immutable source branch readback before I published
this pin.
- The new narrative control fails on the parent. The fixed source passes
300 timeline, native-proof and declaration controls, including all 242
lazy declarations with zero fixture callbacks.
- The response from result 5094 is accepted by the local diagnostic. The
original grade is retained as FAILED; this is not a new native PASS.
- Fresh full runner E2E types and the SDK guard over 506 inputs pass in
the qualified source graph. An earlier isolated worktree type attempt
had dependency-alias errors; the clean source qualification supersedes
that setup gap.
- Controller: `node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs` — 40
controls pass.
- The snapshot equals the committed source descriptor bytes. All 244
rows compare equal to the prior pin except the timeline oracle version.
- Source descriptor SHA256:
`19185aa5298c93d159c3d8547661fd6ef22185e74be1c18b8497bae2ef8051c7`.
- Controller manifest SHA256:
`822494b170139a8204ff36b33891e2f4960ac0aba6800e9856f2d25dd24de7c6`.
- Launcher, protected evidence wire and the accepted 506 SDK inputs
remain unchanged. The source SDK registry stays
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`.

- Exact pin head `31f47fcdfb600e6b15b35ed50c2a447d03681f06` has 56
successful checks and three configured skips. Both protected checks
pass. Greptile is 5/5 for this head with zero open threads. Paperclip
Review completed neutral at 5/5. GitHub reports CLEAN and MERGEABLE.
These checks do not qualify the unrun native experiment.

## Risks

- Original timeline result 5094 remains FAILED. All three native runs
succeeded and the account was complete in 248,876 ms, but the original
narrative check failed. Local calibration does not rewrite that grade.
- Original Company result 5093 ended without first-CEO completion. Its
model/runtime timing cause remains unresolved. This source makes no
Company runtime or latency fix claim.
- The full-ten measurement is unrun. It is a bounded experiment, not
proof of deterministic timing, reliability or an all-ten pass.
- Company retains two base human inputs plus at most one independently
verified UI approval, minimum two and maximum three native runs, and
480,000 ms. Timeline retains three native runs, one human input and
720,000 ms. No condition is waived.
- Secret journeys still require independent semantic safety review.
Metadata shape alone does not establish that a proposed name is
non-sensitive.
- The interaction-accept and API-search overlays remain separate,
reviewed, unmerged core PRs. This pin does not merge them or the full
catalog. The 196/244 admission gate stays fixed.

## Model Used

OpenAI Codex, GPT-6.1 Sol (`gpt-6.1-sol`), with reasoning, repository
tools and code execution. The host does not expose an exact
context-window size. No model or paid provider was called for local
controls.

## Checklist

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

> - Paperclip manages AI agents and their governed actions.
> - The TestOps controller runs an immutable product-eval source.
> - The last company-secret attempt rejected a safe metadata question
before private entry.
> - A governed approval also had a redundant server notification and
wake path.
> - Natural-language API search could hide the resource needed for a
timeline answer.
> - This pull request pins the reviewed source and its exact descriptor
snapshot.
> - New native evidence must still prove the affected journeys.

## Linked Issues or Issue Description

Refs #19381, #19093, #19387, #19388. This is the next controller pin for
those reviewed changes. The core pull requests remain unmerged.

## What Changed

- Pin source `2c99c248e839f41b520fc2d7e3702169ac6cb0a2` and its exact
descriptor snapshot.
- Advance company oracle v12 to v13. Admit bounded environment-name
questions without a required authored pattern or exact prompt template.
Preserve independent human-answer validation.
- Include the reviewed interaction-accept notification and API-search
ranking overlays. Record their route and catalog dependencies in the
company and timeline provenance.
- Retain the existing cap of two, zero retries, DeepSeek1017 model, and
all 244 current YAML definitions. Company keeps 480000ms, native2..3,
base human2 plus one independently proved approval. Timeline
keeps720000ms, native3/human1.

## Verification

- Source:396 controls in9 suites,2046 API catalog controls,145 route
controls, full runner TypeScript check, and unchanged SDK506 input guard
passed. Fresh-master API PR has2059 controls; its other baseline tests
are absent from this catalog source.
- Controller:133 contract, API, adapter, reconcile, streaming and
manifest controls passed. Existing report-lock preparation returned
`already-reviewed`.
- All current YAML definitions and launcher bytes remain unchanged from
the prior source. No model or native eval ran for this pin.
- The original company5059 and timeline5060 remain failed. Company
private entry, approval and final binding remain unproved on this
successor.
- Exact-head normal checks are terminal:56 success,3 intentional skips,
and one neutral Paperclip review. Greptile and Paperclip both report5/5
with no findings; review threads are empty. The next TestOps/AWS run
follows the protected controller merge.

## Risks

The new source is not a native feature pass. Its effect on model
completion is unproved. The original480000ms company budget may still be
too short for three native turns. No budget change or count waiver is
included. The full catalog remains outside master and its existing
admission gate remains unchanged. The controller reuses byte-identical
SDK506 evidence; no compiler or registry renewal is claimed. Actual
post-merge helper imports still need qualification against the merged
controller lock. The CI virtual merge includes a newer upstream lock
than the local frozen dependency proof.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with repository tools and code
execution. The host did not report its context window.

## Checklist

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

Co-authored-by: Paperclip <paperclip@paperclip.ing>
2026-11-05 20:05:16 -06:00
github-actions[bot]andlockfile-bot 675f7283dd chore(lockfile): refresh pnpm-lock.yaml (#19389)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-06 01:42:27 +00:00
DottaandPaperclip 46414fcfa4 test(evals): pin timeline and governed Company approval at native cap two (#19381)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The chat catalog uses a fixed source and explicit execution
conditions.
> - A correct timeline response failed because its completed edit and
attached command result were not recognized.
> - Company credential setup can require a real human approval after the
secure save.
> - The controller must declare that optional approval and its run
bounds before it admits the source.
> - This pull request pins the reviewed source and caps native catalog
overlap at two.
> - The next run can test these conditions without treating local
controls as native acceptance.

## Linked Issues or Issue Description

Refs: #19357, #19086, #18971, #19093.

This follows the prior fixed-source catalog pin. It changes only
controller metadata, admission, tests, and load policy. The complete
catalog and separate core feature PRs remain unmerged.

## What Changed

- Pin immutable source `fe547be84826b4611d3ba9ee1a7d7aa0bd0a2843`, tree
`a23723ea5244e6ce8cee11e9c4b476acb6978fcd`.
- Advance only timeline v10 to v11 and Company v11 to v12. Add the
declared Company proposal helper to its source closure.
- Declare Company minimum two and maximum three native runs. Retain two
base human inputs and permit at most one independently verified UI
approval. Retain its original 480000ms attempt.
- Carry the literal Company-only approval marker from the descriptor
into the manifest. Reject foreign markers, changed bounds, and a
mismatch with static source task metadata.
- Cap native catalog execution at two workers. Keep the external lane
serial and retain zero retries.
- Keep all244 requests, contexts, expected outcomes, model, clocks,
credentials and other case bounds unchanged.

## Verification

- Source:421 focused controls across seven suites pass. Full runner E2E
TypeScript check passes.
- Explicit model-free approval UI canary passes one test with three
local scenarios. It checks accepted approval, wrong human, and failed
response. The first sandbox attempt stopped at Chrome launch; the
allowed execution passed.
- Controller:40 manifest, adapter and reconciliation controls pass.
- SDK506 inputs remain byte-identical to the accepted registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`.
- Launcher and trusted private evidence wire remain byte-identical.
Source contract/flow accounting changes are explicit.
- Source descriptor SHA256:
`50e90d8c02ad57f444e27b522efe694db9734d47bdbc3a058475af77bac8b2ca`.
- Controller manifest SHA256:
`0447315601ed21ba15d6ea0ecd7fb89bc79ad6262db2594cd12ac774aa8d6c21`.
- Review the two changed rows. The next planned experiment selects
timeline and Company once at cap2 before a full ten-case run. No native
run on this source has passed yet.

- Exact controller head `d49dfc59ab7fddfe1a1de7e81bdb9c4e13400f30`:
normal CI has56 successful checks and three configured skips. Protected
`ci / verify` and `ci / e2e` both pass. Greptile5/5 and zero open
threads are verified for this head.

## Risks

- Original timeline5056 and Company5057 remain FAILED. Timeline5056
supplied the correct account; the local revised check passes its
diagnostic only. Company5057 saved the secret but left the binding
approval pending.
- Company native3 completion within480s is unproved. This change does
not raise its clock or claim to fix latency.
- Two-worker execution is a changed load condition. It does not prove a
concurrency cause, reliability, or eight-worker qualification.
- Secret journeys require independent semantic safety review before pass
credit. The documented closing-comma warning and arbitrary
metadata-prefill classifier limitations remain follow-ups in the
functional secret PR; a native failure is not waived.
- Candidate core PRs remain unmerged. The full-catalog196/244 admission
gate remains fixed. Local controls do not qualify all244 journeys.
- Local checks use Node26.4.0. They do not replace actual AWS runtime
qualification.

- The separate Paperclip Review app remains queued while its assigned
task waits for maintenance. It has no completed assessment. GitHub
reports `UNSTABLE` and `MERGEABLE`; this is not an all-checks PASS
claim. No review retry or staging mutation was performed.

## Model Used

OpenAI Codex, GPT-6.1 Sol (`gpt-6.1-sol`), with reasoning, repository
tools and code execution. The host does not expose an exact
context-window size. No model or paid provider was called for local
controls.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-05 19:06:42 -06:00
Nicky LeachandClaude Opus 5.5 3a8f95d928 fix(ci): let verified Dependabot lockfiles merge through the reporting-lock gate (#19356)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Only trusted environments may change `pnpm-lock.yaml`: the lockfile
refresh workflow and Dependabot. Contributors never commit it.
> - Paid evaluation jobs also install a lock only when the
reporting-lock proof (`tests/runner-e2e/report-lock.json` and `.patch`)
admits it.
> - #19283 added a CI test that checks the committed lock against that
proof. Only the refresh workflow writes the proof, so every Dependabot
lockfile pull request now fails CI. Examples are #17364, #17172, and
#17911.
> - A merged Dependabot lockfile also breaks the refresh workflow.
`prepare-report-lock.mjs --refresh` refuses to renew the proof for a
lock that the proof does not already admit.
> - This pull request lets a verified Dependabot lockfile pass, and it
keeps both lockfile rules strict. It also closes a gap in the
contributor rule.
> - The benefit is that Dependabot security updates can merge again, and
only trusted environments write lock content.

## Linked Issues or Issue Description

Refs #19283, #17364, #17172, #17911, #19303.

**What happened?**
`server/scripts/reporting-lock-policy.test.mjs` fails on each Dependabot
pull request that changes `pnpm-lock.yaml`. The error is "Reporting lock
changed; review the dependency correction before install". A Dependabot
pull request cannot change the proof files, so it can never pass. After
a merge, the lockfile refresh also stops at "Committed report lock is
not reviewed; refusing to refresh its proof".

**Expected behavior**
- Contributors cannot change `pnpm-lock.yaml` or the reporting-lock
proof.
- Dependabot can change `pnpm-lock.yaml`.
- The lockfile refresh workflow can change `pnpm-lock.yaml` and the
proof.
- After a Dependabot lockfile merges, the refresh workflow admits it and
renews the proof.

**Steps to reproduce**
1. Open a Dependabot pull request that changes `pnpm-lock.yaml`, such as
#17364.
2. Let CI run. The `server (9/12)` shard fails on the reporting-lock
policy test.

**Security gap found during this work**
The old rule skipped the lockfile check when `github.head_ref` was
`chore/refresh-lockfile`. A contributor could open a pull request from a
fork branch with that name and commit a lockfile change. The old rule
also exempted any pull request that Dependabot opened, including commits
that other people pushed to its branch.

## What Changed

- Add `.github/scripts/lockfile-trust.mjs`. It decides which writers may
change lock content:
- The refresh workflow: the head is `chore/refresh-lockfile` in this
repository, and `github-actions[bot]` opened the pull request.
- Dependabot: Dependabot opened the pull request from this repository,
and the head `pnpm-lock.yaml` matches a Dependabot commit. That commit
must have `dependabot[bot]` as its author, GitHub (`web-flow`) as its
committer, and a verified signature. The script reads these fields from
the GitHub API.
- The reporting-lock proof files count as lock content. Only the refresh
workflow may change them.
- `pr-trusted.yml` policy job: replace the inline `head_ref` and author
exemption with `lockfile-trust.mjs pr`. The job runs the script copy
from the base commit, so a pull request cannot change the check that
judges it. If the base predates the script, the job uses the earlier
rule.
- `refresh-lockfile.yml`: add `lockfile-trust.mjs merged`. It checks
that the last lockfile change on `master` is a GitHub-signed merge of a
Dependabot pull request, and that the lockfile at the pull request head
matches a verified Dependabot commit. If both checks pass, it gives the
lockfile SHA-256 to `prepare-report-lock.mjs --refresh
--trusted-lock-sha256`.
- `refresh-lockfile.yml` PR step: check `pnpm-lock.yaml` and both proof
files before it exits as unchanged. A refresh that renews only the proof
now opens a pull request.
- `prepare-report-lock.mjs` and its `.d.mts` declaration:
`refreshReportLock` accepts a trusted lock hash. If the trusted lock
already resolves, the proof admits it exactly with an empty patch. If
not, the proof records the resolution as the reviewed correction, as
before.
- `reporting-lock-policy.test.mjs`: skip on Dependabot pull requests.
The policy job verifies those lockfiles. The general test job gets
`PAPERCLIP_CI_PR_AUTHOR` for this purpose. This keeps the test, so it
still merges cleanly with #19303.
- `check-pr-lockfile.mjs` (advisory gate): allow Dependabot lockfile
changes, and flag changes to the proof files.
- `CODEOWNERS`: add the two proof files.
- `doc/RELEASE-AUTOMATION-SETUP.md`: describe the writers, the
`@dependabot recreate` path, and the proof renewal after merge.

## Verification

- `node --test '.github/scripts/tests/*.test.mjs'`: 707 passed. This
includes 17 new tests in `lockfile-trust.test.mjs` and 3 new tests in
`check-pr-lockfile.test.mjs`. The new tests run the `pr` command against
real git histories with a stub `gh`.
- `tests/runner-e2e/prepare-report-lock.test.ts`: 10 passed, including 3
new trusted-lock refresh tests. I ran it with a minimal Vitest config,
because the runner-e2e config builds a provider bundle first.
- `server/scripts/reporting-lock-policy.test.mjs`: passes normally, and
skips with `PAPERCLIP_CI_PR_AUTHOR=dependabot[bot]`.
- Live check of the `pr` mode against #17364 with the real GitHub API:
- With the real author, it reports "pnpm-lock.yaml matches verified
Dependabot commit 83c328c15c…" and `writer=dependabot`.
- With a contributor as the author and `chore/refresh-lockfile` as the
head ref, it fails.
- Live check of the `merged` mode at the real merge commits of #16018,
#16020, and #15361. All three report a trusted lock hash. For #16018 and
#15361, `master` changed after Dependabot's commit, so GitHub's merge
produced different lockfile bytes. An exact-bytes rule would refuse
them. That is why the rule trusts GitHub-signed merges of a verified
Dependabot head.
- Greptile reviewed `513ca2def8` at 4/5 with one P1: a proof-only
refresh was never committed, because the PR step checked only
`pnpm-lock.yaml`. `edbeb1ea0d` fixes it. A new test in
`lockfile-refresh-merge.test.mjs` runs the step's change check on a
proof-only change. The test fails without the fix.
- CI `Typecheck + Release Registry` failed at `edbeb1ea0d`:
`prepare-report-lock.d.mts` did not declare the new options argument
(TS2554 twice in `prepare-report-lock.test.ts`). `9139aaad85` updates
the declaration. A local `tsc -p tests/runner-e2e/tsconfig.json` shows
the 2 errors with the old declaration and none with the new one.
- CI at `9139aaad85` failed in six general test shards. None of them run
code that this pull request changes, and PR CI loads `pr-trusted.yml`
from `master`. The failures:
- `heartbeat-plugin-environment.test.ts`: "expected 'running' to be
'succeeded'"
  - `status-card-evaluation-work.test.ts`: a deadline comparison
  - `isolated-repository-rehome.test.ts`: timed out after 15 seconds
- `chat-channels.integration.test.ts`: GitHub webhook recovery
scheduling
- `company-import-export-e2e.test.ts`: child server start timeout, which
also fails on unrelated branches
- `workspaces-b`: every test passed, but an `EPIPE` error came after
`acpx-engine/execute.test.ts`
  I started a rerun of the failed jobs.
- Superagent found a P1 at `9139aaad85`: a verified signature proves who
committed, not who authored. A collaborator could sign a commit with
their own key and set Dependabot as the author. `4fe180d6c1` also
requires GitHub (`web-flow`) as the committer. New tests cover the
spoofed-author case. #17364, #16018, #16020 and #15361 still verify
against the GitHub API.
- `git merge-file` merges this test change with #19303 without
conflicts.
- Not run: the full repository test suite and typecheck. These changes
touch only CI scripts, workflows, one helper, and tests. GitHub CI
covers full regression.

## Risks

- `pr-trusted.yml` loads from `master`, so the new policy takes effect
only after merge. This pull request's own CI uses the earlier rule.
- A Dependabot pull request that is behind `master` now fails if someone
merges `master` into it and the lockfile changes. Use `@dependabot
recreate`. The policy job error says this.
- Paid evaluation jobs refuse a merged Dependabot lockfile until the
refresh pull request merges. The refresh merges without review when it
adds no new package versions. If the release-age gate holds it, the wait
lasts until a maintainer merges it or the daily refresh runs. During
that time, the reporting-lock policy test also fails on other pull
requests, which is the current behavior for any unrenewed lock.
- The rule trusts GitHub as the signer of Dependabot commits and of
merge commits (`web-flow`). Superagent uses the same trust root.
- People with write access can still push to `chore/refresh-lockfile`.
This was already true. The bot merges only its own head commit
(`--match-head-commit`), and code-owner review covers anything else.
- A future manual proof renewal, such as #19283, now needs the refresh
workflow or an admin merge. A contributor pull request that changes the
proof files fails.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), with tool use and code
execution, in Claude Code.

## 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 tests; see
Verification)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 16:42:26 -08:00
Dotta b68f69a801 test(evals): pin author self-use and credential guard corrections (#19357)
## Thinking Path

> - Paperclip manages agents and their work.
> - The protected chat catalog selects an immutable evaluated source.
> - The measured parent produced seven independently reviewed passes out
of ten.
> - The authoring observer rejected valid author-only use, and two
credential wording guards needed stricter boundaries.
> - The reviewed source corrects those observers and declares each
affected oracle version.
> - This PR pins that source without changing the original questions or
run limits.

## Linked Issues or Issue Description

Refs #19346, #19095, #19093.

**What happened?**

The measured authoring response described real saved author-only use.
The old observer required zero assignments and wrongly rejected an
audited author-only assignment. The credential scanner also needed to
retain an unsafe comma-separated destination and mixed
reference/password requests. These are evaluation-layer corrections. The
parent timeline and company runs did not complete; no causal latency fix
is claimed here.

**Expected behavior**

Select the reviewed immutable observer source. Keep all original
scenario identities, questions, conditions, actor/resource proof,
counts, clocks, credentials, model, permissions and zero retries
unchanged.

**Steps to reproduce**

Run the source authoring and shared credential consumer controls.
Compare the committed candidate descriptor snapshot with source
`d1ab241cac0db7f700fadaaf62ffb3d2b51cf0c3`.

## What Changed

- Scope the private Company creation observer to the exact Create secret
dialog. Its successful close can open a separate details Sheet without
making the observer wait for that Sheet.
- Admit blank or bounded non-secret metadata defaults only for the
Company saved-secret-name question variant. Verify the same canonical
payload in independent human accounting.
- Pin source `d1ab241cac0db7f700fadaaf62ffb3d2b51cf0c3`, tree
`c4efaef62405cbb37236ad01db1187cf8a156868`.
- Store exact descriptor SHA256
`60db015337e807ff53a376b6db11c375a239097b224d2253dad68ecd0b0f61f3`.
- Update only seven oracle-version leaves: authoring v5, company v11,
personal v12, and four shared external consumers v6. Source-file lists
remain fixed.
- Retain provenance anchors, historical conditions and failures. Update
the single expected-target assertion. Exactly three metadata/test files
change.

## Verification

- 41 manifest, adapter, reconciliation and CLI controls pass on this
actual pin projection.
- Qualified source: one actual-worker offline browser canary passes all
three creation, failed-POST and missing-form mechanisms. Full E2E types
pass on this successor. Reused unchanged proof: 286 distinct controls
across authoring, Company saved-name question, human accounting and
shared-consumer/declaration suites pass. Full E2E typecheck passes. All
242 declarations load with zero fixture callbacks.
- SDK506 inputs and registry `efa70621` remain unchanged. Launcher
SHA256 `2b9a6953`, private transport interfaces, production/UI/CLI
source, lockfile and workflows remain unchanged from the measured
source.
- All 244 YAML queries, context and expected outcomes are byte-identical
to the parent. All descriptor native/human counts, clocks,
authentication, setup policy and source-file lists remain fixed.
- The parent source has seven measured semantic passes out of ten. The
new authoring and credential oracle versions are native-unrun. Existing
failed grades remain failed.
- The isolated company concurrency diagnostic
[run42124035785](https://github.com/paperclipai/paperclip/actions/runs/42124035785)
is a separate measurement. This pin does not alter concurrency or claim
to fix native noncompletion.
- Repo-wide build/tests were not repeated for this three-file metadata
update. Normal PR CI remains required.

## Risks

- The name character set does not prove secrecy. The saved-key-name
variant can admit a credential-shaped synthetic default; this general
classifier limit remains unfixed and tracked in #19093. These are finite
experimental journeys only. Independent review must reject any actual
credential-like or unknown-value prefill without clear
public-metadata/proposed-name grounding, even if autograding is green.
If safety cannot be established, the journey cannot receive PASS credit.
Secure UI save, human answer, canonical payload/hash, audit, binding and
byte-leak checks remain mandatory.
- Earlier CI includes three explicit runner-shutdown cancellations and
one deferred-observer test assertion at line573. Those outcomes remain
retained and unresolved; the Company dialog repair makes no claim to fix
them. New exact-head CI is required.
- The Company dialog mismatch was established from production source and
an actual-worker model-free regression before the next secure-save step.
The prior isolated attempt did not reach private entry, so it is not
evidence of an observed private-save failure.
- A valid review warning remains as a documented follow-up in #19093:
safe closing comma exclusions such as “only there” can be falsely
rejected by the credential wording guard. The pin authorizes bounded
experimental journeys only. If a valid actual handoff hits that guard,
its failed grade is retained; no regex failure is waived or counted as
PASS. Independent semantic review remains required for both secret
handoffs.
- Isolated Company original5055 remains FAILED. A real succeeded native
took255949ms and produced a valid saved-name question, but the observer
rejected its proposed non-secret metadata default. Secure entry and the
second native were not reached. This successor repairs that assertion
boundary only.
- The next selected74/466/578 run is an explicit bounded
lower-concurrency functional experiment at the existing cap2, same
model, original clocks and zero retries. It is not evidence of a latency
fix or reliability improvement.
- Local observer proof is not a new native PASS. Timeline and company
noncompletion remain unresolved, and no clock increase is included.
- A secure handoff still requires independent semantic review before
PASS credit. Actual saved resources, owner/audit evidence, provider
outcomes and privacy gates remain required.
- The source catalog remains separate from master. This PR does not
merge the core or full catalog feature changes into master.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, with repository tools and code execution.
The host does not expose the context-window size.

## Checklist

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

> - Paperclip manages AI agents and their work.
> - The protected TestOps catalog selects one immutable source revision.
> - The current pin predates reviewed secure-entry and Team observation
repairs.
> - A new run must use the qualified source and its exact descriptor
bytes.
> - This PR updates only the source pin, retained descriptor snapshot,
and expected-target test.
> - Existing failures remain failures until a new native run proves the
feature.

## Linked Issues or Issue Description

Refs: #19333, #19084, #18971, #19112.

**What happened?**

The current catalog points to the earlier source. It does not include
the reviewed personal entry-dialog observer, visible secure-entry
guidance, company menu navigation, Team claim attribution, or
completion-link guidance changes.

**Expected behavior**

The protected catalog must select the qualified immutable source and
verify its exact descriptor snapshot. Model, original queries, run
counts, clocks, private transfer interfaces, and retries must remain
fixed.

**Steps to reproduce**

Read the manifest target and candidate descriptor digest. Compare them
with source `7ccfc33bf074e37d8fd901a6e8453d1b45307e82` and its committed
descriptor bytes.

## What Changed

- Pin source `7ccfc33bf074e37d8fd901a6e8453d1b45307e82`, tree
`5afa0cf2e8ad8d17b7563e62378b0994f7777c67`.
- Store the exact candidate descriptor snapshot with SHA256
`e1b7de947567569d96fcc9dca607ef5807ffaba4bf994562c0c7ab46d1856df6`.
- Update current version and source-file provenance while retaining the
original anchors and prior conditions.
- Update one expected-target assertion. This PR changes exactly three
metadata/test files. The final target-only successor retains the
previous pin commit and its CI results; descriptor bytes do not change.

## Verification

- 41 model-free manifest, adapter, reconciliation, and CLI controls
pass. Another 42 chat-admission controls pass.
- Initial source qualification: 268 focused controls, five explicit
offline Chromium controls, and full E2E types pass. The first six-path
Company/Team amendment passes 233 affected controls and full E2E types.
The final reviewed six-path followup passes 271 affected controls, two
offline browser canaries and full E2E types. Unchanged source inputs
reuse the prior qualification. The accepted completion-feedback core
patch has 22 real PostgreSQL controls from its owner.
- All 244 scenario YAML definitions and all 242 descriptor run counts,
clocks, authentication, and setup policy remain unchanged from the
previous source. Seven descriptor rows change only versions or
source-file lists.
- SDK506 inputs and registry `efa70621` remain unchanged. Launcher
SHA256 `2b9a6953` and private transfer interfaces remain fixed.
- Fresh-main reporting installation passes with pnpm9.15.4, frozen
lockfile, ignore-scripts, and offline mode. The unchanged reviewed
report policy returns `already-reviewed`. No lock or workflow change is
included.
- Repo-wide build/typecheck were not repeated for this three-file
metadata update. Normal PR CI remains required.

## Risks

- Both secret journeys require independent review of the actual native
handoff before any PASS credit. Unsafe value requests cannot count as a
feature pass even if an oracle accepts them. Two additional unexercised
adversarial wording guards (comma-only plaintext destinations and mixed
reference/password requests) are being hardened separately in #19093.
They are not included in this source pin. No current native PASS is
claimed.
- This pin includes reviewed source changes whose separate core/catalog
PRs remain unmerged. This PR does not merge those features into master.
- New native measurements remain required. The prior personal failure
remains failed; its first native took 580602ms, and completion within
the unchanged 660s remains unproven.
- The plain-comment save acknowledgment fixes a downstream phase that
the failed attempt did not reach. Component checks do not prove native
completion.

## Model Used

OpenAI Codex, GPT-6.1 Sol (`gpt-6.1-sol`), with code execution and
repository tools. The runtime does not expose its context-window size.

## Checklist

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

> - Paperclip is the open source app people use to manage AI agents for
work
> - Product E2E journeys grade agent work in the QA staging smoke plan
> - On the current QA deployment, two journeys failed after the product
had already done the requested work
> - protected-actions counted a wake that the control plane retired
before it started as a bound run, and failed its runtime binding check
> - question-answer-resume waited for its saved document in a view that
no longer exists. The wait lasted 27 minutes, until the case deadline,
and starved the run queue
> - This pull request grades only runs that started provider work, and
reads the document where the UI now shows it, with a bounded wait
> - The benefit is that both journeys measure the product, and a UI
readback failure costs about two minutes instead of a whole worker

## Linked Issues or Issue Description

**What happened?**
- protected-actions: the task succeeded with two runs. A third
automation wake for the same agent and task was cancelled before it
started, with the reason "Agent cannot start work while completed runs
await accounting". Its `startedAt` was null, its
`resultJson.cancellation` had `source: "control_plane"` and `expected:
true`, and its `executionRecovery.providerWorkStarted` was false. That
run has no runtime binding, so `validateAgentTaskState` failed with
`agent_run_binding_mismatch`.
- question-answer-resume: the agent saved the requested document and the
task was done by 19:32. The journey then navigated to `#document-<key>`
and waited until 19:59 for an element that never appeared. With the task
chat shell and Artifacts V1, documents render in the properties pane's
Artifacts tab. The run reported `journey_operation_failed` and
`evidence_collection_timeout`, and the 60-minute job ended before four
other cases could run.

**Expected behavior**
- A wake retired before admission is kept as evidence but is not graded
as provider work.
- The saved document is read in its current view, and a UI readback
failure ends quickly.

**Steps to reproduce**
QA staging smoke launch 3074 on app cb8df178c8. The stack-side run
records are described above.

**Paperclip version or commit**
master at 03eb49053f.

## What Changed

- `agent-flows.ts`: add `retiredBeforeProviderStart(run)`. The run must
have status `cancelled` and `startedAt === null`, a control-plane
cancellation with `expected: true`, and
`executionRecovery.providerWorkStarted === false`.
`validateAgentTaskState` still checks such a run's company, agent and
task binding and counts it toward the run limit, then skips the runtime
checks.
- `clarification-flow.ts`: after reload, open the Artifacts tab with the
existing `openDocumentAuthoring` helper before reading the document.
task-dependency-resume uses the same path and passes on this deployment.
The UI readback is capped at 2 minutes after the API returned the saved
document. Agent work time is not changed.
- `agent-evidence.test.ts`: the retired wake is accepted. Nine variants
still fail: a started run, a missing `startedAt`, a failed status, an
unexpected cancellation, an operator source, `providerWorkStarted:
true`, missing recovery evidence, another agent, and another task. The
run limit still applies.

## Verification

- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/product-journeys`: 46 files passed.
- Negative control: without the skip, the new test fails.
- `clarification-readback.spec.ts` (browser support): 6 tests passed.
- `tsc -p tests/runner-e2e/tsconfig.json` shows no errors in the changed
files.
- Not verified live yet. QA uses the pinned harness, so the pin must
move to a commit that contains this change.

## Risks

- The exclusion is narrow, and every field it requires is positive
evidence that the wake did no work. Any started or unexpected extra run
still fails.
- The readback cap is stricter, not looser. It applies only after the
API has confirmed the document. Agent work and answer timing still use
the existing deadlines.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, browser, code editing). Extended reasoning was used.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:39:18 -06:00
github-actions[bot]andlockfile-bot 1e98aa76e3 chore(lockfile): refresh pnpm-lock.yaml (#19337)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-05 20:36:41 +00:00
DottaandPaperclip 6a66c09f7f test(evals): pin secure confirmation and team warning repairs (#19333)
## Thinking Path

> - Paperclip manages AI agents and human approval for work.
> - The chat catalog measures real user journeys through TestOps.
> - The last personal-secret journey reached a valid secure-save
confirmation that its observer rejected.
> - The team journey reported a missing named skill with a typographic
apostrophe that its observer rejected.
> - A company-secret request returned body validation before the
required agent authorization denial.
> - This PR pins one reviewed source that addresses these boundaries
without changing the requests, models, or time limits.
> - New native measurements must establish the result. Existing failures
remain failures.

## Linked Issues or Issue Description

Refs: #19084
Refs: #19112
Refs: #19325
Refs: #19261

This is the single successor pin for the reviewed personal confirmation,
team warning, and company authorization changes. It does not merge those
core or full-catalog branches into master.

## What Changed

- Pin immutable source `ab0f5246f765058af702b93d9b6637f2ef5b83cd`, tree
`6cf28980b0ab6d1dd8e54efda3996708c53aeb98`.
- Bind the exact descriptor snapshot
`0b57bba133a5c15860ca77b804f7282b5314d7feb8efbfd6f11fca42cdbdee49` and
matching target test.
- Advance personal-secret v9 to v10 and team-install v4 to v5. Record
the personal confirmation helper and its existing contract/flow inputs
in source provenance.
- Disclose the unmerged company-secret authorization fix from #19325. It
denies scoped agent creation before body validation and gives safe human
entry guidance. Board creation remains unchanged.
- Retain the original query history, including the single previously
approved multipart-form clarification. Preserve all 244 identities, the
196/244 gate, model, clocks, native and human bounds, SDK registry,
launcher, and private evidence protocol.

## Verification

- Pin-local checks: all **38** manifest, adapter, and reconcile controls
passed with `node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs`.
- Exact source qualification: the combined domain run passed 328
controls and skipped one optional canary. Its two local listener
failures were sandbox EPERM setup failures. The same two controls then
passed with the authorized local listener, in a 73-control run. The
eight new route authorization controls also passed. These local runs do
not prove native completion.
- Full E2E TypeScript passed on exact source ab0 after reuse of the
healthy, same-source workspace graph. Earlier missing-alias graph
failures are retained. A full local server build or repository-wide
suite was not run; #19325 has its own core checks.
- The source SDK guard verified all **506** registered input Git blobs
unchanged, registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`. No
SDK build or qualification renewal was needed.
- Actual anchored controller dependency check: `prepare-report-lock.mjs`
returned `already-reviewed`, then pnpm **9.15.4** completed the frozen,
ignore-scripts install in 17 seconds. This exercised the current
upstream Claude ACP patch and reporting output
`dd5934060dd06b8e731e3beeed49daf918d1a0b2a6c32d3da7815f2e7f0b3691`. It
made no tracked lock or policy change. Earlier source-lock and
controller-lock evidence remain separate.
- Existing failed personal/team attempts remain failed. The company
initial noncompletion remains uncorrected as an outcome claim; the
authorization fix addresses one proven error boundary only. Team
repeat/link checks were not reached in the failed measurement and remain
required. No uniform-ten PASS or new native feature PASS is claimed.
- Next validation is a controlled TestOps measurement after normal pin
merge and fresh actual-controller proof. Any later whole-ten regression
is separate. All attempts remain recorded; there is no retry-until-green
policy.
- Exact head `58d4a9b2d3c90be725e8877873010295122fb9c0`: required CI
aggregates `ci / e2e` and `ci / verify` passed in run 42099871883.
Windows passed in run 42099871391. Genuine Greptile review is 5/5 on
that exact head, with zero unresolved threads. The complete rollup has
56 successes, three configured skips, and one neutral check; no pending
or adverse check remains. No native measurement ran as part of these
checks.

## Risks

- Personal v10 accepts two logical human inputs: the original chat
request and a separately verified same-human secure-save confirmation.
The raw chat count remains one. This is a disclosed fixture variant, not
proof from a new native journey.
- The new confirmation fields do not change the trusted publisher schema
or its closed enums. Existing private helper and launcher bytes remain
unchanged.
- Team v5 only normalizes the apostrophe in its warning predicate. Saved
state, named-skill truth, repeat idempotency, links, and
contradictory-success guards still apply.
- The authorization fix is present only in the pinned source. #19325
remains unmerged; its effect on the unfinished native turn is unproven.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with reasoning, repository tools,
and local code execution. The context window size is not reported by
this runtime. No model inference was used for local tests.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-05 14:22:05 -06:00
DottaandClaude Opus 5.5 aaaad177eb fix(e2e): follow renamed project and Artifacts V1 download controls (#19323)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Product E2E journeys drive the real UI and run in the QA staging
smoke plan
> - Two UI changes landed after the previous QA deployment: the Projects
toolbar action is now "Create project" (#18716), and Artifacts V1 is on
for every instance (#19164), so attachment rows offer download as an
icon link with an `aria-label`
> - The journeys still clicked "Add Project" and required a visible
"Download" text, so they timed out before reaching the server
> - This pull request accepts both the old and the current controls
> - The benefit is that project-task-context, build-revise and
stop-redirect measure the product again on current deployments

## Linked Issues or Issue Description

**What happened?**
On the QA deployment of cb8df178c8, three journeys failed with the
generic `journey_operation_failed`: project-task-context, build-revise
and stop-redirect. Records on the stack show that build-revise and
stop-redirect delivered their ZIP and finished. The user's next
interaction never reached the server.

**Expected behavior**
The journeys use the controls that the current UI shows.

**Steps to reproduce**
1. Run the `project-task-context` product journey against a managed
local target at cb8df178c8.
2. Playwright waits 30 seconds for `getByRole('button', { name: 'Add
Project', exact: true })` and times out.
3. For downloads, an Artifacts V1 row renders `<a
href=".../content?download=1" aria-label="Download slugify.zip">` with
only an icon. `filter({ hasText: /Download/i })` matches no element.

**Paperclip version or commit**
master at 03eb49053f; deployed QA app cb8df178c8.

## What Changed

- `project-context-flow.ts`: open the new-project dialog with the button
named "Add Project" or "Create project".
- `story-artifact.ts`: find the attachment download link by "Download"
text or by an `aria-label` that starts with "Download". The attachment
ID is still required in the link.

## Verification

- Local managed target at cb8df178c8: project-task-context failed with
the old selector (Playwright timeout on "Add Project") and passed 1/1
with this change.
- A Chromium check with Playwright on V1, legacy and no-download markup:
the old locator finds 0 elements on V1 markup. The new locator finds the
download link on V1 and legacy markup, and finds nothing on markup
without a download link.
- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/product-journeys tests/runner-e2e/story-artifact`: 47
files, 1237 tests passed.
- Not run live on QA yet. QA uses the pinned harness
(`QA_SMOKE_HARNESS_SHA`), so the pin must move to a commit that contains
this change.

## Risks

- Low risk. Only the selectors change. All assertions, download checks
and artifact checks stay the same.
- The download link must still point at the exact attachment's content
route. The "Open raw" icon link is not selected.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, browser, code editing). Extended reasoning was used.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:19:50 -06:00
github-actions[bot]andlockfile-bot b37188ce42 chore(lockfile): refresh pnpm-lock.yaml (#19317)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-05 18:59:42 +00:00
github-actions[bot]andlockfile-bot b4e7b76635 chore(lockfile): refresh pnpm-lock.yaml (#19294)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened?**

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

**Expected behavior**

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

**Steps to reproduce**

Run a frozen install before and after this lock refresh.

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-11-05 17:40:05 +00:00
DottaandPaperclip 3fca8a1500 test(evals): renew the reporting lock after iMessage update (#19283)
## Thinking Path

> - Paperclip verifies the selected source and reporting dependencies
before it obtains model credentials.
> - The reporting helper admits only an exact reviewed lock or its exact
reviewed correction.
> - Master updated the iMessage dependency and protobuf after the last
reporting-policy review.
> - The controller lock therefore stopped matching either admitted hash.
> - A real five-case launch failed at this guard before any case
execution.
> - This PR renews the exact hashes and keeps the existing patch and
rejection mechanism unchanged.
> - A normal-CI repository check now exercises the real helper against
the committed lock before paid execution.

## Linked Issues or Issue Description

Refs: #19261, #18914.

**What happened?**
The five selected execution jobs in the retained launch 3002 stopped
during “Verify source-bound build and authenticated selection before
credentials.” The first observed error was `Reporting lock changed;
review the dependency correction before install` in the trusted
controller helper. Model-key and original case execution steps were
skipped. The failed attempt remains infrastructure evidence; this PR
makes no native product-grade claim.

**Expected behavior**
Admit the exact reviewed current controller dependency graph. Keep
rejecting unknown locks, changed correction patches, and wrong output
bytes before credentials or provider execution.

**Steps to reproduce**
Run the reporting helper against the committed current-master lock. The
parent policy recognizes 754… and 60f…, while the actual controller lock
is 6f252b…. The parent stops at the same pre-credential boundary as AWS.
The existing correction patch reverses and reapplies cleanly to that
lock.

## What Changed

- Renew only the reporting policy input and output SHA256 values. The
output is the exact committed current-master lock after
`@photon-ai/advanced-imessage` 2.1.0→2.2.0 and `@bufbuild/protobuf`
2.15.0→2.16.0.
- Derive input
`ea91060774e3289d5d07bc58f72d8953f5a6dcb9db98aa9a1adf202476bf89ac` by
reversing the existing correction patch from the current lock.
Reapplying that byte-identical patch yields output
`6f252b0c8099ed837a297f97f1fc5e14e96bc7530b0239065d0789b33b2ee477`
exactly.
- Keep patch SHA256
`2adced9a66052ba5752140ec6cc6670f679552a9a8559bd1faea10036afeeb97`,
helper code, and guard behavior unchanged. Update the policy basis to
describe the review truthfully.
- Add one normal server-suite check. It copies the committed lock and
reviewed policy into a temporary directory and runs the real helper. The
prior focused suite already covered this contract, but its runner-e2e
location is outside normal root Vitest projects.
`server/vitest.config.ts` already includes `scripts/**/*.test.mjs`; no
workflow change is needed.

No `pnpm-lock.yaml`, workflow, source pin, descriptor, oracle, model,
permission, credential, scanner, or case bound changes. Immutable source
6773 and the failed launch remain unchanged.

## Verification

- Parent existing reporting suite: 4 fail and 3 pass because the
committed lock is outside the admitted pair. Renewed policy: all 7 pass,
including unknown-lock, changed-patch, wrong-output, and refresh-path
rejection controls.
- New normal-CI repository control fails with the exact paid-step
reporting-lock error on the parent policy. The corrected combined run
passes 8 controls across 2 suites.
- Exact patch reverse/forward roundtrip preserves the full current lock
bytes. The actual CLI returns `already-reviewed`; the working lock hash
stays 6f252b… and is not modified.
- Focused command: `node node_modules/vitest/vitest.mjs run --config
../report-lock-imessage-vitest.config.mts`. The external local config
selects only the two affected suites with the existing 30-second test
limit.
- `git diff --check` passes. No SDK/native/source build, model call,
evaluation retry, or private archive download was needed for local
proof. Full workspace typecheck/build were not run for this
policy-and-test change. Latest-head required CI and genuine review
remain pending.

## Risks

This policy deliberately rejects the next unreviewed lock change. The
normal-CI check should expose that drift before paid fanout. The input
is the current lock with the already approved correction reversed; it is
not a claim that a new dependency graph was resolved or installed
locally. Local guard controls do not prove a repaired AWS execution or
any of the five product journeys. The next measured attempt still
requires normal protected merge and fresh actual-controller admission.

## Model Used

OpenAI `gpt-6.1-sol`, with reasoning, repository tools, and local code
execution. The host did not expose a context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-05 11:32:46 -06:00
DottaandClaude Opus 5.5 45073d97ae fix(evals): keep evidence for wakes retired by a terminal issue before start (#19258)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Product regression TestOps plan runs 20 Product E2E cells, and
each cell saves run evidence after grading
> - In the final full run, `first-task/clarify-propose-accept` passed
every journey check
> - The cell still failed while saving evidence: it requested a provider
log for a wake that never started
> - That wake was retired with `issue_terminal_status` because its child
task was already done, so no log exists
> - The settle oracle already accepts such a wake
(`isTerminalUnstartedWake`), but the evidence collector did not
> - This pull request records that wake's log as omitted, with a reason,
and keeps its events
> - The benefit is that a passing journey is no longer reported as
failed because of a log that never existed

## Linked Issues or Issue Description

Refs #19073, #19243

**What happened?**
In GitHub run
https://github.com/paperclipai/paperclip/actions/runs/42046147744,
`first-task.runner-codex.local.clarify-propose-accept` had no failed
checks in `first-task.json`. The conversational acceptance was recorded
through `resolve-from-comment` (200). The `finally` evidence step then
threw `GET /api/heartbeat-runs/ef2295c4…/log returned 404: Run log not
found`. Run `ef2295c4` is an `issue_status_changed` wake on the
completed child task. It is `cancelled` with `issue_terminal_status`,
and `startedAt`, `logStore` and `logRef` are all null.

**Expected behavior**
Evidence capture keeps that wake's events and records why it has no log,
as it already does for reset, blocked, reassigned and pre-provider runs.

**Steps to reproduce**
Run the cell. A child status-change wake may be queued just before the
child becomes `done`, and is then retired before admission.

## What Changed

- `collectChatRunEvidence` (`tests/runner-e2e/chat-flow.ts`): a run that
is `cancelled` with `errorCode: issue_terminal_status` and explicit null
`startedAt`, `logStore` and `logRef` gets `log: null` and
`logOmissionReason: "issue_terminal_before_start"`. Its events are still
collected.
- `chat-flow.test.ts`: a test for that case, plus negative controls.
Each of the following still fails on a missing log: started, `startedAt`
undefined, `failed` status, a different error code, a log store, a log
ref.

## Verification

- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/chat-flow.test.ts tests/runner-e2e/first-task.test.ts
tests/runner-e2e/continuation.test.ts`: 378 pass.
- `tsc -p tests/runner-e2e/tsconfig.json`: no errors in
`tests/runner-e2e`.
- Retained artifact from run 42046147744 (cell
`clarify-propose-accept`): there are no failed checks, and the run
ledger shows the retired wake with null `startedAt`, `logStore` and
`logRef`.

## Risks

- Low. This is an evidence-capture change in the eval harness, and the
journey's grading is unchanged. The omission needs explicit positive
evidence that the run never started and never had a log store. Any run
that did provider work still fails on a missing log.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), via Claude Code with tool use and
code execution.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 10:07:05 -06:00
DottaandPaperclip cb8df178c8 test(evals): pin the clarified five-case chat repairs (#19261)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The TestOps catalog executes one reviewed immutable source with
declared model, permissions, counts, clocks, and private evidence gates.
> - Recent retained attempts exposed specific question, timeline,
secret-handoff, and team-reporting contract gaps.
> - Five focused repairs now have one qualified source; their component
checks do not establish a native pass.
> - This PR binds the trusted catalog lane to that source and records
its exact changed definitions.
> - One visible-form question is clarified and disclosed; all other
catalog requests stay fixed.
> - The controller, launcher, private evidence helpers, and execution
authority stay unchanged.

## Linked Issues or Issue Description

Refs: #19086, #19084, #19093, #19112, #19148, #19188.

**What happened?**
The retained native attempts include a timeline narrative rejected
despite the saved handoff, secure-entry admission failures before
downstream verification, and a truthful contextual team caveat rejected
after a correct repeat. Multipart attempts4623 and4717 did not complete
under the original broad request. All original statuses and evidence
remain unchanged.

**Expected behavior**
Measure the five reviewed repairs on one immutable source with the
original model, limits, and privacy gates. A component replay must not
rewrite an old result or count as a product pass. The catalog must
display and execute the same versioned request.

**Steps to reproduce**
After normal protected merge and fresh controller admission, use the
existing TestOps plan102 and job100 to select the intended five cases on
master. Root owns the actual Submit and original-evidence review. No
evaluation is dispatched by this PR.

## What Changed

- Pin only the catalog lane to
`6773b1c128a2e7efa7571ff04b38238f00d06117`, tree
`5669b199edc1aed3ab812403407b5930f5127da4`.
- Copy its exact descriptor snapshot, SHA256
`aaf15ca6755fcfe550daa98bca1ed263e3d625159b53cd1e1f52fefbf9474778`.
Advance only multipart53 v4, timeline466 v10, company-secret578 v8,
personal-secret580 v9, and team-install610 v4. Add four declared source
paths across the two secret cases.
- Record exactly one query clarification through the existing per-case
changed-field join. Old: “Help me choose the details for the launch page
before you build it.” New: “Walk me through the launch-page question
form so I can choose the audience and tone and enter my own headline
before you build anything.” Preserve the old query and failed results in
history. Retain inventory `0cf530…` and disclose clarified inventory
`814bb363…`. All other243 catalog requests are unchanged.
- Disclose that the company-secret second human message now uses actual
saved non-secret metadata instead of repeating the initial request. Its
continuation still requires the actual agent identity. No fabricated
agent comment or private value establishes the handoff.
- Team recovery uses independent saved canonical skill/version/member
proof. No recovery-success phrase is required. A contradictory current
denial still fails; a still-missing skill still requires truthful
disclosure.
- Keep all244 identities, the196/244 admission gate, model/profile,
human/native counts, clocks, retries0, cap8, launcher, private protocol,
and SDK506/efa qualification unchanged. No product code, full catalog,
workflow, permissions, secret, runtime, or helper change lands on
master.

## Verification

- Source owner qualification:680 affected controls on the accepted
parent and213 focused successor controls plus two explicit browser
canaries, fresh same-source server declarations, and full E2E TypeScript
pass on localNode26.4.0. Registered SDK506 Git inputs, production
source, private protocol, launcher, and original limits match the
accepted source. The source-only contract/flow additions are not copied
into this controller.
- Pin-local command: `node --test
tests/runner-e2e/chat-full-catalog-testops-manifest.test.mjs
tests/runner-e2e/chat-full-catalog-testops-reconcile.test.mjs
tests/runner-e2e/chat-full-catalog-testops-adapter.test.mjs` —38 pass.
- Exact source descriptor and launcher bytes match the bound hashes. The
manifest keeps the original metadata source and source history, joins
the new descriptor, and permits only the one explicitly recorded53 query
clarification. `git diff --check` passes.
- Warm controller admission:10 committed helper byte checks, five
required source matches, and four trusted module imports passed with the
existing exact-main60f dependency graph. No SDK or native rebuild ran.
Actual post-merge master and imports still require a fresh check before
Submit.
- The53 clarification changes the evaluated question. It does not fix or
regrade the original300-second failures. All form validation, back
retention, custom answer, persisted-answer, continuation, and
visible-summary checks remain required. One targeted post-clarification
measurement is planned; any later whole-ten regression is separate, with
all attempts retained and no retry-until-green. The existing case53
description must be updated and read back after merge so TestOps
displays the clarified request.
- All five successor scenarios remain unrun. No new native pass,
uniform-ten pass, reliability claim, or master catalog qualification is
made. Focused source PRs remain separate and unmerged; their independent
CI does not replace this PR's required checks.
- Full workspace typecheck/build were not run locally for this
metadata-only PR. Current-head required CI, Windows, genuine review, and
zero unresolved material threads are required before normal protected
merge.

## Risks

A wrong source or descriptor would misstate the measured definition.
Strict target, snapshot, field, and identity joins cover that risk. The
clarified question cannot establish success for the old broad request.
Safe guidance admission still needs real human entry, private UI
persistence, and worker evidence in the next attempt. Component controls
do not prove those outcomes or completion within the original limits.

## Model Used

OpenAI `gpt-6.1-sol`, with reasoning, repository tools, and local code
execution. The host did not expose a context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-05 10:00:50 -06:00
TonioandClaude Opus 5.5 9e9a628a57 feat(ui): turn Artifacts V1 on for every instance and hide its toggle (#19164)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Artifacts show the output of agent work on the Artifacts page, in
the panel Artifacts tab, and in the task thread
> - #17228 added the Artifacts V1 presentation behind an experimental
setting that is off by default
> - The presentation is now ready for all users, so an opt-in toggle is
no longer necessary
> - A new default alone does not reach all instances, because each
experimental write persists every flag
> - This pull request removes the toggle and turns V1 on for every
instance
> - The benefit is one artifact presentation for all users, with an off
switch for hosting operators

## Linked Issues or Issue Description

Refs #17228
Refs #17263

**Is your feature request related to a problem? Please describe.**
Artifacts V1 shows only on instances where an admin turned on an
experimental setting. Other users see the previous cards.

**Describe the solution you would like**
Show Artifacts V1 on all instances. Remove the toggle from Experimental
settings.

**Describe alternatives you have considered**
A new default without a change to the hook. This does not work, because
many instances have a stored false that nobody chose, and no toggle
would remain to change it.

## What Changed

- Removed the Artifacts V1 card from Instance Settings, Experimental.
- Changed `enableArtifactsV1` to default on in the schema, the feature
catalog, and the settings service.
- Changed `resolveArtifactsV1Enabled` to ignore a stored false. It
honours false only when the value comes from managed config.
- Kept the flag and the previous cards, so a hosting operator can hold
V1 off.
- Kept the key in the Cloud staging list, so a managed false does not
hold V1 off on staging.
- Updated unit tests, the Artifacts V1 plan, and the directions-lab
Today reference.
- Moved the attachment and upload e2e specs and the runner download
helper to the V1 rows.
- Added V1 tests for a Markdown review: expansion, deep link, and open,
raw and download actions.

## Verification

- `cd ui && npx vitest run`: one test file failed before its fix. That
file tests the previous cards, and it now mocks the hook to off. I reran
it with the other changed UI tests, and they pass. I did not repeat the
full UI run after the fix.
- `npx playwright test --config tests/e2e/playwright.config.ts
tests/e2e/text-attachment-tabs.spec.ts
tests/e2e/artifact-uploads.spec.ts
tests/e2e/artifact-tab-arrival.spec.ts`: 10 tests pass on V1.
- `tests/e2e/cloud-auth.spec.ts` failed once in CI on a task heading. It
does not touch artifacts, and 10 local runs pass.
- `cd server && npx vitest run src/__tests__/instance-settings`: 183
tests pass.
- `cd packages/shared && npx vitest run src/feature-catalog.test.ts
src/validators/instance.test.ts`: 35 tests pass.
- `pnpm run check:token-gates` and the `ui` and `server` typechecks
pass. I did not run the full repository check.
- In the artifact directions lab, with no stored settings, the Today
right panel renders the V1 rows.
- I did not test this on a live instance. After merge, confirm on
staging that the Experimental page has no Artifacts V1 card and that all
three surfaces show V1.

## Risks

- All users see V1 after the next release, not only staging users. To
revert, revert this pull request.
- Users cannot turn V1 off. Only a hosting operator can, through managed
config, and not on Cloud staging.
- An instance with a managed `enableArtifactsV1: false` stays on the
previous cards. The cloud harness source has no reference to this key,
but I cannot read the live fleet configuration.
- V1 surfaces render before settings load. An operator-held instance can
briefly show V1 before the previous cards.
- Admins who use the API can still write the flag. The write has no
effect on unmanaged instances.

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

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with
tool use and code execution.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 08:14:49 +00:00
DottaandPaperclip 48b57e0c94 test(evals): pin held scenario repairs and await Cloud return (#19188)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - Protected TestOps runs admit one immutable catalog source.
> - Three held scenario observers now have reviewed, locally qualified
repairs.
> - A separate Cloud recovery test started its heading wait before the
Cloud return.
> - This PR pins the qualified successor and corrects that test
boundary.
> - It changes no product behavior, model, execution budget, or private
evidence protocol.

## Linked Issues or Issue Description

Refs: #19155, #19093, #19095, #19112.

The next candidate retains the reviewed skill, company-secret, and
team-install observer repairs. It adds a narrow timeline v9 correction:
a recorded task identifier can be the subject of its actual
reassignment. The real timeline attempt remains failed; the diagnostic
correction is not a regrade or a new native pass. Earlier failed
attempts stay retained; a source pin and component tests do not
establish a native pass.

The Cloud recovery fixture failed both direct-task variants in the first
CI attempt of #19155. Its five-second heading check started before the
external Cloud roundtrip ended. The failure image already showed the
expected task shortly afterward. One unchanged local direct-task control
passed. The single authorized CI recovery also passed; this did not
establish a reliable boundary. This PR waits for one handoff and the
exact return URL before the original heading check.

## What Changed

- Pin source `5aef4bffa2b106f2066bf2485338798f04a702bd`, tree
`464be838a448c728d44e2d5593b9d7faea266663`.
- Update the two manifest target literals and expected pin test literal.
Bind the exact v9 descriptor snapshot and its one changed timeline
oracle leaf.
- Add the reviewed two-line Cloud return readiness witness. Keep the
original five-second heading assertion and existing overall test limit.
- Use descriptor
`744a566faaa90b8048fff526e0a30b7475b86c2de88d697783f8da9e02f70e20`. Keep
the launcher, all private helpers, 244 identities, requests, setup,
human/native counts, clocks, profile, model, retry policy, permissions,
and the 196/244 gate unchanged.

## Verification

- Current infrastructure worktree: **131 pin, admission, selection,
streaming, API, and reconciliation controls passed**.
- The fixture owner ran the exact patched Cloud spec: **all five real
auth cases passed** in 37.4s. A six-second Cloud hold passed the
unchanged heading check after return. Missing handoff and missing return
controls rejected. This PR's fresh master base is verified by
current-head CI, not credited from the earlier run.
- Fresh v9 source qualification: **268 focused timeline controls**, the
242-declaration gate, fresh server declarations, and full E2E typecheck
passed under local Node **26.4.0**. The preceding held-helper
qualification (239 Node controls and one offline Chromium route control)
remains evidence for the byte-identical unaffected helper closures. The
original browser sandbox failure is retained. Actual AWS Node and model
configuration remain unchanged.
- All 506 registered SDK input Git blobs and registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8` equal
the prior qualified source. No new SDK build or runtime refresh.
- All 75 private protocol files, production trees, YAML, lockfile,
launcher, identities, counts, clocks, and sourceFiles declarations equal
the prior source. Only the timeline descriptor oracle advances v8 to v9.
- Prior head `ce18f2bd52ed00ce750302f63aecc4167a3daff3` finished CI with
43 passed, one expected skip, four originating runner interruptions, and
a failed dependent verify aggregate. Two logs show runner shutdown
signals; two annotations show lost runner communication. No assertion
failure was observed. Those outcomes are retained; no unchanged recovery
was requested.
- Required fresh current-head CI, genuine review, thread clearance, and
Root's exact-diff acceptance are pending. No merge or new paid run is
authorized by this PR's publication.
- The earlier 3 PASS / 7 FAIL uniform attempt and all later original
outcomes remain unchanged. No new native pass or whole-catalog readiness
claim is made.

## Risks

The source remains a frozen candidate with unmerged catalog repairs. A
real measured run is still required. The readiness witness requires both
a real handoff and the exact task URL; it does not extend the heading
timeout, bypass auth, skip a case, or change production code. The active
measurement on the previous pin is not altered.

## Model Used

OpenAI GPT-6.1 (`gpt-6.1-sol`), with reasoning, code execution, and
repository tools. The host did not expose a 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 for and linked related public PRs above
- [x] I have linked public PRs and described the issue
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change
- [x] Relevant local pin tests passed; source and fixture qualification
scope is stated above
- [x] I have updated the expected pin test and the observed fixture
boundary
- [x] Owning source metadata and this description document the change
- [x] I have considered and documented the risks
- [ ] All current-head infrastructure CI gates are green
- [ ] Greptile is 5/5 with no unresolved material findings
- [x] I will address reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-04 23:14:14 -06:00
DottaandPaperclip 088e959d7b test(evals): pin qualified chat scenario follow-up repairs (#19155)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The protected TestOps workflow admits one fixed catalog source.
> - The retained uniform attempt exposed scenario observation and
grading gaps.
> - Focused source PRs now contain the reviewed repairs and local
controls.
> - A new immutable candidate combines those changes without a runtime
refresh.
> - This PR binds that qualified candidate for a future normal TestOps
measurement.

## Linked Issues or Issue Description

Refs: #19135, #19148, #19086, #19084, #19093, #19095, #19100, #19112.

The previous uniform attempt finished **3 PASS / 7 FAIL**. Its original
results and the separate failed control result4587 remain retained. The
source repairs correct visible multipart summary evidence, canonical
skill navigation, bound approval history, timeline attribution,
credential guidance, company configuration questions, and team-install
observation. Local qualification is component evidence. It does not
establish a new passing uniform-ten attempt.

## What Changed

- Pin immutable source `2ec214914cdaa11148ab2527d2203303f1485e2f`, tree
`f1dc0c47668e1ed1db1b4d1ead4d3d262edefc0a`.
- Update eleven existing oracle-version declarations in the manifest and
its frozen descriptor snapshot.
- Keep all 244 identities, 242 canonical declarations, requests, setup,
human/native counts, clocks, model, profile, retries, permissions, and
the 196/244 readiness gate.
- Preserve historical manifest provenance and prior failure records.
- Keep the launcher and all 75 private protocol files byte-identical to
the prior source. This PR changes no controller helper or workflow.

## Verification

- Existing focused pin, selection, admission, streaming, API, and
reconciliation tests: **131 passed**.
- Source owner qualification on the exact published candidate: **675
Node controls and 20 hire DOM controls passed**; all six affected
domains are included. The 242-declaration gate passed.
- Fresh server declarations and full E2E typecheck passed on the exact
candidate under local Node **26.4.0**. The temporary Node24/output tree
disappeared; the source owner restored exact frozen dependencies and
rebuilt only missing identical-source outputs under Root authorization.
Actual AWS Node and the model profile remain unchanged.
- Existing SDK guard: **506 registered inputs unchanged**, registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`; no
SDK renewal or runtime build.
- Production server, packages, CLI, UI, YAML, and lock bytes equal the
prior source. Only eleven oracle-version descriptor leaves change.
Query, clock, count, and policy comparisons passed.
- Launcher SHA256 stays
`2b9a6953ee51f0ea0dbbd475b0491d9a6c39a1d6835eeaa912e0dbb7cf987724`.
Descriptor SHA256 is
`41038d984f045f593923da53ac036a9a6adefed5edcaedc609e55991e2fa03b7`.
- The next controlled acceptance selection is **only [53, 466, 564,
580]**. Their current source reviews and manual contract reviews are
clear. Cases 74, 578, and 610 have separate open observation findings
and remain held. This pin does not qualify the whole catalog or a
uniform-ten result.
- Root approved the final three-SHA pin delta. Exact current-head pin
review is 5/5 with no unresolved threads, and Windows passed. Normal CI
is terminal and blocked: 42 jobs passed, one expected selector skipped,
and six failed. Both direct-task Cloud recovery variants failed the
existing initial heading check. The native Runner, package Runner, and
server1 test leaves lost communication with their self-hosted runners,
as the GitHub annotations confirm. Their host cause is unproven; Spot is
not established. The dependent E2E and verify aggregates also failed.
Original CI results are retained. One same-head failed-jobs-only
recovery was accepted after a fresh terminal/head guard. The independent
unchanged direct-task control passed locally in 4.9s; the CI trace shows
its five-second heading wait began before the Cloud roundtrip, with the
expected page visible in the failure screenshot shortly afterward. This
supports a test-boundary hypothesis, not a fixed race or reliability
claim. Attempt 2 is pending; no second unchanged retry is authorized.
Merge remains blocked until all required gates pass. Individual source
PRs retain their separate CI and base-policy limitations; this PR does
not claim that all source PRs are merge-ready.
- No model call, TestOps submission, archive read, permission change,
core merge, or catalog merge occurred during this pin work.

## Risks

The candidate contains unmerged catalog changes. The protected source
pin keeps that boundary explicit. Component controls cannot replace a
real product attempt. Prior failures and unknown historical grades
remain unchanged. A future measurement must use the admitted source and
original bounds.

## Model Used

OpenAI GPT-6.1 (`gpt-6.1-sol`), with reasoning, code execution, and
repository tools. The host did not expose a 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 for and linked related public PRs above
- [x] I have linked related public PRs and described the issue
- [x] I have not referenced internal or instance-local Paperclip links
- [x] My branch name describes the change
- [x] I have run the relevant pin tests locally and they pass
- [x] I have updated the source pin regression and descriptor snapshot
- [x] I have updated the owning source provenance conditions
- [x] I have considered and documented the risks
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-04 22:32:45 -06:00
DottaandPaperclip a0250284e3 fix: preserve proposal revision turns and prove chat completion (#19105)
## Thinking Path

> - Paperclip manages work done by AI agents.
> - A completed delegated task must report its result to the originating
chat.
> - That report uses a real provider turn and must stay in cost
accounting.
> - Ordinary first-task proposals must also support the promised chat
acceptance path.
> - A revision response can reject an older proposal before it creates
the replacement.
> - The old rejection transition clears that active response's ownership
and blocks its next tool.
> - This change proves required completion work, guides ordinary
proposal policy and preserves the revision turn under the existing
locks.

## Linked Issues or Issue Description

No separate issue exists. The original failures remain in [the complete
Product
run](https://github.com/paperclipai/paperclip/actions/runs/41915965118).
The independent continuation repair is #19076. Related #12209 concerns
prior-run confirmation binding. This change fixes the ownership reset
during rejection, rather than changing binding authorization.

**What happened?**

The complete 20-case run finished with 13 passes and 7 failures. Three
delegated-chat cases counted one required `chat_task_completed` provider
turn as unexpected work. Two first-task agents chose optional human-only
cards, then correctly received 403 when they tried conversational
acceptance.

A [reviewed two-case candidate
run](https://github.com/paperclipai/paperclip/actions/runs/41931445311)
then used the changed first-task skill. Both models inherited the
ordinary resolver policy. Clarify/propose/accept passed all 12
predicates. Revise/accept failed after the new response rejected its
predecessor's proposal. The saved rejection was followed by
`paperclip_runner_tool_binding_not_authorized` on its next tools. The
final `native_session_lease_lost` label followed those binding failures;
this PR does not assume lease expiry caused them. Both cells cleaned up
and published their original grades.

**Expected behavior**

Keep the existing ordinary-turn bounds and account for one independently
proved completion notification. Inherit the normal resolver policy for
ordinary proposals that accept chat replies. When an active response
rejects an older proposal, save the rejection and retain that response's
current ownership so it can create the revised proposal. Keep human,
current-source and native completion-review rejection behavior and all
real approval restrictions.

**Steps to reproduce**

The original full run used `4740d251`. The two-case candidate used
trusted workflow `7d1e9b34` and target `74da56c4`. Run the focused
provider-free controls below. The dual-run API regression first fails
because rejection changes the issue to `todo` and clears the newer run's
execution and checkout fields.

## What Changed

- Prove one completion notification only for native Codex/local
`multi-repository`, `clarify-reuse` and `plan-handoff`. Keep the
ordinary bounds of 2, 3 and 4. Preserve actual totals of 3, 4 and 5, all
run IDs and all usage.
- Read those declared totals from the current catalog, which now
includes the completion reply. Check the total once and prove that
exactly one turn is the required notification. Do not add another turn
while waiting. The required-server controls use the actual catalog
tasks.
- Bind the notification to the same company, agent, conversation
generation, completed child, single delivery, accounted native run,
saved reply and rendered result link. Reject extra work, duplicate
deliveries, unknown events and mutations, including native work without
a Paperclip tool call.
- Collect workspace operations through the real run API for these three
proofs. Keep other collector calls unchanged. Keep the proof controls in
the existing required server test lane.
- Stop idle polling on a permanent completion-proof error. Continue to
retry transient observations within the original 240-second window.
- Guide ordinary chat-accepting first-task proposals to omit optional
`resolverPolicy` and inherit server/company defaults. Preserve explicit
and governed human-only restrictions. Do not lower or recreate saved
restricted cards.
- Under the existing locked issue and interaction rows, preserve the
active responding run when it rejects a different source run's proposal.
Change only the ordinary requeue predicate. Keep the saved rejection,
notifications, activity and existing Telemetry calls. Keep global
status, lease and tool-authority guards unchanged.
- Extend the existing native API controls with the actual dual-run
rejection/revision sequence and policy, provenance, human,
current-source and native completion-review countercontrols. No new
workflow or test framework is needed.

## Verification

- Current combined head is `a8567ded67e5ab811675390e9a5c5ed2194aee2f`,
integrated cleanly on `fb96537e28c4c7bfced4939909cb334392320868`. The
upstream completion-reply waiter is preserved. [Current required
CI](https://github.com/paperclipai/paperclip/actions/runs/41940780852)
passes. Actual test checkout `ff93c034d7bb40f3df7bc75cf51828fd07bb0d29`
merges this head into `9c6993f0aab7ebb22a26d78f5d227accb35a6ad1`.
- Fresh Greptile is 5/5 on exact head `a8567ded`, with no blocking
finding. All addressed review threads are resolved. The separate
automated reviewer emitted a paused-work response; that response is not
a review approval.
- Current required server CI actually passed all 11 native confirmation
API cases, 46 completion-proof controls and 13 onboarding asset checks.
Canonical typecheck, Build, the native package/server suites, all
browser and serialized shards, `ci / e2e` and `ci / verify` pass. No
current-head CI retry was needed.
- Local dual-run RED: the unmodified transition returned HTTP 200 and
saved rejection, then changed the issue to `todo` and cleared the newer
run's execution/checkout fields. Whole setup and check took 28.95
seconds; the case took 596 ms.
- Local treatment: all 11 real native/API cases pass. The same-session
response retains execution/checkout ownership, reads task context and
persists the recorded-shape revised confirmation. Its stored lease
receipt stays intact and one rejection activity is saved. Human-only
rejection, current-source rejection, human rejection with/without a
newer owner, Plan/Ask, foreign provenance, authentication and formal
approval controls pass.
- All 59 existing confirmation resolver controls pass in 16.62 seconds.
These cover cancellation, lost ownership, company/user scope, policy
changes, transactional rollback, concurrent retries and stale revisions.
- All 46 completion controls pass in 4.07 seconds. The two added clock
controls preserve the original idle deadline and prove immediate
permanent-proof failure plus transient observation retry. The existing
live collector-to-proof and native mutation negatives remain in this
required server file.
- The first current-catalog integration check failed 5 controls in 2.70
seconds. The old consumer added the already-declared reply again and
could accept an extra ordinary turn. The corrected consumer passes all
46 controls using the actual catalog. The existing full 20-case
catalog/reporting compatibility check also passes in 4.93 seconds. Case
identities, configured models and reporting match the declared 20.
- The API controls used one owned loopback PostgreSQL instance through
existing supported test hooks. It was stopped and removed. Earlier
missing-library/setup failures and one corrected current-source test
expectation remain retained; they are not counted as product failures or
passes.
- The unchanged first-task skill has SHA-256
`b789090996e7925676590c006418eb8b57f4514e646f6bca18ffd7b2b8e864de`. Both
candidate runtime copies matched it. The inherited policy was observed
in both models; one complete acceptance journey passed. This does not
qualify the new rejection repair.
- The three retained real completion streams pass the stronger local
proof, including native items, workspace observations and recorded DOM
links. Their original failed grades stay unchanged.
- Earlier related checks passed 153 hiring/non-execution controls and 13
asset checks. Their source is unchanged. Required discovery includes the
completion, API and asset files exactly once.
- Prior candidate `74da56c4` passed all required CI, including canonical
typecheck and build, in [CI run
41929148958](https://github.com/paperclipai/paperclip/actions/runs/41929148958).
Its fresh Greptile was 5/5. This is prior-head evidence.
- The intermediate `053150d9` head also received Greptile 5/5. Its [CI
run](https://github.com/paperclipai/paperclip/actions/runs/41940014165)
and review stay retained as superseded evidence. They do not qualify the
final catalog correction.
- A clean full local typecheck/build is not claimed because the reused
dependency cache has stale adapter-utils/Runner declarations. No source
or lock workaround was made. Fresh canonical CI must pass before merge.
- The original full-plan result remains 13/20. The separate two-case
probe remains 1/2. A fresh complete saved-plan run against delivered
source is required for acceptance. No case, assertion, model, budget,
timeout or failed grade is changed.

Focused commands:

```sh
# From server/; database URLs point only to an owned disposable local instance.
node ../node_modules/vitest/vitest.mjs run src/__tests__/chat-completion-proof.test.ts
PAPERCLIP_TEST_DATABASE_URL="$OWNED_TEST_DATABASE_URL" node ../node_modules/vitest/vitest.mjs run src/services/native-runtime/confirmation-comment-api.integration.test.ts
PAPERCLIP_TEST_POSTGRES_ADMIN_URL="$OWNED_TEST_DATABASE_URL" node ../node_modules/vitest/vitest.mjs run src/__tests__/confirmation-comment-resolution.test.ts
```

## Risks

- The ownership exception applies only to an agent acting as the current
execution run against a different non-null source run. Human, unowned
and current-source requeue behavior must stay intact. Native
completion-review handling remains separate.
- The completion proof fails closed on new native tools or event shapes.
A new shape needs review.
- A stored unchanged lease receipt is supporting local evidence. The
final real journey must prove full revision, execution and delivery.
- The new head still needs normal protected merge approval. The optional
queued Paperclip review is not a passing review. No causal repair of
unrelated CI intermittency is claimed.

## Model Used

OpenAI `gpt-6.1-sol` in Codex, with `max` reasoning effort. The runtime
reports a 475,000-token context window. Used reasoning, code editing,
shell tools and provider-free controls.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-04 22:04:12 -06:00
DottaandPaperclip 7c66b6b1f6 test(onboarding): cover plan, hiring, and execution approval history (#19069)
## Thinking Path

> - Paperclip manages agent work and human decisions.
> - Onboarding can approve a plan, a hire, and an execution step in
separate turns.
> - Tests covered single approvals more closely than that full history.
> - The repaired gate must retain valid plan approval through later
decisions.
> - Every consumer must recognize the saved confirmation kind and
selected scope.
> - This change tests that contract and registers a complete
interview-to-execution journey.

## Linked Issues or Issue Description

Refs #19043, #17914, #18283.

The earlier tests admitted one accepted proposal at a time.
Decomposition fixtures used standard confirmations. The direct-task E2E
path forbids hiring. Those cases did not cover an accepted checkbox plan
followed by hiring and a separate untargeted execution approval.

## What Changed

- Add eight PostgreSQL contract cases for standard and checkbox plan
approvals. Native tools create the cards. An authenticated human accepts
them through HTTP. A later native run reads the approved revision and
actual selected scope.
- Exercise native task creation, generic REST creation, child REST
creation, and accepted-plan decomposition. Check the assigned child and
one creation audit event. Check durable replay on the three entry points
that support it. A pending execution confirmation still prevents
creation.
- Register the explicit-only `onboarding-approval-history` suite for
local native Codex and ACPX Claude. The browser chooses the interview,
selects only drafting in the saved plan, approves one writer hire, and
approves a separate Start drafting confirmation. The model must hire the
writer and use that writer's own child execution to save the welcome
document.
- Grade each human decision, the unchanged plan revision and selection,
approval timing, one assigned child and worker execution, the exact
writer-authored saved revision, no pending requests, and persistence
after reload. Calibrate the oracle against missing, forged, premature,
duplicate, and changed outcomes.
- Preserve synthetic option choices, document/run bindings, and saved
revision authorship in the existing public first-task evidence
projection. Keep private provider/account data excluded. Document the
workflow, evidence, billing, and cleanup bounds.
- Align the approval-history fixture with its completion oracle: the
onboarding parent must be Done. Test both native profiles against graded
completion evidence and reject a completed child whose parent remains In
review. Count parent heartbeats separately from the writer: accept one
to seven parent records while retaining the twelve-company-run cap and
the independent three-approval/one-writer oracle.
- Retain the existing 52-cell first-task suite. The new suite has one
attempt, seven expected work turns, a twelve-run maximum, a
fifteen-minute deadline, and the existing $5 company task budget. It is
excluded from `--all`.
- Update two stale cleanup assertions to include the existing
thirty-second deletion timeout.

## Verification

- Red control: temporarily restore the pre-fix admission module and run
the new checkbox/native history case. It fails with the expected
`First-task proposal requires human acceptance` error after plan,
hiring, and execution acceptance. Restore the repaired module after the
probe.
- The final post-rebase history matrix and existing onboarding safety
suite passed together: 74 tests, no skips.
- Final focused Runner E2E support passed: 413 Vitest tests and all 370
Node support checks. This covers catalog discovery, journey controls,
wrong-outcome calibration, public evidence, and existing first-task
behavior.
- Review controls: four authorship cases fail before the revision check.
A delayed browser-response control fails before the approval-time fix.
Both pass after repair. The final oracle requires the exact current
document revision, writer ID, native child run ID, matching body, and
readback after reload.
- Credential-free discovery lists both new native cells. No provider
call was made. `OPENAI_API_KEY` and `ANTHROPIC_API_KEY` are absent, so
the real provider journey remains unqualified.
- The earlier broad credential-free E2E support run reported 6,728
passing cases, three skipped cases, and nine failures in three unrelated
files. All nine reproduce with the changed E2E source restored to the
unchanged baseline: three expired overhead-fixture cases, one stale Pi
profile-version assertion, and five workflow security assertions. This
change does not alter those files, paid workflow policy, or provider
pins.
- Previous full workspace typecheck/build and [Linux
CI](https://github.com/paperclipai/paperclip/actions/runs/41921754638)
passed on `4f431f5aae99d072cc75027e90d7b847b4c342ca`, including the new
eight-case PostgreSQL file. Ponytail subsequently found a fixture/oracle
terminal-status mismatch. Both native-cell controls fail on that fixture
(`done` observed versus `in_review` expected), while the
parent-in-review negative control passes. A second comparison uses the
actual `matchesRunCount` predicate: graded evidence with six parent runs
and one writer run fails the old exact-seven-parent requirement. Both
fixes pass these controls, all 413 focused support tests, all 370 Node
checks, and the owning E2E project typecheck. [Fresh
CI](https://github.com/paperclipai/paperclip/actions/runs/41936699686)
passed on `91c980b110252da451b92eda597c168517de1276`: 48 successful jobs
and one expected skip. Greptile reviewed this head at 5/5 with no
unresolved findings. Ponytail's terminal-status finding is fixed and its
thread is resolved; its current-head re-review remains queued. Live
provider cells remain unqualified.

## Risks

The production API and approval gate are unchanged. The new paid journey
can expose model or product failures at an intermediate approval
boundary. It retains those failures and uses the existing diagnostics
and cleanup. Registration and deterministic tests do not establish a
live provider pass. The unrelated baseline support failures remain
explicit.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-04 21:46:55 -06:00
Dotta 9c6993f0aa test(evals): pin corrected chat catalog and restore retained attachments (#19135)
## Thinking Path

> - Paperclip uses real Product E2E journeys to verify agent work.
> - The trusted TestOps controller must bind the reviewed source and
retain inspectable evidence.
> - The last uniform attempt exposed bounded observation and
evidence-retention defects. Its original outcomes remain unchanged.
> - The reviewed successor corrects those boundaries with the original
model, requests, counts, and clocks.
> - Its private framework report stores canonical attachments once. The
controller must validate and restore those references before normal
reporting.
> - This PR ports that reader support and pins the qualified source in
one infrastructure change. It does not merge the full catalog or its
core repair PRs.

## Linked Issues or Issue Description

Refs #19127, #19083, #19086, #19084, #19093, #19095, #19100, #19112.

**What happened?**

The last uniform attempt retained real failed outcomes. It also lost the
multipart-question original when evidence packaging exceeded its
unchanged physical byte allowance. Review found independent boundaries
in skill navigation, announcement observation, timeline attribution,
hire history, credential questions, and team visibility.

**Expected behavior**

The next run must execute the same ten requests against one reviewed
source. The controller must retain complete original evidence, validate
private attachment references, and report the actual outcome. Historical
failures and missing-original UNKNOWN grades must remain unchanged.

**Steps to reproduce**

Use the focused source controls linked above. The private framework
control uses a real failed Playwright test and a 140 MiB attachment.
Legacy duplicate carriers hit the old cap. Canonical original evidence
passes both seals and strict archive restoration. The controller
restores derived files and the existing TestOps exporter preserves the
failed result.

**Paperclip version/commit**

Qualified candidate: `155dd1bc1c4b85ae107f6a0cd429720caa281367`. The
controller port is based on current master. The full candidate catalog
stays on its own immutable branch.

**Deployment mode**

Existing AWS/TestOps job 100, plan 102, branch master. This PR does not
dispatch a run.

## What Changed

- Pin the published qualified source and its exact launcher and
descriptor fixtures.
- Preserve current manifest history. Update twelve declaration fields
across eleven cases: oracle versions and skill source-file provenance
only. Preserve all 244 identities, 242 canonical declarations, queries,
setup, human/native counts, clocks, profile, model, retry policy, and
global cap of 8.
- Port the exact source-owned compact framework helper and
private-transfer reader. Keep the three existing required
source/controller protocol helpers byte-identical.
- Validate both sealed inventories before restoring registered
attachments into the derived selected report tree. Verify exact bytes
and hashes. Preserve seals and unregistered evidence.
- Keep deep JSON, decoded-body, sensitive-key, path, and original/final
status checks. Plain-text bodies and registered plain files fail closed
if existing diagnostic redaction would change them; JSON remains under
structured inspection. Keep all existing physical byte, entry, ZIP,
time, privacy, and archive bounds.
- Preserve registered clean metadata and attachment bytes. Reject
content that needs privacy redaction instead of silently rewriting
immutable evidence.

## Verification

- 131 existing Node pin, selection, admission, adapter, reconciliation,
and security controls pass. The explicit new target assertion and drift
negatives remain active.
- 86 current-controller controls pass. They cover legacy reports,
privacy and static assets, canonical reference guards, both seals,
strict archive restoration, derived files, the actual report normalizer,
and the actual TestOps/Allure exporter. The original failed result stays
failed; screenshot and trace hashes resolve.
- Actual P1 controls reject both an unknown password in a decoded
plain-text body and an unknown command token in a registered text file.
Parent code fails both controls; corrected code passes. The composed
source passes 87 affected controls, fresh server declarations, and full
E2E typechecking. The old cfe head completed all 49 CI jobs without
adverse conclusions, but its review found this real privacy defect. That
CI result is not credited to this successor.
- The existing report-lock preflight returns already-reviewed at
`60f4c06bca47af3ab9d74281f2ef2e1ff559d566b862ba51c2fbe6c8e5bac35b`.
- The existing source SDK guard confirms 506 registered inputs,
unchanged registry
`efa70621e9fb42aa185f7ee616a1a726aa3eccb367e67e28817cedf26ef2ade8`, and
unchanged runtime pins. No registry renewal or SDK build was needed.
- Source launcher SHA-256:
`2b9a6953ee51f0ea0dbbd475b0491d9a6c39a1d6835eeaa912e0dbb7cf987724`.
Descriptor SHA-256:
`e026d5c000102f8d50397dc59055d187388304f91dbca9a6ccfbe747004cd16d`.
- No model call, evaluation dispatch, evidence download, reporting
retry, core merge, or permission change was performed. Full current-head
CI and review are pending. Separate source PR failures remain disclosed;
local controls do not establish universal source CI readiness.
- Seven cases have verified passing historical attempts. A uniform
passing ten-case run remains unverified. The old lost multipart-question
original remains UNKNOWN.

## Risks

This changes a trusted evidence reader and the source selected for
future measurements. The new helper is included in the controller import
closure. Compact references require matching originals; missing,
foreign, changed, unsafe, or redaction-required evidence fails closed.
Legacy reporter formats remain valid. A single canonical evidence set
can still exceed a bound. Current-head CI and material review must pass
before normal protected merge. Actual AWS/TestOps evidence remains
required afterward.

## Model Used

OpenAI `gpt-6.1-sol`, with reasoning, code editing, and tool use. The
host does not expose the context-window size.

## Checklist

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

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Runner Full-Stack E2E workflow runs the paid Product E2E cells,
including the Product regression TestOps plan
> - #18983 added an optional `testops_selection` job and made `catalog`
depend on it
> - That job is skipped in every ordinary manual or scheduled campaign
> - GitHub's implicit `success()` also fails when an ancestor job was
skipped, so every job below `catalog` was skipped
> - Since #18983 merged, ordinary campaigns run no cells: the merge
reports every selected cell as "No result artifact was uploaded"
> - This pull request gives each job below `catalog` an explicit status
condition
> - The benefit is that ordinary, nightly and branch-targeted campaigns
run their cells again, and TestOps campaigns are unchanged

## Linked Issues or Issue Description

Refs #18983, #19000

**What happened?**
Run https://github.com/paperclipai/paperclip/actions/runs/41914430034
selected 20 Product regression cells with the `id` input. `catalog`
passed. `daytona_image`, `build_runner_artifacts`,
`build_remote_provider_pack` and every matrix job were skipped. The
merge failed with 20 "No result artifact was uploaded" rows.

**Expected behavior**
An ordinary manual campaign runs its selected cells when
`testops_selection` is skipped, as it did before #18983.

**Steps to reproduce**
Dispatch `runner-full-stack-e2e.yml` on `master` without `testops_case`
or `ALLURE_JOB_RUN_ID`. The scheduled daily campaign has the same path.

## What Changed

- `daytona_image`, `build_runner_artifacts`,
`build_remote_provider_pack`, `test`, `test_recurring` and
`test_manual_private` now start with `!cancelled()`.
- Each of those jobs now requires `needs.<job>.result == 'success'` for
each of its real dependencies. A failed or skipped build still skips the
cells, as before. The existing schedule, cadence and evidence-route
conditions are unchanged.
- A new regression test parses the workflow. It requires every job below
`testops_selection` to use a status function and to require each real
dependency result.

## Verification

- `node --test tests/runner-e2e/product-regression-testops.test.mjs`:
15/15 pass.
- Negative control: the new test fails against the current `master`
workflow.
- `daytona-image.test.ts`, `workflow-target.test.ts` and
`workflow-timeout.test.ts` pass. `workflow-security.test.ts` has 5
failures. The same 5 fail on unchanged `master` (they concern
`pr-trusted.yml` and `chat-catalog-testops-case.yml`).
- A workflow change takes effect only from `master`, because paid
campaigns run only from the default branch. After merge, dispatch an
ordinary `id=` campaign and confirm the cells run.

## Risks

- Low risk. The conditions keep the previous failure propagation: a job
runs only when each direct dependency succeeded and the run is not
cancelled.
- `catalog` success already implies `authorize` and `target_lock`
success, so those are not repeated.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), via Claude Code with tool use and
code execution.

## Checklist

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 17:41:18 -06:00
DottaandClaude Opus 5.5 23cd123ff8 fix(e2e): retain the closed cause code of a journey cleanup failure (#19079)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Product E2E journey harness runs the QA staging smoke plan and
reports each case to TestOps
> - Each case runs a journey, then releases its owned target resources
(cleanup)
> - Three recent cleanup failures had a passed journey and all checks
passed, but each result only says `target_cleanup_failed`
> - The adapter throws an error with a closed identifier code, and the
harness discards that code, so no one can find the failing cleanup step
> - This pull request keeps the identifier-shaped cause code as an extra
cleanup phase
> - The benefit is that the next cleanup failure is diagnosable from
TestOps without private runner files

## Linked Issues or Issue Description

**What happened?**
QA staging smoke cleanup failures show only `target_cleanup_failed`.
This occurred for `question-answer-resume` (launch 2390), and for
`company-access-isolation` and `create-skill-studio` (launch 2693). In
each case, the journey and all behavioral checks passed. The private
runner report is deleted with the runner, and the adapter error code is
not kept in the retained result. The cause is not known.

**Expected behavior**
A cleanup failure keeps a closed, identifier-shaped cause code (for
example `fixture_cleanup_not_confirmed`). The result never keeps the raw
error message.

**Steps to reproduce**
1. Run a Product E2E journey with a target session whose `release()`
throws an error that has a `code` property.
2. Read `normalized-results.json`.
3. Before this change, the cleanup phase only contains
`target_cleanup_failed`.

**Paperclip version or commit**
master at c99bcd89fe.

## What Changed

- `tests/runner-e2e/product-journeys/launch.ts`: when target release or
stop-only recovery fails, also record `cause.<code>` as a failed cleanup
phase. The code must match `^[A-Za-z][A-Za-z0-9_]{1,79}$`. Other values
are ignored. Timeouts keep their existing codes. `result.error` stays
`target_cleanup_failed`.
- `tests/runner-e2e/product-journeys/campaign.test.ts`: add a regression
test. It checks that an identifier code is kept, that the raw message is
not kept, and that a free-form code is not kept.

## Verification

- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/product-journeys`: 46 files, 1235 tests passed.
- Negative control: with the old `launch.ts`, the new test fails. With
the change, it passes.
- `tsc -p tests/runner-e2e/tsconfig.json` shows no errors in the changed
files. (This worktree has unbuilt workspace packages, so other unrelated
errors appear.)
- The Paperclip Cloud TestOps exporter already publishes phase codes
that match its closed code pattern as step messages. A `cause.*` code
matches that pattern.
- Not verified live: QA staging smoke uses a pinned harness revision
(`QA_SMOKE_HARNESS_SHA`). The new phase appears in TestOps only after
the pin moves to a revision that contains this change.

## Risks

- Low risk. The change only adds a phase entry when cleanup already
failed. Pass and fail grading does not change.
- An adapter could put private data into an error `code`. The strict
identifier pattern limits this to short identifier strings.
- Report consumers that count cleanup phases see one more failed cleanup
phase.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, browser, code editing). Extended reasoning was used.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 17:41:03 -06:00
DottaandClaude Opus 5.5 b1a71044af fix(evals): observe chat handoff replies and restarted task pages (#19073)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Product regression TestOps plan runs 20 Product E2E cells
through `runner-full-stack-e2e.yml`
> - The full 20-case TestOps launch on `master` 4740d251 passed 13 of 20
> - Four failures came from the eval's observation, not from the product
> - Three Agent Chat handoff cases raced the product's completed-handoff
reply turn, and the run-count contract treated that reply as an
unexpected run
> - One continuation case waited for `DOMContentLoaded` after a server
restart, which the dev server can leave pending while the page is
interactive
> - This pull request makes the eval observe those two behaviors
explicitly
> - The benefit is that these cases measure the product again, and the
handoff cases now also prove that the result returns to the chat

## Linked Issues or Issue Description

Refs #14408, #19053

**What happened?**
TestOps launch https://paperclip.testops.cloud/launch/2694 (GitHub run
https://github.com/paperclipai/paperclip/actions/runs/41915965118)
failed these cells:
- `agent-chat` `multi-repository`, `clarify-reuse`, `plan-handoff`:
"Declared total provider-run bounds". Each final run ledger has exactly
one extra run. That run is the source chat's `chat_task_completed` turn,
with `chatCompletionUpdates` naming the finished task.
- `continuation` `completed-action-resume`: `page.goto: Timeout 30000ms
exceeded` waiting for `domcontentloaded` right after the deliberate
server restart. The server log shows the page loaded and called the API
during that wait.

**Expected behavior**
A completed handoff returns to the source chat (#14408). The eval must
observe that reply, require it, and count it. After a restart, the eval
must wait for the rendered task, not for a browser load event.

**Steps to reproduce**
Run the cells listed above on `master` with the Product regression
TestOps lane.

## What Changed

- `chat-flow.ts`: after the delegated task is `done`, the handoff branch
waits for the source chat's completion-reply turn
(`chat_task_completed`, correlated by `chatCompletionUpdates[].id`). It
requires exactly one such turn, `succeeded`, and exactly one agent
comment created by that turn.
- `chat-cases.ts`: the declared run counts include that one reply turn:
`multi-repository` 2 → 3, `clarify-reuse` 3 → 4, `plan-handoff` 4 → 5.
The minimum and maximum stay equal, so a missing reply or an extra run
still fails.
- `catalog.test.ts`: the catalog run-count total changes from 385 to 397
for these three cases across their profiles.
- `continuation-flow.ts`: `open()` uses `waitUntil: "commit"` with a 60
s navigation limit, then requires the rendered task thread
(`waitForTaskChatRendered`). This matches the existing restart handling
in `chat-flow.ts`.

## Verification

- `npx vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/chat-flow.test.ts tests/runner-e2e/continuation.test.ts
tests/runner-e2e/catalog.test.ts
tests/runner-e2e/kimi-qualification.test.ts
tests/runner-e2e/non-execution-wake.test.ts
tests/runner-e2e/product-regression-testops-catalog.test.ts
tests/runner-e2e/lifecycle-live.test.ts`: all pass.
- `tsc -p tests/runner-e2e/tsconfig.json`: no errors in
`tests/runner-e2e`.
- The retained ledgers from run 41915965118 show the reply turn:
`multi-repository` 3 runs, `clarify-reuse` 4 runs, `plan-handoff` 5
runs, each with one `chat_task_completed` run on the chat issue.
- Live single-case TestOps runs against this branch: see the PR
comments.

## Risks

- Changed eval conditions: the three handoff cases now also require the
completion reply. A product regression that drops the reply now fails
these cases, as intended.
- The continuation navigation allowance changes from 30 s
(`domcontentloaded`) to 60 s (`commit`) plus a rendered-thread check.
That is an observation deadline, not a product latency requirement. The
rendered-thread check is stronger than the old load event.
- Three other plan failures are not changed here. They are product
failures: the agent creates `human_only` confirmations, and
`resolve-from-comment` then refuses to record the user's explicit text
approval (`interaction_human_only`).

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), via Claude Code with tool use and
code execution.

## Checklist

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

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 17:40:58 -06:00