Skip to content

🤖 perf: replay synthetic session tapes through the desktop app with egress blocked (T3) - #5612

Merged
ThomasK33 merged 18 commits into
mainfrom
perf/tapes-3-replay-e2e
Oct 4, 2026
Merged

ThomasK33 merged 18 commits into
mainfrom
perf/tapes-3-replay-e2e

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds perf.tapeReplay. It is an opt-in harness mode (XUM_REPLAY_TAPES) in which the desktop app serves a session tape as a workspace's workspace.onChat stream. The replay runs through the real backend subscription, MessagePort oRPC, WorkspaceStore and React. A Playwright perf scenario replays a committed synthetic tape, checks the rendered transcript, and writes timings like the other perf specs. make perf-tape-replay runs it.

Background

T1 (#5529) records tapes. T2 (#5568) added the offline loader and replay driver. T2's app integration was removed because the real renderer fetches remote URLs found in recorded content (markdown images). This PR adds app playback together with network isolation. It also picks up the read-side items from #5587 that matter now that the app reads tapes.

Implementation

  • Activation. XUM_REPLAY_TAPES='{"<workspaceId>":"<absolute .jsonl>"}'. Unset or blank: no work beyond one env lookup. Set (even unparseable): the whole process is in replay mode. Tapes are served only inside the perf harness, which also sets XUM_E2E=1 and XUM_REPLAY_HARNESS=1. Without those markers every mapped workspace shows the refusal row and nothing is replayed. Tape paths must be absolute local paths (allowlist: POSIX /... or a Windows drive path). UNC shares, \\?\ and \\.\ prefixes, URLs and relative paths are refused before any read.
  • Guarantee. Replay mode keeps providers, recorded tools and recorded URLs offline. The app's other background network (git remote queries, gh, Coder CLI probes) is not tied to tape content. The harness isolates it (see Scenario below).
  • Read-only, process-wide. In replay mode, WorkspaceService refuses send, resume, truncate/clear, reset, replace (Start Here) and ask-user answers. The refusal is a non-retryable session_tape_replay send error that names XUM_REPLAY_TAPES. A task admission token passed with a send is disposed. Provider model creation refuses at its three chokepoints (ProviderModelFactory.createModelEffect, createEvaluationModelEffect, evaluationModelFactory.createEvaluationModel), so background callers (status, title, compaction, 🤖 fix: XUM_MOCK_AI still sends background claude-haiku requests #5604) cannot reach a provider. Telemetry is disabled. Other writes, such as plan-review snapshots, are documented as unguarded: replay maps scratch workspaces only.
  • onChat replay source (sessionTapeReplaySource.ts). subscribeWorkspaceChat branches before any session access for a mapped workspace. It serves fresh full subscriptions only, and refuses since and live ("reload to replay"). It accepts closed and stopped tapes and refuses rejected and truncated ones. It checks the header workspaceIdHash and requires exactly one successful caught-up. Events play at recorded offsets. The only change to an event: caught-up.hasOlderHistory is set to false, so the client never pages in live history. The stream then stays open with transport heartbeats. Refusals are typed (ORPCError + SESSION_TAPE_REPLAY_REFUSAL_DATA). WorkspaceStore shows them as a non-retryable "Session tape replay refused" row.
  • Desktop only, egress blocked.
    • At app ready, desktop main installs webRequest.onBeforeRequest on the default session. Local file: URLs (no host, no UNC path), data:, blob: and devtools: pass. In dev-server mode, the exact app-page and terminal-page dev origins also pass. Everything else is cancelled, loopback included.
    • The installer sets the latch that lets the backend serve tapes.
    • Chromium gets --host-resolver-rules="MAP * ~NOTFOUND, EXCLUDE localhost[, EXCLUDE <dev host>]", because browser-internal fetches such as the spellcheck dictionary download bypass webRequest.
    • External-open paths refuse.
    • Replay mode runs no API server (ServerService.startServer refuses), so browser and CLI clients cannot render tapes outside the block.
  • Renderer side effects off. Preload exposes isSessionTapeReplay. WorkspaceStore then applies tape events without side effects (skill refresh, gateway dialog, toasts) and skips the file-modifying-tool refresh.
  • 🤖 perf: session tape read side follow-ups for T3 (from #5568) #5587 fixes.
    • The reader checks size with stat first: 32 MiB recorder cap, regular files only.
    • It decodes UTF-8 in fatal mode.
    • Deep-JSON RangeError on any line becomes a rejection.
    • The recorder hashes the trimmed workspace id.
    • Replay waits are chunked below the timer limit.
  • Fixture and scenario.
    • tests/e2e/fixtures/sessionTapes/perf-tape-replay.jsonl is synthetic, generated with the T2 builder by scripts/perf/generateTapeReplayFixture.ts. It contains probe image URLs (a .invalid host and loopback 127.0.0.1:47999) and a tool call with a non-builtin marker command.
    • The spec strips credential env vars, shadows coder and gh with failing logged stubs, and wraps git with GIT_ALLOW_PROTOCOL=file.

Validation

  • make perf-tape-replay passes locally and remotely. perf-summary.json → tapeReplay: 10 events, recorded duration 361 ms, first row ~0.8 s, last row ~1.3 s, 2 blocked probe requests (net::ERR_BLOCKED_BY_CLIENT). The send attempt shows the read-only refusal.
  • Remote dogfood UAT via Coder Agents passed on e8289e2 (round 2). strace -f covered connect, sendto, sendmsg, execve and socket, with a capture server on 127.0.0.1:47999.
    • The capture server saw 0 connections, also with the demo repo's origin pointed at it.
    • There were 0 non-loopback TCP connects, 0 non-loopback sends and 0 DNS lookups.
    • The only non-loopback event is Chromium's IPv6 reachability probe: a UDP connect that failed with ENETUNREACH and sent no data.
    • No real gh or coder ran, and the recorded tool command never ran.
    • Invalid tapes (wrong hash, truncated, corrupted line, missing or failed caught-up) show the refusal row. A stopped tape plays.
    • Round 1 found git-remote and gh egress. The harness isolation above fixed it.

Risks

Low for normal use. Every new branch is gated on XUM_REPLAY_TAPES, and onChat, send, model creation, telemetry and the API server behave as before when it is unset.

Deferred (tracked in #5587)

Synchronous tape load on the main process. fast pacing. Replaying real local tapes through make. Composer side effects of replayed restore-to-input / auto-compaction-triggered events. Background network isolation outside the harness.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $29.69

…only replay mode

XUM_REPLAY_TAPES maps workspace ids to tapes; onChat for a mapped workspace is
served from the tape (desktop only, after the renderer egress block), and the
whole process refuses sends, history changes and provider model creation.
Includes the #5587 read-side fixes and the Start Here refusal dialog.

Signed-off-by: Thomas Kosiewski <tk@coder.com>
…re and make perf-tape-replay

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
…mode

Signed-off-by: Thomas Kosiewski <tk@coder.com>
…renderer replay paths

Signed-off-by: Thomas Kosiewski <tk@coder.com>
…import path

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
…Coder CLI probe in perf.tapeReplay

strace of the scenario showed Chromium's spellcheck dictionary download (browser-internal,
outside webRequest) and the backend's coder whoami probe reaching the network.
The refused-Start-Here test added clickStartHere/findEnabledOkButton but left
the original test with an inline copy of the same lookups. Use the helpers in
both tests; behavior is unchanged.

Signed-off-by: Thomas Kosiewski <tk@coder.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T14:57:37.377714Z 62c186e Manual request
🔒 Security Review ✅ Completed 2026-10-04T14:59:30.091905Z 62c186e Manual request

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4de6de0566

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/utils/messages/applyWorkspaceChatEventToAggregator.ts
Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts
Comment thread src/desktop/main.ts Outdated
Comment thread src/node/services/providerModelFactory.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 4de6de0566

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 51e70a96d2

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

…r and git remotes in perf.tapeReplay

Codex security round 1: browser/CLI clients of the API server would render tapes outside the
desktop egress block. UAT round 1: the app's background git remote queries and gh calls reached
the network; the scenario now shadows coder/gh with failing logged stubs and wraps git with
GIT_ALLOW_PROTOCOL=file.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51e70a96d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/desktop/main.ts
Comment thread tests/e2e/scenarios/perf.tapeReplay.spec.ts Outdated
Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9fc75d848

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts
Comment thread src/desktop/main.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: c9fc75d848

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0f38ebc7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts Outdated
Comment thread src/desktop/sessionTapeReplayEgress.ts Outdated
Comment thread src/desktop/main.ts Outdated
…only file URLs, documented read-only funnels)
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: ad52106e6a

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad52106e6a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts
Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8289e2817

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.test.ts Outdated
Comment thread src/node/services/sessionTapes/sessionTapeReplaySource.ts Outdated
Comment thread scripts/perf/tapeReplayFixture.test.ts Outdated
Comment thread src/node/services/sessionTapes/sessionTapeReplay.test.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: e8289e2817

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

Stopping the review loop: the 6-round Codex cap for this PR is used up. This PR is not ready.

  • Head: e8289e2817f87d46eb7ef61326f0443a522654a1. All CI jobs pass except Codex Comments (and therefore Required), which fails because of the 4 open round-6 threads.
  • Remote dogfood UAT round 2 passed on this exact head.
  • Open round-6 findings, each with a small, known fix:
    1. P1 (AGENTS static imports): the egress-latch test's bun -e child script uses await import(). Fix: static import lines in the script string.
    2. P2: reject Windows UNC tape paths (\\\\server\\share, //server/share) in XUM_REPLAY_TAPES before stat/readFile. Fix: two lines in parseReplayTapeMap.
    3. P1 (no tautological tests): delete the committed-fixture vs generator equality test. The validity test stays.
    4. P1 (no duplicated constants): export the timer-limit constant from sessionTapeReplay.ts and import it in the test.

The next step needs a decision from the owner: allow one more Codex round (fixes, validation, remote UAT on the new head), or accept the findings as follow-ups.

…rts in the child test, shared timer limit, drop fixture copy test)
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 62c186ebe1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 62c186ebe1

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

Final state of the round-7 exception round. Head: 62c186ebe1a5b7bd9dfb681aa75e6c16c8a1bc4e.

  • Codex round 7 gave a 👍 on this head (code and security reviews both completed), with no new findings. The review loop closed after 7 rounds; round 7 was the one exception the user granted.
  • Required passes on this head (run https://github.com/coder/xum/actions/runs/37210867039). No review threads are open.
  • Remote dogfood UAT round 3 passed on this exact head:
    • Harness scenario: the capture server recorded 0 connections, also with a git origin pointing at it. There were 0 non-loopback TCP connections, sends or DNS lookups. The only exception is Chromium's IPv6 probe, which fails and sends no data.
    • A launch without the harness markers refuses replay and replays nothing.
    • UNC paths and a relative path are refused before any read.
  • Low-severity UAT notes are tracked in 🤖 perf: session tape read side follow-ups for T3 (from #5568) #5587 (comment).

This PR is ready for the conductor. I did not merge or enqueue it.

@ThomasK33

Copy link
Copy Markdown
Member Author

Readiness record: merging at 62c186ebe1.

  • Review: 7 Codex rounds. Round 7 was the maintainer's one exception round. Codex gave a clean verdict on this exact head and then a 👍. 0 open threads. Required passes on this head.
  • Supported scope: replay runs only inside the isolated E2E harness (make perf-tape-replay, which needs XUM_E2E=1 and XUM_REPLAY_HARNESS=1). Without the markers the app shows a refusal row and replays nothing. The harness, not the app, isolates background network traffic (git remotes, gh, Coder CLI). This PR does not claim app-wide network isolation.
  • Tape paths: a syntax allowlist accepts only absolute local paths. It refuses network shares, device prefixes, URLs and relative paths before any read. It is not filesystem confinement: .. segments and symlinks are accepted (tracked in 🤖 perf: session tape read side follow-ups for T3 (from #5568) #5587).
  • Validation: make static-check, 712 bun tests, the Start Here jest suite and make perf-tape-replay pass.
  • Remote UAT round 3 passed on this exact head. In the harness run the capture server saw 0 connections, and strace showed no non-loopback TCP connects, sends or DNS lookups. The only non-loopback event was Chromium's IPv6 reachability probe, a UDP connect that failed and sent no data. A launch without the markers refused and replayed nothing. Network-share and relative paths were refused before any stat or open.
  • Follow-ups are tracked in 🤖 perf: session tape read side follow-ups for T3 (from #5568) #5587. The refusal text's pointer to the make target is corrected in the docs addendum.

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 4, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 4, 2026
@ThomasK33

Copy link
Copy Markdown
Member Author

Re-enqueueing once. The merge queue removed this PR because Test / Unit (2/6) failed in BrowserTab.test.tsx, a file this PR does not touch. The failure is a race in that test: it waits for the mock call, not the render. Tracked in #5624. The test passed on the same merge-group commit locally: 6/6 alone, 3/3 paired with this PR's WorkspaceStore.test.ts, and in a full shard-2 run.

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit 68bac4d Oct 4, 2026
42 of 43 checks passed
@ThomasK33
ThomasK33 deleted the perf/tapes-3-replay-e2e branch October 4, 2026 16:04
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Oct 4, 2026
…filing Xum page (coder#5625)

## Summary

Documents two merged perf features on the Profiling Xum page
(`docs/reference/profiling.mdx`), and fixes one wrong runtime message.

1. **Report slowness** (coder#5558): a new `## Report slowness` section.
- How to run it: the palette command, a link to its shortcut on the
keyboard shortcuts page, and `xum api perf-reports create`.
   - Where the report goes: `~/.xum/perf/reports/<id>/`.
- A table of every file in the report: `snapshot.json`, `trace.json`,
`environment.json`, `README.txt`, `captures/` with `manifest.json`,
`hangs.json` and `app-metrics.json`. The last two are desktop only.
- What it never contains: tapes, chat content, prompts, tool payloads or
environment variables.
- A warning that path redaction is partial, not anonymization: copied
CPU profiles keep the folder names below `~` (coder#5561).
- The "Report a performance problem" checklist now starts with this
report.
- `docs/config/keybinds.mdx` keeps the shortcut and links here, so each
fact has one home.
2. **Tape replay** (coder#5612): a new "Replay a synthetic tape
(contributors)" subsection.
   - What `make perf-tape-replay` runs and where its output goes.
- It replays only synthetic fixtures. A warning says never to replay or
commit real tapes.
- An accordion explains how replay stays offline. Replay runs only when
`XUM_E2E=1` and `XUM_REPLAY_HARNESS=1` are set, and the test harness
sets them, not the Makefile. The app blocks renderer requests, while the
harness takes background network offline. Tape paths are checked for
absolute local syntax only: `..` and symlinks are accepted.
3. **Refusal message** (`sessionTapeReplaySource.ts`): it now says "Run
make perf-tape-replay to use the isolated replay harness." The old text
claimed the make target sets the markers. The existing test matches only
`/only inside the perf harness/`, which is unchanged, so this PR adds no
exact-copy test.

## Validation

- I ran the documented commands against a sandbox `xum server` with a
temporary `XUM_ROOT`:
- `perf-reports create` with the experiment off fails with
`PRECONDITION_FAILED` and the documented message.
- With the experiment on, it writes the documented layout: `README.txt`,
`captures/` with `manifest.json`, `environment.json`, `snapshot.json`
and `trace.json`. Folders are 0700 and files 0600.
- The `environment.json` keys match the page, and the home path appears
nowhere in the bundle.
- Two concurrent runs get `CONFLICT` with "a slowness report is already
being written".
- I rendered the page locally with the CI-pinned Mintlify and checked
the new sections at desktop and 390 px widths. Both accordions expand.
- `make static-check-full` passes, including `mintlify broken-links`.
`sessionTapeReplaySource.test.ts` passes (25 tests).

![Report slowness privacy warning and checklist,
desktop](https://github.com/user-attachments/assets/3ddd8877-1fd3-47a5-b04a-cc6701988c82)

![Report contents table at 390
px](https://github.com/user-attachments/assets/85b8e4da-723a-414b-afc9-5d7594074933)

![Tape replay subsection with the offline accordion expanded,
desktop](https://github.com/user-attachments/assets/6e571060-1c8e-4a6d-a3cb-98fe2f794a97)

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$30.02`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=30.02 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant