Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ User-facing feedback shown while Flutter Pilot prepares the Target App Package f
_Avoid_: Step progress, Scenario progress, Flutter build progress

**Target Device**:
The device selected for a high-level Flutter Pilot test run. It may be selected explicitly by the user or automatically when Scenario Recording requires one recordable device. The Target App Package runs on this device, and any Scenario Recording for that run must record the same device.
The device selected for a high-level Flutter Pilot test run. It may be selected explicitly by the user or automatically when Scenario Recording requires one recordable device. The Target App Package runs on this Flutter Device. Scenario Recording for that run must use the paired Recording Device for the same physical or virtual device, matched by exact id or by unique exact name.
_Avoid_: Runtime Target, Recording Device

**Runtime Adapter**:
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ widgets to tap, where to type, what to wait for, when to scroll, and where to
capture diagnostic artifacts.

Scenario metadata can also request full-run device video recording with
`scenario.recording`. Recording is run-level context: it starts before the first
Step, stops during run shutdown, and is reported as a Device Video Recording
artifact rather than a Step artifact.
`scenario.recording`. Recording is run-level context: Flutter Pilot may prepare
device capture before app launch, starts the saved video segment before the
first Step, stops it during run shutdown, and reports it as a Device Video
Recording artifact rather than a Step artifact.

Runtime connection details are not stored in YAML. The same Scenario can be
validated, shared, committed, and replayed against different Runtime Targets by
Expand Down Expand Up @@ -236,9 +237,10 @@ vocabulary and selects the app entrypoint file; it does not accept a VM service
URI.

When `scenario.recording` is enabled, Flutter Pilot records the resolved Target
Device. The Target Device must also be available as a Recording Device with the
same device id. If `--device` is omitted, Flutter Pilot auto-selects only when
exactly one supported Flutter Device id is also recordable.
Device. The Target Device must also pair with a Recording Device by exact id or
by a unique exact name match. If `--device` is omitted, Flutter Pilot
auto-selects only when exactly one supported Flutter Device has a paired
Recording Device.

## Artifacts

Expand Down
11 changes: 6 additions & 5 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ Flutter Pilot 把一次 UI 旅程视为一个可移植的 Scenario。Scenario
诊断产物。

Scenario metadata 也可以通过 `scenario.recording` 请求整次运行的设备视频录制。
录制属于运行级上下文:它在第一个 Step 执行前启动,在运行收尾时停止,并作为
Device Video Recording 产物记录,而不是某个 Step 的产物。
录制属于运行级上下文:Flutter Pilot 可能会在应用启动前准备设备捕获,在第一个
Step 执行前启动最终保存的视频片段,在运行收尾时停止,并作为 Device Video
Recording 产物记录,而不是某个 Step 的产物。

Runtime Target 的连接信息不会写进 YAML。相同的 Scenario 可以被校验、分享、
提交到仓库,并通过 CLI 参数在不同的 Runtime Target 上运行。
Expand Down Expand Up @@ -225,9 +226,9 @@ Step Library 候选,不会被直接运行。
用于选择应用入口文件,不接受 VM service URI。

启用 `scenario.recording` 时,Flutter Pilot 会录制已解析的 Target Device。
这个 Target Device 必须同时是具有相同 device id 的 Recording Device。如果没有
传入 `--device`,只有在恰好一个受支持 Flutter Device id 同时可录制时才会自动
选择
这个 Target Device 必须能通过完全相同的 id,或唯一的完全相同名称,配对到一个
Recording Device。如果没有传入 `--device`,只有在恰好一个受支持 Flutter Device
能配对到 Recording Device 时才会自动选择

## 产物

Expand Down
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ include: package:lints/recommended.yaml
analyzer:
exclude:
- examples/smoke_app/**
- packages/pilot_runtime/test/**
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package rather than as part of the Flutter Pilot Runtime Adapter.
The package owns device-level recording concepts:

- a Recording Device selected through recording backend discovery
- an optional Prepared Capture that opens backend capture resources before a
saved segment starts
- a Recording Session started with `startRecord`
- explicit `stopRecord` and discard behavior
- a stop result that returns the final saved video path
Expand Down Expand Up @@ -36,8 +38,10 @@ by default unless overwrite is explicitly requested.

Physical iOS recording will use an in-package Swift helper based on the
CMIO/AVFoundation approach already validated in the local `ios_screen`
prototype. The `screen_recorder` package will not shell out to that prototype or
depend on files outside its own package.
prototype. The helper supports prepared capture so AVFoundation can be opened
before a saved `.mov` segment begins and then disposed explicitly after the
segment is finalized. The `screen_recorder` package will not shell out to that
prototype or depend on files outside its own package.

This keeps Flutter Pilot's Runtime Target model focused on Flutter app runtime
communication through `mcp_flutter`, while `screen_recorder` remains a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ Flutter app entrypoint file, while `--device` selects the Target Device and
`--flavor` selects the Flutter flavor.

Scenario Recording under `test` makes Target Device a first-class concept. When
recording is enabled, the selected Target Device must be both a supported
Flutter Device and a Recording Device with the same device id, and Flutter Pilot
uses that resolved id for both app launch and device recording. The trade-off is
that workflows which want to connect to an already-running app, such as an IDE
debug session or an externally supplied VM service URI, are out of the first
CLI contract and would require a future command if they become important again.
recording is enabled, the selected Target Device must be a supported Flutter
Device paired with a Recording Device by exact id or by a unique exact name
match. Flutter Pilot uses the Flutter Device id for app launch and the paired
Recording Device id for device recording. The trade-off is that workflows which
want to connect to an already-running app, such as an IDE debug session or an
externally supplied VM service URI, are out of the first CLI contract and would
require a future command if they become important again.
2 changes: 1 addition & 1 deletion docs-internal/flutter-pilot-prd.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ The result is a reproducible bug report package that can be consumed by humans,
- The `capture` action records diagnostic artifacts at a Step. `capture: {}` uses the default bundle: `screenshot: true`, `snapshot: true`, `widgetTree: false`, and `logs: true`. Each option can be explicitly overridden.
- Failed Steps automatically capture the same default bundle as `capture: {}`.
- Raw Widget Tree dumps may be available, but agent-facing output should default to compact summaries of visible text, interactive widgets, routes, logs, runtime failures, and likely suspects. The Diagnostic Reducer writes this summary as `diagnosticSummary` in the run report when `--print` captures raw Snapshot, Widget Tree, or error diagnostics.
- Scenario-level device video recording is supported as an optional run-level artifact. When recording is enabled, `test` requires the selected Target Device to also be available as a Recording Device with the same device id. The Device Video Recording is stored under the run directory as `artifacts/device-video-recording.<ext>` and recorded in reports with a run-directory-relative path. Richer recording parameters remain out of scope. Step screenshots and timeline reports remain the primary step-level visual artifacts.
- Scenario-level device video recording is supported as an optional run-level artifact. When recording is enabled, `test` requires the selected Target Device to pair with a Recording Device by exact id or by a unique exact name match. Flutter Pilot may prepare capture before app launch for backends that require it, but the saved Device Video Recording segment starts after Runtime Target initialization and before the first Step. The Device Video Recording is stored under the run directory as `artifacts/device-video-recording.<ext>` and recorded in reports with a run-directory-relative path. Richer recording parameters remain out of scope. Step screenshots and timeline reports remain the primary step-level visual artifacts.
- The implementation should be organized around deep modules:
- Scenario model and parser: validates YAML and produces a typed scenario.
- Finder and action model: represents user intent independently from `pilot_runtime` command details.
Expand Down
18 changes: 11 additions & 7 deletions docs-internal/scenario-recording-prd.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ Teams that already have the `screen_recorder` package need Flutter Pilot to
optionally create a Device Video Recording for the full Scenario Run without
turning recording into a Step or mixing it into Capture Action semantics.
Users need a strict Scenario DSL option that enables run-scoped recording,
starts before the first Step executes, stops after the run completes, and fails
clearly when recording was requested but cannot be started.
starts the saved video segment before the first Step executes, stops after the
run completes, and fails clearly when recording was requested but cannot be
started.

## Solution

Add a Scenario-level recording option under `scenario.recording`. The option is
part of Scenario metadata, not a Step Action. When enabled, Flutter Pilot
creates one Recording Session for the full Scenario Run: it starts recording
before Step execution begins and stops recording during run shutdown.
creates one Recording Session for the full Scenario Run: it may prepare device
capture before Target App launch, starts the saved segment before Step
execution begins, and stops recording during run shutdown.

The first slice supports only a strict recording toggle in the YAML Scenario
schema. The accepted forms are:
Expand All @@ -42,7 +44,7 @@ backend availability.

1. As a Flutter developer, I want a Scenario to request full-run device video recording, so that I can review the entire visual flow around a bug.
2. As a Flutter developer, I want recording to be configured in Scenario metadata, so that it is clearly separate from Step behavior.
3. As a Flutter developer, I want recording to start before the first Step, so that the video includes pre-interaction context.
3. As a Flutter developer, I want the saved recording segment to start before the first Step, so that the video includes pre-interaction context without Flutter build or launch time.
4. As a Flutter developer, I want recording to stop after the run finishes, so that the final artifact covers the complete Scenario Run.
5. As a Flutter developer, I want recording to remain optional, so that ordinary runs do not pay recording cost by default.
6. As a Flutter developer, I want `scenario.recording: {}` to enable default recording behavior, so that simple Scenarios stay compact.
Expand Down Expand Up @@ -86,15 +88,17 @@ backend availability.
- Unknown fields inside `scenario.recording` are validation errors.
- The parser continues to return typed domain objects on success and `ScenarioValidationException` on failure.
- The runner treats Scenario Recording as run lifecycle state, not step lifecycle state.
- The executor may prepare backend recording capture before Target App launch when a backend requires it. Physical iOS uses this to keep AVFoundation capture warm without starting the saved movie segment.
- When recording is enabled, the runner starts a Recording Session before executing any Scenario Step.
- When recording is enabled, the runner stops the Recording Session during run shutdown so the final Device Video Recording path is available.
- Prepared recording capture is disposed after Target App cleanup. Disposal is awaited and idempotent.
- If recording startup fails, the run fails before Step execution begins.
- Validation remains schema-only; host recording capability is checked only during `test`.
- Device Video Recording is stored as a run-level artifact rather than a Step artifact.
- The artifact store should expose Device Video Recording with stable run-level metadata so JSON and HTML reporting can discover it without scanning raw directories.
- Recording integration should depend on a narrow recording boundary rather than teaching the Runtime Adapter about device recording.
- The Runtime Adapter remains responsible for Flutter Runtime Target operations only: Finder resolution, Step actions, Screenshot, Snapshot, Widget Tree, and Logs.
- Build or adapt a small recording integration module that translates Scenario Recording intent into `screen_recorder` session lifecycle calls.
- Build or adapt a small recording integration module that translates Scenario Recording intent into `screen_recorder` prepared capture and Recording Session lifecycle calls.
- Keep recording session acquisition, stop, and failure normalization behind a fakeable interface so runner tests do not require real Android or iOS devices.
- Documentation and glossary language should use Scenario Recording, Recording Session, Recording Device, and Device Video Recording consistently.
- No ADR is required for the Scenario DSL addition by itself; the harder-to-reverse package-separation decision is already covered by the existing screen recorder ADR.
Expand All @@ -112,7 +116,7 @@ backend availability.
- CLI validation tests should verify that valid recording DSL passes `validate`.
- CLI validation tests should verify that invalid recording DSL reports structured field paths.
- Runner tests should use a fake recording boundary in the same spirit as existing fake Runtime Adapter tests.
- Runner tests should verify that recording starts before Step execution when enabled.
- Runner tests should verify that recording preparation can happen before launch and that the saved Recording Session starts before Step execution when enabled.
- Runner tests should verify that recording is not started when recording is omitted or explicitly disabled.
- Runner tests should verify that startup failure ends the run before any Step executes.
- Runner tests should verify that a successful run saves a run-level Device Video Recording artifact.
Expand Down
17 changes: 9 additions & 8 deletions docs-internal/scenario-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,17 @@ scenario:
recording: true
```

When recording is enabled, `flutter_pilot test` starts a Recording Session before
executing the first Step and stops it during run shutdown. If recording startup
fails, the run fails before any Step executes. The final Device Video Recording
is reported as a run-level artifact in `run_report.json`; it is not attached to
an individual Step.
When recording is enabled, `flutter_pilot test` may prepare device capture
before Target App launch, starts the saved Recording Session before executing
the first Step, and stops it during run shutdown. If recording preparation or
startup fails, the run fails before any Step executes. The final Device Video
Recording is reported as a run-level artifact in `run_report.json`; it is not
attached to an individual Step.

`test` records the same Target Device that runs the app. The selected Target
Device must also be available as a Recording Device with the same device id.
Without `--device`, Flutter Pilot auto-selects only when exactly one supported
Flutter Device id is also recordable.
Device must pair with a Recording Device by exact id or by a unique exact name
match. Without `--device`, Flutter Pilot auto-selects only when exactly one
supported Flutter Device has a paired Recording Device.

## Steps

Expand Down
11 changes: 7 additions & 4 deletions docs-internal/screen-recorder-prd.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ the final extension.
- The primary contract is a programmatic API, not a CLI-first command surface.
- Add a thin CLI for manual smoke testing and interactive foreground recording.
- The CLI must call the same core library API that programmatic callers use.
- Core API includes `listDevices`, `startRecord`, `stopRecord`, and discard behavior.
- Core API includes `listDevices`, `startRecord`, `stopRecord`, discard behavior, and an optional prepared capture lifecycle.
- Prepared capture API includes `prepare`, `startRecord(preparedCapture: ...)`, and `dispose(capture)`. Backends without a separate prepared mode keep direct recording behavior and do not start recording during preparation.
- `startRecord` returns a Recording Session.
- `stopRecord` accepts a Recording Session and returns a Recording Result.
- Discard behavior accepts a Recording Session and cleans up backend artifacts without returning a saved recording.
Expand Down Expand Up @@ -156,9 +157,11 @@ the final extension.
- iOS simulator discard stops the process and removes the local output file.
- Physical iOS recording uses an in-package Swift helper based on the native AVFoundation/CoreMediaIO capture approach validated in the local prototype.
- Physical iOS recording does not shell out to or depend on the local prototype directory.
- The Swift helper lists physical iOS capture devices and records one selected device to `.mov`.
- Physical iOS recording starts the helper as a long-running process and stops it by signaling the process so the helper can finalize the movie file.
- Physical iOS discard stops the helper and removes the local output file.
- The Swift helper lists physical iOS capture devices and can serve one selected device through a line-delimited JSON protocol.
- Physical iOS prepared recording starts the helper before a segment is requested, waits until AVFoundation has produced a real frame, then starts the `.mov` writer only when `startRecord(preparedCapture: ...)` is called.
- Physical iOS stop finalizes the active `.mov` segment while keeping the AVFoundation capture session alive for a later segment.
- Physical iOS dispose sends helper shutdown, waits for process exit, and stops native capture so host/device recording indicators do not remain active.
- Physical iOS discard finalizes or stops the active segment as needed and removes the local output file.
- Support simultaneous active recordings on different Recording Devices.
- Reject starting a second active Recording Session for the same Recording Device.
- Build deep modules for device resolution, output naming, backend lifecycle, process execution, and CLI interaction.
Expand Down
Loading
Loading