Skip to content

refactor(trace): extract the trace-format transforms into their own package, and export traces from the backend - #333

Merged
vishnuv688 merged 8 commits into
mainfrom
vv/301-shared-trace-helpers
Aug 27, 2026
Merged

refactor(trace): extract the trace-format transforms into their own package, and export traces from the backend#333
vishnuv688 merged 8 commits into
mainfrom
vv/301-shared-trace-helpers

Conversation

@vishnuv688

@vishnuv688 vishnuv688 commented Aug 25, 2026

Copy link
Copy Markdown
Member

What & why

Two related changes, split into eight reviewable commits. Part of #301.

1. The trace transforms move to a new workspace-internal package,
@wdio/devtools-trace (commits 1–4).

core is the one layer every adapter needs and Python cannot reach — it is
TypeScript. So everything it provides was written a second time in Python
(~1,200 lines that are not language-specific), and that gap has already cost
us: the force-anchor drain (#285), the recovery drain (#286) and document-start
preload (#284) were each fixed in the JS adapters and silently never reached
Python. Trace assembly is another ~2,000 lines; ported, it becomes the second
copy, and Java would make it the third.

The backend could host it once for every language, but backend → core is
forbidden (eslint.config.cjs, CLAUDE.md §2.2) because core is adapter
logic. Rather than weaken that rule, the transforms move below it: walking the
import graph, every one of them depends on nothing but shared, yazl and
node builtins — none touches a driver or a framework, which is what made the
split possible at all. Layering is now shared ← trace ← core ← adapters and
shared ← trace ← backend, enforced in ESLint.

Adapter-side orchestration and policy stay in core: trace-finalizer,
spec-trace-helpers, and trace-retention — which despite its name governs
screenshot and video retention too, so it is not a trace transform.

2. The backend can build a trace from the run it already accumulates
(commits 5–8).

Over the worker socket, using those same transforms. The JS adapters keep
calling them in-process, so backend-free trace mode (launcher.ts: "Trace
mode — skipping backend and Chrome window"
) is untouched and its output stays
byte-stable. This exists for an adapter that streams but cannot transform.

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Polish (an improvement to an existing feature)
  • Breaking change (existing behavior changes for users)
  • Documentation
  • Internal (build, CI, dependencies, tooling)

Packages touched

  • shared (types and contracts)
  • core (framework-agnostic capture/reporting)
  • elements (published element/snapshot API — @wdio/elements)
  • service (WebdriverIO adapter)
  • nightwatch-devtools (Nightwatch adapter)
  • selenium-devtools (Selenium adapter)
  • backend (server)
  • app (UI)
  • script (page-injected runtime)
  • selenium-devtools-py

Plus a new trace package. service is config-only — its vite external
callback enumerated the private packages by name, so a fourth would have been
silently externalized and the dist would have died at install with
ERR_MODULE_NOT_FOUND. It is a list now.

Notes for reviewers

No adapter source file changed. The 13 moved files are byte-identical to
their originals (verified by checksum), and core re-exports them per module
rather than as one export * so its public surface is provably unchanged —
diffed module-by-module against the parent commit, trace-transcript still
deliberately absent as before. Test count was identical either side of the
move.

This carries a refactor and a feature in one PR, which CLAUDE.md says
should be two. The seam is clean and verified — commits 1–4 pass on their own
(163 files / 2171 tests, typecheck and lint clean at a3fb35b) — so it can
still be split if a reviewer would rather. Merging as one was a deliberate
call, not an oversight.

Two duplications dissolved by the move. trace-reader-utils.ts carried a
local copy of sha1Hex whose comment named the cause ("the backend only
imports from shared"), and hand-built the writer's src@<sha1>.txt template
inline. Those had to agree or source recovery in the viewer silently returns
nothing, with no test able to catch a rename on one side. Both now resolve to
sourceResourceName.

One divergence from the #298 decision record, which listed
trace-retention as moving: it stays in core, per the reasoning above.

Known gaps in the backend export, both already tracked on #301.
actionSnapshots does not travel (the exporter synthesizes from commands
carrying screenshots), and neither do screencastFrames — the screencast
scope carries video metadata, not frames. A stream-fed export matches
in-process fidelity only once those travel. Nothing sends the export frame yet;
the Python side is #288.

yazl had to become a runtime dependency of backend — the inverse of
the workspace-internal rule, and worth knowing about. Importing the trace
writer pulled yazl into the ESM bundle, and yazl is CJS: esbuild rewrote its
require into a shim that threw Dynamic require of "fs" is not supported,
killing dist/show-trace.js on every invocation. Neither pnpm build, pnpm test nor the workspace-leak grep noticed — all three pass on a dist that dies
on first import. packages/backend/tests/dist-bundling.test.ts now asserts the
shim is absent; verified by rebuilding without the fix and watching it fail.

Verification

  • pnpm test — 166 files, 2197 tests
  • pnpm test:ui — 31/31
  • pnpm lint — 0 errors, no new warnings
  • pnpm build + tsc --noEmit — clean
  • Workspace-internal leak grep — clean in all four dists, trace included
  • 12 mutations against the new backend code, all caught (dropping metadata,
    sources, console and network; accepting a partial frame; removing the
    try/catch; deleting the dispatch branch)
  • pnpm show-trace run against a real cucumber trace zip — player serves,
    /api/trace returns 200

Screenshots / recordings

Not applicable — no UI change.

@greptile-apps

greptile-apps Bot commented Aug 25, 2026

Copy link
Copy Markdown

Greptile Summary

The PR extracts trace-generation transforms into a private trace package, moves shared action and console helpers out of core, and adds backend-side trace export from accumulated worker data.

  • Adds the @wdio/devtools-trace workspace package and updates package boundaries, aliases, lint rules, and bundler configuration.
  • Adds a shared trace-export worker contract and backend reconstruction/export handling.
  • Updates tests and architecture documentation for the new package layout.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the provided follow-up-review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/backend/src/trace-export-message.ts Adds parsing, dispatch, and response handling for worker-requested trace exports; no follow-up-eligible issue was established.
packages/backend/src/trace-export.ts Converts accumulated backend run state into the trace package’s exporter input and writes the requested artifact.
packages/backend/src/baselineStore.ts Extends active-run accumulation and snapshot access to support backend-side trace reconstruction.
packages/shared/src/trace-export.ts Defines the shared request and result contract for trace-export worker messages.
packages/trace/src/trace-exporter.ts Moves the existing trace assembly implementation into the new framework-independent trace package.
packages/service/vite.config.ts Updates private-workspace-package handling so shared, core, and trace code remain bundled into the service distribution.
packages/backend/package.json Adds the private trace package as a build-time dependency and keeps the CJS zip writer externalized as a runtime dependency.

Sequence Diagram

sequenceDiagram
    participant A as Adapter worker
    participant B as Backend
    participant S as Baseline store
    participant T as Trace package
    participant F as Trace artifact
    A->>B: Captured event frames
    B->>S: Accumulate active run
    A->>B: traceExport request
    B->>S: Read active-run snapshot
    B->>T: Build and write trace
    T->>F: trace.zip
    B-->>A: Export result
Loading

Reviews (3): Last reviewed commit: "fix(backend): externalize yazl so the sh..." | Re-trigger Greptile

@vishnuv688 vishnuv688 changed the title refactor(shared): move action-mapping and console out of core refactor(trace): extract the trace-format transforms into their own package, and export traces from the backend Aug 27, 2026
@vishnuv688 vishnuv688 linked an issue Aug 27, 2026 that may be closed by this pull request
@vishnuv688
vishnuv688 merged commit 4669c80 into main Aug 27, 2026
11 checks passed
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.

Move stream post-processing behind the wire

1 participant