Files
PaperClipAI/tests
DottaandClaude Opus 5.5 068d814735 test(chaos): run waves in Cloud's volume-free server mode; make W2 phase 1 yield (#20930)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The restart chaos harness (`tests/restart-chaos/`) runs real agent
tasks against an isolated control plane and injects faults
> - Cloud servers run in the volume-free mode
(`PAPERCLIP_EPHEMERAL_SERVER=true`, durable agent files, run logs in
object storage)
> - The harness never set that mode, so every wave ran a different
server mode from staging. Paths that exist only in that mode were never
tested. One of them is the per-agent directory operation lock, so
`--fail-recovery-step directory-lock` could never reach its step with
any workload
> - The re-wake workloads W2 and W2C also lost coverage: an agent that
reported phase 1 with disposition `done` closed the task, and the
harness never sent the re-wake (four of eight Claude cells on
2026-11-11)
> - This pull request adds `--ephemeral-server` and makes the W2/W2C
brief ask for a `yielded` phase-1 report
> - The benefit is that chaos waves can run in staging's server mode and
the re-wake cells test the re-wake on every provider

## Linked Issues or Issue Description

**What is the problem?**
The restart chaos harness cannot run the control plane in the
volume-free mode that Cloud and staging use. The `directory-lock`
recovery step (`agent_directory.operation_lock.before_acquire`) is
reached only for disposable remote copies, which need
`PAPERCLIP_EPHEMERAL_SERVER=true`. W2 and W2C cells also stop before the
re-wake when the agent reports phase 1 as `done`.

**What is the expected behavior?**
A wave can opt in to the volume-free mode on Daytona, and every restart
of the wave keeps that mode. The W2 and W2C cells reach the re-wake.

**Steps to reproduce**
Run `--fail-recovery-step
agent_directory.operation_lock.before_acquire:1` on Daytona with any
workload: the check `recovery_step_failed_once` reports "never reached".
Run W2 on Claude: the first run ends with the task `done` and
`rewake_sent` is "never sent".

## What Changed

- `assertIsolatedServerEnvironment` (`tests/runner-e2e/harness-env.ts`)
takes `expected.generatedSecretsMasterKey`. It admits
`PAPERCLIP_SECRETS_MASTER_KEY` only when that parameter is set and
equals the value exactly. `PAPERCLIP_SECRETS_MASTER_KEY_FILE` stays
refused. The check runs over the final server environment.
- `--k15-fresh-home` implies `--ephemeral-server` and defaults
`--storage` to `s3`. A fresh instance home without the volume-free mode
loses the agents' instruction bundles, which staging keeps in Postgres
and object storage.
- `--ephemeral-server` (`config.ts`, `types.ts`, `main.ts`,
`supervisor.ts`, new `ephemeral-server.ts` with its unit test
`ephemeral-server.test.ts`): it needs `--storage s3` and `--env daytona`
and refuses K14. Every server of the wave gets
`PAPERCLIP_EPHEMERAL_SERVER`, `PAPERCLIP_DURABLE_AGENT_FILES`,
`PAPERCLIP_SHARED_UI_ASSETS`, the wave's Postgres as
`PAPERCLIP_DATABASE_LISTEN_URL`, one stable
`PAPERCLIP_SECRETS_MASTER_KEY` (also written to the config key file) and
`RUN_LOG_S3_*` in the wave's object store.
- `rewake.ts`: the W2/W2C phase-1 brief asks for `paperclip_finish` with
disposition `yielded` and a `response_wake` continuation.
- W2/W2C tasks are created in `backlog` with their assignee, and a board
comment starts phase 1 (`startComment` in `workloads.ts`, used by
`observer.ts`). A passive board wait needs a comment-started run;
without it the yield queues an immediate continuation and phase 1 wakes
itself. The start comment is posted once (saved-comment check plus a
stable `clientRequestId`), and the brief keeps phase 2 out of blocking
`remainingWork`.
- Volume-free mode drops the repository workloads (B1, B5, F1, R1) from
the default list and refuses them when listed: their fixture is a
`local_path` project source, which a volume-free server refuses.
- `README.md`: a section for the new flag and a note on the brief.
- `shape-cells.test.ts`: option parsing and refusals for the new flag.

## Verification

- `pnpm exec vitest run --config tests/restart-chaos/vitest.config.ts
tests/restart-chaos/shape-cells.test.ts` passes (16 tests).
- `node scripts/typecheck-test-projects.mjs tests/restart-chaos` passes.
- Live proof wave (Daytona, Codex, W2, K1 and K15 with a fresh home,
`--storage s3 --ephemeral-server`): wave `w-20261111T205259-s6301` (2
tasks). The first server and both replacements (K15 with a fresh home,
then K1) started and reached ready in the volume-free mode. The server
process had `PAPERCLIP_EPHEMERAL_SERVER=true`,
`PAPERCLIP_DURABLE_AGENT_FILES=true` and `RUN_LOG_S3_BUCKET` set. Both
W2 tasks left phase 1 `in_progress` (yielded), received the re-wake and
ended `done`. The wave also found product faults (reported separately,
not fixed here): a re-wake after K1 failed with
`runner_harness_state_mismatch: backup_without_reusable_lease` and
needed Retry.
- `pnpm exec vitest run --config tests/runner-e2e/vitest.config.ts
tests/runner-e2e/support.test.ts` passes, including the new master-key
admission test (a matching wave key passes; an inherited key, a
mismatched key and `PAPERCLIP_SECRETS_MASTER_KEY_FILE` are refused).

## Risks

- Low risk. The flag is opt-in and the harness is test-only. The brief
change alters the W2/W2C prompt, so results from older W2/W2C seeds are
not directly comparable.

## Model Used

- 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-11 17:12:14 -06:00
..