Files
PaperClipAI/tests
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
..