Part of #330.
A Python trace mode run writes one archive, always, whatever the outcome.
traceGranularity, tracePolicy, per-test screenshot/video and Allure
attachment all have no Python equivalent, and the first of those is what the
other three depend on.
That is a real gap rather than a structural impossibility: the backend already
holds every input it would need.
What already exists
| Need |
Where it is |
| The retention decision |
core/trace-retention.ts shouldRetainTrace(policy, {outcomes, attemptInfoAvailable}) — imports only @wdio/devtools-shared, no driver, no framework |
| Per-test outcome |
backend/src/baseline/types.ts TimeWindowNode.state |
| Per-test window |
the same node's start / end |
| The streams to slice |
ActiveRun.commands, consoleLogs, networkRequests, mutations, actionSnapshots, screencastFrames — all timestamped |
The pytest plugin already feeds those nodes; Preserve & Rerun needed them. No
new capture is required.
What is missing
- Move
trace-retention.ts from core to trace. A pure file move — it
already satisfies the trace rule (shared and nothing else). Today
backend has zero dependency on core by design (§2.2), so this is what
makes the policy reachable at all. Worth doing on its own merits: retention
living in core is a layering smell now that a non-core consumer wants it.
traceGranularity and tracePolicy on TraceExportRequest
(shared/src/trace-export.ts), so the adapter can state what it wants.
- Slice-by-window in the backend. The real work.
core/spec-trace-helpers.ts
cannot move — it pulls in node:path, ./uid.js, ./artifact-naming.js and
is built around a TraceCapturer the backend does not have. Mechanically this
is "filter six arrays by [start, end] per test node"; the risk is in the
edges — a command straddling a boundary, a mutation anchored before its test
began, screencast frames shared across neighbouring tests.
Known limitation from day one
retain-on-first-failure needs per-attempt outcomes. pytest reruns
(pytest-rerunfailures) are not tracked by the plugin's registry, so
attemptInfoAvailable would be false and shouldRetainTrace would degrade to
retain-on-failure — which it already handles explicitly (degradedToFailure),
the same way Nightwatch's BDD interface does. Graceful, but the support would
carry an asterisk unless attempt tracking is added too.
Acceptance criteria
A Python run with traceGranularity: 'test' writes one archive per test, and
tracePolicy: 'retain-on-failure' keeps only the failing ones. The retention
decision is made by the same shouldRetainTrace the JS adapters use, not a
second implementation. retain-on-first-failure degrades to retain-on-failure
with the existing warning until attempt tracking exists.
Sequencing
After #294. Publishing without tracePolicy is honest as long as #358 says
so, and adding it later is additive. Doing it first delays a release already
gated on three other decisions.
Size: M (step 1 is S; step 3 carries the risk).
Part of #330.
A Python trace mode run writes one archive, always, whatever the outcome.
traceGranularity,tracePolicy, per-test screenshot/video and Allureattachment all have no Python equivalent, and the first of those is what the
other three depend on.
That is a real gap rather than a structural impossibility: the backend already
holds every input it would need.
What already exists
core/trace-retention.tsshouldRetainTrace(policy, {outcomes, attemptInfoAvailable})— imports only@wdio/devtools-shared, no driver, no frameworkbackend/src/baseline/types.tsTimeWindowNode.statestart/endActiveRun.commands,consoleLogs,networkRequests,mutations,actionSnapshots,screencastFrames— all timestampedThe pytest plugin already feeds those nodes; Preserve & Rerun needed them. No
new capture is required.
What is missing
trace-retention.tsfromcoretotrace. A pure file move — italready satisfies the
tracerule (sharedand nothing else). Todaybackendhas zero dependency oncoreby design (§2.2), so this is whatmakes the policy reachable at all. Worth doing on its own merits: retention
living in
coreis a layering smell now that a non-core consumer wants it.traceGranularityandtracePolicyonTraceExportRequest(
shared/src/trace-export.ts), so the adapter can state what it wants.core/spec-trace-helpers.tscannot move — it pulls in
node:path,./uid.js,./artifact-naming.jsandis built around a
TraceCapturerthe backend does not have. Mechanically thisis "filter six arrays by
[start, end]per test node"; the risk is in theedges — a command straddling a boundary, a mutation anchored before its test
began, screencast frames shared across neighbouring tests.
Known limitation from day one
retain-on-first-failureneeds per-attempt outcomes. pytest reruns(
pytest-rerunfailures) are not tracked by the plugin's registry, soattemptInfoAvailablewould befalseandshouldRetainTracewould degrade toretain-on-failure— which it already handles explicitly (degradedToFailure),the same way Nightwatch's BDD interface does. Graceful, but the support would
carry an asterisk unless attempt tracking is added too.
Acceptance criteria
A Python run with
traceGranularity: 'test'writes one archive per test, andtracePolicy: 'retain-on-failure'keeps only the failing ones. The retentiondecision is made by the same
shouldRetainTracethe JS adapters use, not asecond implementation.
retain-on-first-failuredegrades toretain-on-failurewith the existing warning until attempt tracking exists.
Sequencing
After #294. Publishing without
tracePolicyis honest as long as #358 saysso, and adding it later is additive. Doing it first delays a release already
gated on three other decisions.
Size: M (step 1 is S; step 3 carries the risk).