Skip to Content
DocsRunning flowsReports (JSON / HTML / JUnit)

Reports

Every klera run can write a versioned JSON report. JSON is canonical; HTML, JUnit, and OTLP replay are derivative views over the same artefact. Read the JSON when you want machine-parseable output, render the HTML when you want a self-contained page to share, emit JUnit when you want PR-pane test results, replay OTLP when you want to backfill an existing report into your observability stack.

klera run flows/login.flow.md --report .klera/reports/login.json klera report .klera/reports/login.json --html out/login.html klera report .klera/reports/login.json --junit out/login.xml klera report .klera/reports/login.json --otlp

The JSON artefact

klera run --report <path> writes the JSON when the run finishes (success or failure). The schema is versioned via a top-level schemaVersion field; readers should branch on it.

{ "schemaVersion": 4, "name": "Sign in and see today's notifications", "status": "passed", "durationMs": 4123, "driftCount": 0, "intentDriftCount": 0, "replanCount": 0, "triage": null, "steps": [ { "index": 0, "kind": "tap", "status": "passed", "durationMs": 412, "drift": null, "intentDrift": null, "error": null, "details": null, "telemetry": null, "idleWait": { "animations": "idle", "network": "idle" }, "visualDiff": null, "boundarySnapshots": null, "matcherTrace": null, "frames": null, "sourceLinks": null } ] }

Top-level fields:

FieldPurpose
schemaVersionInteger; the only field whose meaning never changes. Branch on it.
nameThe flow’s name.
status"passed" | "failed" | "skipped".
durationMsWall-clock duration of the whole flow.
driftCountSteps that resolved via the matcher’s self-healing strategies.
intentDriftCountSteps the planner flagged as semantically drifted from the cache.
replanCountMid-run replans (off in --strict).
triageAuto-triage block on failure (verdict + narratives + suspect commits); null on pass.
stepsPer-step detail array.

Per-step fields populate as the executor accumulates evidence. On a clean pass most are null; on a failure the report ships matcherTrace (every strategy attempt), frames (PNG triplets), boundarySnapshots (element graphs at the failure boundary), and optional sourceLinks (denormalised paths back to the React tree — dev-only).

The schema version bumps every time the shape grows a new field with semantic meaning. A v4 reader handles v1 / v2 / v3 by reading the version up front and treating absent fields as the documented defaults. Don’t Zod.parse against the latest schema unless you control both producer and consumer.

Rendering views

klera report <report.json> reads a JSON report and renders one or more derivative views. Without flags it prints a text summary to stdout; flags compose, each writes an independent artefact.

Text summary

klera report .klera/reports/login.json
Sign in and see today's notifications status: PASSED (4123ms) ✓ [0] tap — passed ✓ [1] type — passed ✓ [2] assert — passed

HTML

klera report .klera/reports/login.json --html out/login.html

Self-contained — no external assets, no relative file paths to preserve. PNG diffs (visual snapshots, failure frames) are embedded as data URIs. Open out/login.html directly in a browser; share the file by email or Slack and it works for the recipient with no extra setup.

The HTML view annotates idle-wait bars per step, draws the visual-diff triplet (actual / baseline / diff) when present, and renders the triage card with verdict + narratives + suspect commit list when the run failed. XSS is escaped at the render boundary.

JUnit XML

klera report .klera/reports/login.json --junit out/login.xml

Mapping:

JUnit elementklera report field
<testsuite>one per flow
<testcase>one per step
<failure>step error + matcher trace
<skipped/>skipped step
<system-out>drift + triage annotations

Every CI test-results pane that reads JUnit picks this up: GitHub Actions test reporters, GitLab MR test panes, CircleCI test insights. See CI scaffolds for the wiring.

OTLP replay

OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io \ OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=YOUR_KEY \ klera report .klera/reports/login.json --otlp

Replays the report’s spans + metrics through the same bootstrap klera run uses live. Adopters who wired OTel after they already had an archive backfill with one shell loop:

for r in .klera/reports/*.json; do klera report "$r" --otlp done

Output:

replayed to OTLP — 4 span(s), 7 counter increment(s), 2 histogram sample(s)

--otlp requires a valid OTLP activation source (the standard env vars or .klera/config.yaml telemetry.otlp.endpoint). Without one, the command exits 1 with a clear message rather than silently no-opping. See observability for the full attribute schema.

Schema versioning

Each schemaVersion bump is additive — fields gain meaning, never lose it. Older readers see new fields as opaque keys they ignore.

VersionAdded
1base shape: name, status, durationMs, steps[]
2per-step idleWait and visualDiff
3per-step boundarySnapshots, matcherTrace, frames, sourceLinks
4top-level triage block (verdict + narratives + suspect commits)

Adopters writing report-consumers should:

const report = JSON.parse(await readFile(path, 'utf8')) switch (report.schemaVersion) { case 1: return readV1(report) case 2: return readV2(report) case 3: return readV3(report) case 4: return readV4(report) default: throw new Error(`unknown schemaVersion: ${report.schemaVersion}`) }

The klera/cli ships fixture-tested readers for v1 and v2 (legacy backwards-compat). Use those if you need a parser that ages well.

Reports + watch

Watch mode honours --report <path>: each iteration overwrites the same file. Pair with klera report --html and an auto-refreshing browser tab to keep an HTML view live as you edit. See watch mode for the full session shape.

Reports + CI

The canonical CI pipeline is JSON → JUnit → test-results pane. The klera ci scaffolds wire this up automatically; the manual shape:

- run: klera run flows/login.flow.md --report report.json - run: klera report report.json --junit junit.xml if: always() - uses: dorny/test-reporter@v1 if: always() with: name: klera path: junit.xml reporter: java-junit

See CI scaffolds and observability for end-to-end walkthroughs.

Last updated on