Files
PaperClipAI/tests
fb96537e28 test(ui): verify disconnect recovery through browser outages (#18832)
## Thinking Path

> - Paperclip lets people manage agent work through the board.
> - Deploys can interrupt reads and writes while people use the board.
> - Component tests cannot prove the browser keeps task content and
saved drafts through a reload.
> - The read and cache changes need a regression suite against the built
app.
> - This pull request drives those journeys through temporary API
failures.
> - CI discovers the new suite through the existing e2e shard plan.

## Linked Issues or Issue Description

**What happened?**
Outage recovery lacked one browser suite covering retained content,
write recovery, cached reloads, access errors and sign-out clearing
together.

**Expected behavior**
Keep loaded task content visible through a 20-second API outage. Show
one connection banner and its recovery state. Save comments once and
retain document edits. Restore approved reads after a reload. Keep real
error responses readable and clear query records on sign-out.

**Steps to reproduce**
Open a task or settings. Return 503 with `tenant_app_unavailable` from
browser API requests for 20 seconds. Type a comment, edit a document, or
reload. Restore the API and compare the visible result with the saved
server state. Repeat with real 403/404 statuses and sign-out.

Stacked on Refs #18825, which depends on Refs #18822. Related
durable-write foundation: Refs #17960.

## What Changed

- Add `disconnect-resilience.spec.ts` with ten browser cases for
comments, a queued comment across reload, document autosave, cached
settings/sidebar/task reads, legacy Inbox reloads, 403 and 404
responses, sign-out clearing, restored-draft conflict detection, and
first-socket outage control.
- Assert one connection banner, readable recovery, no transient error
boxes or raw codes, retained task text, one saved comment, and the saved
document after reload.
- Use the real local server and isolated embedded PostgreSQL. Intercept
browser API traffic for outages. Control the logout/session response for
the sign-out test. Create no agents or model runs.
- Register realtime interception before navigation. Track both ends of
current sockets, close them at outage start, and keep reconnects
unavailable through the HTTP outage deadline. Preserve normal close
forwarding and close tracked pairs during teardown. The regression
captures the first browser socket without waiting for history or open,
then checks that the outage closes it.
- Prepare complete server-derived experimental settings and workspace
preferences before the legacy Inbox navigation. Its route callbacks
serve per-test snapshots across reloads, avoiding reads from disposed
route.fetch responses.
- Document the direct test command. The existing CI e2e shards already
discover this file exactly once; no workflow or package script is added.

## Verification

- Current head `228c1b68d30` is merge-ready: all 54 check runs completed
(52 successful, one skipped, one neutral), the legacy Snyk status is
successful, and both required gates pass. The single failed-jobs debug
rerun in run `41752978283` passed on attempt 2, including Runner package
job `126328280650` and `verify` job `126332119116`. Greptile Apex
reviewed this exact head at 5/5 with zero unresolved threads; the branch
has no merge conflicts. The three-PR stack is awaiting operator merge
approval.
- Original attempt 1 of current-head CI run `41752978283` had 46
successful jobs, one skipped and two failed: Runner package tests and
the downstream `verify` gate. GitHub reports lost communication with the
Runner host; the test step was cancelled, its log returns HTTP 404, and
no Runner diagnostic artifact is available. The underlying test outcome
and disconnection cause are unknown. One failed-jobs retry with debug
logging was accepted after verifying the unchanged current head and
passed on attempt 2. No source change was made; earlier passing CI and
local tests do not certify this incomplete Runner result. Current-head
CI now passes; the earlier disconnection cause remains unknown.
- Preceding head `6531caccf62` reached merge-ready: all 54 check runs
completed (52 successful, one skipped, one neutral), the legacy Snyk
status was successful, and both required gates passed in run
`41749512329`. Greptile reviewed that exact head at 5/5 with zero
unresolved threads. Current head `228c1b68d30` carries later
account-preference and bulk-selection fixes and now has its own passing
current-head CI.
- All 23 built-UI outage/write/loading cases pass in 4.5 minutes on
exact current head `228c1b68d30`: ten outage, six durable-write and
seven loading cases. The run used bundled Chromium, a fresh
local-trusted server and isolated embedded PostgreSQL on macOS
arm64/Node 25.6.1. Owned temporary server and database stopped.
- Current integrated head `228c1b68d30` contains cache revision
`fe4f682c879` and read head `09d1db29dea`. The exact application source
passes all 1,198 focused tests across twenty-eight files, UI typecheck
and both guards. Seventeen new cases cover restored-account settings,
owned crown cleanup and pending bulk selections; sixteen fail the
previous source and one preserves denial compatibility. All three
browser specs pass standalone strict checking. All 23 current-head
browser cases pass in 4.5 minutes.
- Application revision `9c1a10f25d9` passed all 1,137 focused tests
across twenty-one files, UI typecheck and both guards. Exact preceding
application/spec head `4fec693ec94` passed all 23 built-UI
outage/write/loading cases in 4.6 minutes and standalone strict checking
of all three specs. It used bundled Chromium, fresh isolated PostgreSQL
and local-trusted auth on macOS arm64/Node 25.6.1. Owned test processes
stopped.
- Preceding integrated head `870aa709657`, containing cache
`cbb891dd37d`, passes all 23 built-UI outage/write/loading cases in 4.6
minutes: ten outage cases, six durable-write cases and seven loading
cases. It used bundled Chromium, the built UI, a fresh local-trusted
server and isolated embedded PostgreSQL on macOS arm64/Node 25.6.1.
Owned test processes stopped.
- The earlier head `763fe431b74` passes the affected legacy Inbox
outage/reload case (34.3 seconds; 50.8 seconds including startup) and
strict three-spec checking after the response-snapshot fix. The
preceding head `973a12d77f4` passed all 23 built-UI outage/write/loading
cases in 4.6 minutes: ten outage cases, six durable-write cases and
seven loading cases. Its first-socket regression fails the previous
helper because that socket stays open. The run used bundled Chromium,
the built UI, fresh isolated PostgreSQL and local-trusted auth on macOS
arm64/Node 25.6.1. That earlier isolated callback revision was verified
with its affected case; the later application/spec head `4fec693ec94`
also passes the full suite. Owned test servers and databases stopped.
- The current base gives known skills/app errors priority over sibling
loading. All 60 affected tests and both application UI typechecks
passed. Its twelve new regressions failed the preceding source. All 47
recovery-worker tests and seven related Runner fixture variants also
passed during the historical CI audit; those focused checks do not claim
a full current server/Runner suite.
- All 22 outage/write/loading cases passed in 4.7 minutes on preceding
integrated head `b7deaaee5da`, including direct cache revision
`97c0bc3966f`. The run used the built UI, bundled Chromium and a fresh
local-trusted server with isolated embedded PostgreSQL on macOS
arm64/Node 25.6.1. It covered all nine outage, six durable-write and
seven loading cases. The owned temporary server and database stopped.
- All 1,038 focused tests passed on that direct cache revision, with UI
typecheck and guards. Six regressions failed the previous source: online
retries could trigger a hidden-tab worker reload, and sign-out failed
without crypto.randomUUID. Both modes and stamp states now pass.
Standalone strict checking passes for all three browser specs.
- The restored cached-A/draft-B/server-C test asserts zero replay
PATCHes and retains the conflict. The queued-comment case holds fresh
session verification after general API recovery and asserts zero POSTs
until release. Denial, logout and cached-navigation cases require saved
records. Sign-out seeds several company records to exercise native
Storage key reordering. Healthy navigation waits for
conversation-history readiness.
- Earlier runs exposed real cached-header, storage cleanup and replay
defects in the base. Those failures and corrected fixture assumptions
remain in the discussion. A prior run passed 21/22 while real sockets
remained available during simulated HTTP failures. A diagnostic trace
established the contradiction. The first repair gated new sockets, but
review identified the first pre-existing socket still escaping. This
revision intercepts before navigation and closes existing pairs too. The
new regression fails the preceding helper, and all 23 current cases pass
without weaker assertions. Shared-memory exhaustion prevented two
earlier diagnostic startups; only unused segments from completed owned
test databases were removed.
- All six separate cross-organization link/upload variants passed on an
earlier integrated base. Standalone strict checking of that unrelated
spec reports five existing errors in its shared fixture; this PR does
not claim that check passes.
- CI on older head `53d979e384c` failed the legacy Inbox case with
`apiResponse.json: Response has been disposed` inside a route.fetch
callback. Its other 25 cases passed and one skipped. The seven other
browser shards succeeded; the aggregate only reports that child failure.
The new snapshot callbacks remove those fetched-response lifetimes.
Original CI evidence remains recorded in the discussion.
- Greptile Apex reviewed exact current head `228c1b68d30` at 5/5 with no
actionable findings and zero unresolved threads (summary updated
2026-11-04 at 01:26:14 UTC). The branch has no merge conflicts.
Current-head CI now passes; the earlier disconnection cause remains
unknown. Controlled local outages do not prove hosted authentication or
a real Cloud restart/deploy.

Commands run:

```sh
pnpm exec playwright test --config tests/e2e/playwright.config.ts tests/e2e/disconnect-resilience.spec.ts --grep 'a legacy Inbox reload retains' --reporter=list
pnpm exec playwright test --config tests/e2e/playwright.config.ts tests/e2e/disconnect-resilience.spec.ts tests/e2e/disconnect-write-recovery.spec.ts tests/e2e/task-loading-frame.spec.ts --reporter=list
pnpm exec tsc --ignoreConfig --noEmit --strict --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck tests/e2e/disconnect-resilience.spec.ts tests/e2e/disconnect-write-recovery.spec.ts tests/e2e/task-loading-frame.spec.ts
```

## Risks

The suite adds about three minutes to one e2e shard and depends on
current accessible UI controls. It uses controlled outages and logout
responses. A passing local run must not be treated as real deployment
acceptance. There are no production behavior, schema, dependency, or API
changes in this PR.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning effort, tool
use, and code execution. The context window size is not exposed.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for related PRs and linked them above
- [x] I have described the issue following the bug report template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] All 23 built-UI cases pass on current head `228c1b68d30`
- [x] All three browser specs pass standalone strict typechecking on the
current head
- [x] The current application source passes all 1,198 focused tests, UI
typecheck and both guards
- [x] I have added tests and updated relevant documentation
- [x] I have considered and documented risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Bender (Fable) <bender@agents.paperclip.ing>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 16:11:02 -08:00
..