e2e-report-renderer
Skill1 starsChanged 56 days agoApache-2.0View on GitHub
Render settled e2e-runner JSON as offline HTML in single-run, trend, or comparison mode when asked to visualize or share E2E results. Preserve input data.
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 1 is distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 51
Every field listed as required in CONTRACT.md §5 is present (not just defined).
- Very specific: line 53
Every results[*].dependsOn reference targets a results[*].id present in the same JSON.
- Very specific: line 63
REN-7 (No build step) — MUST: No bundler, no transpiler, no node_modules.
- Very specific: line 87
REN-11 (Theme) — SHOULD: Default theme follows prefers-color-scheme.
- Very specific: line 109
If the runner's JSON contains a value that already looks masked (matches a <MASK:...> placeholder), the renderer leaves it alone.
- Very specific: line 114
If the result still exceeds 4 MB, stop with REN-14: report exceeds 4MB after fallback truncation.
- Distinctive: line 124
REN-16 (No-input behavior) — MUST: If the requested input does not resolve to at least one settled run JSON:
- Very specific: line 138
REN-22 (Missing raw/logs degradation) — MUST: When the run JSON references evidence.rawBodyPath or evidence.logTailPath but the file does …
- Very specific: line 140
Add a footer line: Missing artifacts: <count>.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
E2E Report Renderer — HTML Rendering Protocol
This skill is normative. MUST / MUST NOT / SHOULD carry RFC-2119 meaning. Rules are cited by ID (REN-n).
Authority:
AGENTS.mdis binding. This skill is a view layer overe2e-runner's data; it never re-interprets results or fabricates them.
Shared contract:
docs/e2e-scenarios/CONTRACT.mdis the SSOT for the run-result JSON schema and mask classes. Its bootstrap source and validator ship with the requirede2e-scenario-authordependency. If this skill disagrees with the project contract, the project contract wins.
Input: a run JSON (or set of run JSONs) under
test-report/e2e/. Output: an HTML file in the same directory. HTML output is git-ignored by project policy; if you want history, the JSON beside it is the SSOT.
Reference loading: Apply the common REN contract below and the project report/masking contract. Only
trendorcompareloads comparison modes, the canonical REN-18..21 definitions. Read HTML security if safe embedding is unclear, artifact handling for missing/truncated evidence, or accessibility when changing the shipped visual template. Principles explain rationale; the KB index locates other topics. Read either only when needed. MUST NOT recursively load the entire KB.
A. Boundary
REN-1 (Input is JSON only) — MUST. The skill reads *.json produced by e2e-runner, conforming to CONTRACT.md §5. It MUST NOT parse the runner's Markdown summary, the catalog, or anything else as a primary data source.
REN-2 (Read-only on inputs) — MUST NOT. The skill MUST NOT modify or delete the run JSON, the raw/ directory, or the logs/ directory. Output is written only to test-report/e2e/*.html.
REN-3 (No execution) — MUST NOT. The skill MUST NOT invoke e2e-runner, e2e-scenario-author, docker, gradle, or any system probe. It works strictly from existing files on disk.
B. Modes
REN-4 (Three modes) — MUST. Exactly three modes; pick one per invocation:
| Mode | Trigger | Output filename |
single-run (default) | User points at one {run-id}.json (or it is implied as "the latest settled run") | {run-id}.html (next to the JSON) |
trend | User asks for "last N runs", "trend", "history" | trend-N{N}-{YYYY-MM-DD}.html (see REN-18) |
compare | User passes two run IDs ("A vs B") | compare-{A_lex_smaller}-vs-{A_lex_larger}.html (see REN-19) |
For single-run with no path given, default to the most-recently-modified *.json under test-report/e2e/ that has a sibling .done marker (per REN-17). If no such JSON exists, REN-16 applies.
REN-5 (Schema & contract validation) — MUST. On reading each JSON the skill MUST validate:
schemaVersion == 1andcontractVersion == 1. Mismatch → stop withREN-5.VERSION: <file>: expected schemaVersion=1, contractVersion=1; got <s>, <c>.- Every field listed as required in
CONTRACT.md §5is present (not just defined). Missing field →REN-5.MISSING-FIELD: <file>: <jsonpath>. summary.total == pass + fail + skipped + failedDependency + probeError. Mismatch →REN-5.SUMMARY-MATH: <file>.- Every
results[*].dependsOnreference targets aresults[*].idpresent in the same JSON. Missing →REN-5.DANGLING-DEP.
Best-effort rendering of a malformed JSON is forbidden. The renderer either produces a faithful view or nothing.
C. Single-file output constraints
REN-6 (No external resources) — MUST. The output HTML MUST NOT reference any external URL — no CDN script, no Google Fonts, no remote images. All CSS, JS, fonts (system stack), data, and inline SVG live inside the single .html file.
REN-7 (No build step) — MUST. No bundler, no transpiler, no node_modules. CSS is hand-written with :root variables; JS is vanilla (ES2020). The skill writes the HTML directly using fixtures/template.html as the structural starting point.
REN-7.1 (Safe JSON inlining) — MUST. When substituting the run JSON into the <script type="application/json"> block of the template, every occurrence of </ in the JSON text MUST be replaced with <\/ before insertion. Without this escape, a JSON string value containing the literal </script> would terminate the script block early — breaking the page in the benign case and enabling XSS in an adversarial case (e.g. a response body crafted by an upstream service that the runner faithfully captured).
REN-8 (Raw inline embedding) — MUST. Response bodies (head 4 KB + tail 4 KB per scenario, per RUN-13) and log tails (failed scenarios only) MUST be embedded directly into the HTML as <pre> blocks rather than linked. Linked artifacts defeat the "share one file" property. On overflow show a ...truncated, see test-report/e2e/<run-id>/raw/ notice.
REN-9 (XSS-safe text injection) — MUST. All dynamic text from the JSON (purpose, actual, evidence, log tail, response body) is set via textContent or pre-escaped before insertion. innerHTML with un-escaped runner data is forbidden. This guards against a response body that happens to contain <script> or <img onerror>.
D. Visual design
REN-10 (Semantic color + non-color signal) — MUST. Status uses both color and an icon/text glyph:
| Status | Color | Glyph |
PASS | green | ✓ |
FAIL | red | ✕ (bold) |
SKIPPED (precondition-unmet) | gray | – |
PROBE-ERROR | amber | ? |
FAILED-DEPENDENCY | amber | ⤴ (with link to blocking parent ID) |
Color alone MUST NOT carry information (accessibility). Contrast targets WCAG AA or better — verify with the paired token table in fixtures/template.html (the template ships compliant pairs; do not improvise new pairs without re-checking contrast).
REN-11 (Theme) — SHOULD. Default theme follows prefers-color-scheme. Provide a top-right toggle. Persisting the user's choice in localStorage is acceptable but not required by this skill.
REN-11.1 (Default UI language is Korean) — MUST. All user-facing labels in the rendered HTML — summary card labels, filter placeholders, table headers, footer notice, error/empty-state messages, expanded-row key labels — MUST be in Korean. Status code values themselves (PASS / FAIL / SKIPPED / FAILED-DEPENDENCY / PROBE-ERROR) remain uppercase English because they are literal data values shared with the runner JSON contract; the filter dropdown displays them in the form 통과 (PASS) so the data join continues to work without an i18n table on dataset.status. fixtures/template.html ships Korean labels by default; if an English variant is ever needed, fork the template under a new fixture path and select it via a future skill option — never mix the two within one report.
REN-12 (Layout) — MUST. The single-run report contains, in order:
- Header —
runId,mode,git.sha,git.branch, catalog SHA, stale flag, working-tree-dirty flag, wall time. - Summary cards — exactly five numbers (
pass,fail,skipped,failedDependency,probeError) plustotal.totalis rendered as a literal copy ofsummary.total(validated for math underREN-5), not recomputed in JS. - Filters — area dropdown, status dropdown (with
PROBE-ERRORas a distinct option), text search. - Results table —
ID / Purpose / Dataset / Expected / Actual / Status / Latency, expandable per row to show embedded raw body / log tail. - Failures detail — every
FAILrow expanded by default. - Remaining risks — bulleted list from
remainingRisks.
For trend mode, prepend a small inline-SVG line chart of pass rate over the last N runs and a "flaky scenarios" table per REN-21.
For compare mode, prepend a side-by-side diff of summary numbers and a per-scenario status delta (PASS → FAIL, etc.) before the rest, plus the cross-catalog handling per REN-20.
E. Safety & noise
REN-13 (Masking is mandatory, not advisory) — MUST. Apply every mask class defined in CONTRACT.md §7 to any body / log text injected into the HTML — even though the runner already masked the report Markdown and the raw artifacts (RUN-14), the renderer MUST mask again as a second defense layer. The output HTML is the most shareable artifact in the pipeline; under-masking it leaks PII into chat threads and PR comments.
If the runner's JSON contains a value that already looks masked (matches a <MASK:...> placeholder), the renderer leaves it alone.
REN-14 (Size cap) — SHOULD. The produced HTML SHOULD stay under 4 MB. If it would exceed:
- Truncate per-scenario inline bodies to 1 KB head + 1 KB tail.
- Drop log tails for
FAILscenarios when total log inline > 200 KB across the report. - If the result still exceeds 4 MB, stop with
REN-14: report exceeds 4MB after fallback truncation; render fewer runs or single-scenario subset.
A footer notes the applied truncation level when steps 1 or 2 fire.
REN-15 (No browser auto-open) — MUST NOT. The skill MUST NOT execute open, xdg-open, or any other command that opens the file in a browser — environment side effects belong to the user. Print the output path instead.
F. Edge cases
REN-16 (No-input behavior) — MUST. If the requested input does not resolve to at least one settled run JSON:
| Situation | Action |
single-run default, test-report/e2e/ empty or no .done markers | Print REN-16: no settled run found under test-report/e2e/. Exit non-zero. Do NOT render an empty page. |
single-run explicit path missing | Print REN-16: file not found: <path>. Exit non-zero. |
trend with fewer than 2 settled runs | Print REN-16: trend mode requires ≥ 2 settled runs; found <N>. Exit non-zero. |
compare with one or both run IDs missing | Print REN-16: compare missing: <id> for each missing one. Exit non-zero. |
REN-17 (In-progress race protection) — MUST. A run JSON is settled iff a sibling .done marker file exists in the same run directory (RUN-15). The renderer MUST refuse to render an unsettled JSON in any mode and MUST NOT include unsettled runs in trend selection or compare resolution. Unsettled JSONs print a warning line but do not crash the run.
For trend or compare, apply REN-18 through REN-21 before selecting runs
or computing aggregates. A single-run render does not load that mode contract.
REN-22 (Missing raw/logs degradation) — MUST. When the run JSON references evidence.rawBodyPath or evidence.logTailPath but the file does not exist on disk:
- Render the row with a
(artifact missing)notice in place of the inline<pre>block. - Add a footer line:
Missing artifacts: <count>.
This does NOT fail the render — a missing artifact is a known degraded state (e.g. someone copied the JSON elsewhere without the raw/ directory) and the rest of the report is still useful.
G. Companion behavior
| You want | Skill |
| Refresh the scenario catalog from code | e2e-scenario-author |
| Execute the catalog and produce JSON | e2e-runner |
| Turn that JSON into a shareable HTML | this skill |
The three skills never call each other. Their only coupling is the on-disk artifact each one consumes from the previous, plus the shared CONTRACT.md.
REN-23 (Contract reference is normative) — MUST. The renderer treats CONTRACT.md as a normative input. A contractVersion bump is a coordinated three-skill PR; the renderer alone cannot raise the version. The skill recognizes contractVersion == 1 only; any other value fails REN-5.VERSION.
Checklist
- Input
schemaVersion == 1ANDcontractVersion == 1verified; all required fields present; summary math checks (REN-5) - Default
single-runpath waits for the.donemarker; unsettled runs refused (REN-17) - No-input edge cases handled (
REN-16) - Output is a single
.htmlfile intest-report/e2e/(REN-4) - Trend filename embeds actual N; compare filename canonically sorted (
REN-18,REN-19) - Cross-catalog runs banner shown; flaky logic uses common-scenarios subset (
REN-20,REN-21) - Zero external network references in output (
REN-6) - All runner-derived text injected via
textContentor pre-escaped (REN-9) - Status uses color + glyph;
PROBE-ERRORdistinguished fromSKIPPED(REN-10) - Defensive masking from
CONTRACT.md §7applied to embedded bodies and logs (REN-13) - Size cap fallback applied or hard-failed; missing artifact degradation graceful (
REN-14,REN-22) - Output path printed; no browser auto-open (
REN-15) - Runner JSON, raw/, logs/ untouched (
REN-2) - Contract version on disk matches renderer-supported version (
REN-23)
In this repository65 other files it gives its agents.
- agent-evalSkill
- architecture-review-workflowSkill
- backend-code-review-workflowSkill
- code-authoring-routerSkill
- code-diagram-extractSkill
- codex-agent-runtimeSkill
- design-pattern-applySkill
- diagram-stylerSkill
- document-designerSkill
- e2e-evidence-reportSkill
- e2e-runnerSkill
- e2e-scenario-authorSkill
- e2e-test-workflowSkill
- entitySkill
- enumSkill
- explore-dead-codeSkill
- flywaySkill
- git-flowSkill
- harness-proposeSkill
- harness-refineSkill
- java-spring-review-workflowSkill
- knowledge-auditSkill
- korean-dev-writerSkill
- kotlin-code-authoringSkill
- kotlin-spring-reviewSkill
- kotlin-spring-review-workflowSkill
- learnSkill
- mapperSkill
- markdown-publisherSkill
- mermaid-diagramsSkill
- mssql-code-authoringSkill
- nl-sql-querySkill
- notion-domain-contextSkill
- oop-design-reviewSkill
- opensearch-code-authoringSkill
- opensearch-optimizationSkill
- opensearch-query-reviewSkill
- opensearch-review-workflowSkill
- opensearch-schema-reviewSkill
- pdf-qaSkill
- playwright-e2eSkill
- postgres-code-authoringSkill
- postgres-query-reviewSkill
- postgres-review-workflowSkill
- postgres-risk-checkSkill
- postgres-schema-designSkill
- product-requirementsSkill
- product-ui-designSkill
- refactoring-catalogSkill
- repositorySkill
- requestSkill
- responseSkill
- retroSkill
- schema-doc-extractSkill
- security-scan-workflowSkill
- serviceSkill
- skill-updaterSkill
- start-taskSkill
- test-authoringSkill
- test-quality-refactoring-workflowSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

