Skip to content

docs: run recording PRD (design only, no behaviour change) - #469

Merged
pbertsch merged 2 commits into
mainfrom
chore/run-recording-prd
Oct 17, 2026
Merged

pbertsch merged 2 commits into
mainfrom
chore/run-recording-prd

Conversation

@pbertsch

Copy link
Copy Markdown
Member

Summary

  • Adds docs/prd/run-recording.md, the design for recording a test run step by step: the HTTP traffic each step caused, screenshots and widget trees, and the element each step acted on.
  • Also covers a self-contained viewer, a replayable test, native capture through a device proxy with a per-run CA, and credential redaction.
  • Why: when a test fails, a developer re-runs it and guesses which backend response the app received. FlutterProbe already records most of the inputs, but nothing joins them into one shareable record.
  • Adds a CHANGELOG entry under Docs.

No code or behaviour change. The design is for review before implementation starts.

Test plan

  • Relative links point at files that exist on main (docs/prd/ai-visual-assertions-prd.md, docs/roadmap/gap-analysis-2026-08.md)
  • Markdown renders correctly on GitHub
  • Review of the privacy defaults (section 7) and the PR split (section 10)
  • CI passes, including the disclosure guard

🤖 Generated with Claude Code

Design for recording each test run step by step: the HTTP traffic each step caused, screenshots and widget trees, the target element, a self-contained viewer, a replayable test, native capture through a device proxy with a per-run CA, and credential redaction. Opt-in by design; no product behaviour changes in this PR.

Claude-Session: https://claude.ai/code/session_01QGnLBdCp6x94qKGY5kAxHK
@pbertsch
pbertsch requested a review from a team as a code owner October 16, 2026 17:52
The agent returns only finished HTTP exchanges. Advancing the cursor to the highest seq returned could skip a request that finishes later, so the PRD now says the cursor stops at the first unfinished seq.

Claude-Session: https://claude.ai/code/session_01QGnLBdCp6x94qKGY5kAxHK
@pbertsch
pbertsch merged commit bc6c4b3 into main Oct 17, 2026
17 of 18 checks passed
@pbertsch
pbertsch deleted the chore/run-recording-prd branch October 17, 2026 04:59
pbertsch added a commit that referenced this pull request Oct 17, 2026
… test

## Summary

- Adds `probe test --record` and `--record-dir`. Each test attempt gets a bundle under `<reports_folder>/recordings/<run>/<device>/`: its steps with source file and line, screenshots before and after each step, a widget tree after each step, the app's `dart:io` HTTP exchanges with credentials redacted, and an offline HTML viewer.
- Adds a blocking per-step recorder hook to the runner, separate from `OnStep`. It is nil by default, and with no recorder configured the runner's behaviour is unchanged.
- Adds `internal/record.Recorder`, which writes one bundle per test attempt. Exchange files are numbered per bundle, so an app restart cannot overwrite an earlier exchange.
- Recording is an observer. Capture failures become warnings and never change a result or the exit code. Nothing is uploaded.
- Docs: the CLI reference, the Probe Cloud preview note, the README, the reports page, the landing feature card, the MCP `run_tests` flags, and the CHANGELOG.

Builds on #469 (design) and #470 (bundle writer, HTTP cursor, redaction, viewer, step start times). Both are merged.

## Not recorded yet (stated in the docs)

- Native SDK and WebView traffic. Only the app's `dart:io` HTTP is captured.
- The element each step acted on.
- Screenshot redaction rules. Screenshots are not redacted.
- Widget trees are captured after steps, not before them.
- The manifest's `platform` and `os_version` fields are empty. The CLI does not pass them yet.

## Review notes

- The recorder numbers exchange files per bundle. Using the agent's sequence number would overwrite files after an app restart. A regression test covers this.
- Composite runs: the composite runner is rebuilt when recording is on, with the same timeout and verbosity as `buildCompositeRunner`, plus the recorder factory. `buildCompositeRunner` registers no recipes, so nothing else is lost.
- Local runs do not set a device name in the run metadata, so the recording directory falls back to the `--device` serial.
- `internal/cli/test.go` was run through gofmt, so some untouched alignment lines changed too. Those hunks are whitespace only.
- `probe record` (the interaction recorder) is a different command from `probe test --record`. The docs name both.

## Test plan

- [x] `go test ./...` passes on the root module
- [x] `go build ./...` passes
- [x] `gofmt -l` is clean for the changed files, and `go vet` is clean for `internal/cli`, `internal/mcp`, `internal/record` and `internal/runner`
- [x] New tests: bundle writing, redaction, retries and name collisions, device errors, the app-restart regression, runner hook ordering and error isolation, and the CLI event conversion and device slug
- [x] `probe test --record` run on an iOS simulator and an Android emulator with the project's end-to-end fixture app (5 tests on each). The fixture makes no HTTP calls, so no `http/` folder is written
- [ ] Open a bundle in a browser at phone width and in dark mode. Not done yet
- [x] CI passes, including the disclosure guard
- [ ] Review

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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