AI agent skill · by @zenobi-us
Writing Reports
Writes a self-contained HTML evidence report with screenshots, captions, result badges and a clickable summary table. Use when work must be proved rather than claimed - manual test results, acceptance evidence, an audit, a migration check, a bug reproduction, or any hand-off that needs "here is the screenshot that shows it". Results in one portable directory that renders anywhere, with gaps and leftover test data named.
Archived 2026-10-23 · Source updated 2026-09-18 · License: MIT. Check the original repository for the latest version.
SKILL.md instructions
# writing-reports A report is evidence. It states what was checked, shows the screenshot that proves each result, and names what was **not** covered. A wall of terminal output is not a report. A Markdown file with no screenshots is not a report. This skill produces a directory that renders in any browser, survives being moved or zipped, and can be attached to a ticket. ## When to use - Someone asks for a test report, acceptance evidence, QA results, or proof. - You finished manual testing and the result must outlive the chat session. - An audit, migration, or reproduction needs a durable record. - Another skill hands you evidence and a destination. The `browser-acceptance-evidence` skill does exactly this. Do not use for a running commentary, a plan, or a design document. A report records what happened, in the past tense, with proof. ## Core shape ``` <destination>/ index.html the report assets/theme/v1/ tokens.css, base.css <- never edit assets/report/v1/ report.css <- never edit assets/lightbox/v1/ lightbox.js <- never edit shots/ NN-slug.png files/ companion artifacts the report links to ``` Every report carries its own copy of the four asset files, linked sibling-relative. That is deliberate: a report gets moved, zipped, downloaded and reopened from somewhere else. A report that only renders inside one directory tree is a report that dies on first contact with a reviewer. `files/` holds the same idea for everything else the report links to: the test plan it ran, the evidence file behind the verdicts, a script or a workflow a reader would re-run. Those artifacts usually live in a sibling directory. A copy goes in `files/` so the link survives the move. ## Rules - You **MUST** create the report with `scripts/new-report.ts`. Do not write a report page from scratch, and do not copy the template by hand. - You **MUST NOT** put a `<style>` block, a `style=""` attribute, or inline lightbox JavaScript into the page. Every rule lives in the linked CSS. - You **MUST NOT** write a colour into the page. Every colour is a theme token. A raw hex value outside `<pre>` and `<code>` fails validation. - You **MUST NOT** edit any file under `assets/theme/v1/`, `assets/report/v1/`, or `assets/lightbox/v1/` — in a report or in this skill's template. Published reports link those files forever. A breaking change goes in a new `v2` directory. - You **MUST NOT** change an asset path to `../` or `../../`. The report is self-contained. - You **MUST** copy any companion artifact the report links to — a test plan, an evidence file, a script, a workflow — into `<destination>/files/`, and link it sibling-relative as `files/<name>`. You **MUST NOT** reach a sibling directory with `../`, even for a link that is not an asset. A report is handed over on its own; a `../` link dies the first time it moves. Leave the original where it is and treat the copy as the reader's copy. - You **MUST** give every `<img>` a `class`, `src`, `alt`, `width`, and `height`. Without the size the page shifts while screenshots load and every jump link lands on the wrong section. - You **MUST** read each image's real pixel size with `scripts/imgsize.ts`. You **MUST NOT** guess a size, reuse the size of another shot, copy the template's placeholder numbers, or trust what a screenshot tool said it produced. The validator reads the file itself and fails on a mismatch. `imgsize.ts` reads PNG and JPEG headers directly, so it needs no external tool. You **MUST NOT** write your own size reader, wrapper or shim — if `imgsize.ts` cannot read a file, save that screenshot as PNG or tell the user, and do not type a number it did not give you. - You **MUST** class every styled node. Strict BEM. A node with no class gets no style. - You **MUST** use the vocabulary in `references/markup.md`. Do not invent a class. A layout the vocabulary cannot express is a reason to ask the user, not a reason to add a `<style>` block. - You **MUST** write a "Not covered" section, with an `id="notdone"`, even when it is short. A report that hides its gaps is worth less than one that names them. State the risk each gap leaves. - You **MUST** pass `scripts/validate-report.ts` before you call the report done. - The scripts are TypeScript run by Bun through a `mise x -- bun --install=fallback` shebang. Run them directly. Do not invoke them with `bash`, `sh`, `node` or `python`. ## CLI Run `scripts/report-cli.ts --help` for the Crust router. Use `new`, `validate`, `imgsize`, and `doctor`. The individual script paths remain direct compatibility entry points. ## Procedure 1. **MUST** create the report directory: ```sh scripts/new-report.ts "<destination-dir>" "<TICKET> — what this proves" ``` The destination must not exist. When another skill supplies a destination, use it verbatim. 2. **MUST** save every screenshot into `<destination>/shots/`, named `NN-slug.png`. `NN` orders the shots as the reader meets them, and leaves gaps for later inserts: `10-login.png`, `20-banner.png`, `31-missing.png`. 2b. **MUST** copy every companion artifact the report will link to into `<destination>/files/`: ```sh mkdir -p <destination>/files cp <plan> <evidence> <workflows> <destination>/files/ ``` Link them from the page as `files/<name>`. A report that points at a sibling directory stops working the moment someone zips it and sends it on. 3. **MUST** read the real pixel sizes: ```sh scripts/imgsize.ts <destination>/shots/*.png ``` It prints `<name> <width> <height>` per file, read from the file header. 4. **MUST** write the result summary first, before any section. One row per check. Every cell of a row carries the same `<a class="summary__link" href="#section">`, which makes the whole row clickable with no JavaScript. Drop one anchor and that cell stops working. 5. **MUST** give every section an `id` that a summary row targets. A summary row with no target is a broken promise. 6. **MUST** pick the badge that tells the truth: | Badge | Use for | |---|---| | `badge--pass` | The check passed. | | `badge--fail` | The check failed. Say who owns the failure. | | `badge--info` | Not testable, not reached, or a neutral finding. | | `badge--warn` | A bug found on the side, unrelated to the change. | A check you could not run is `badge--info`, never `badge--pass`. "The code looks right" is not a pass. A pass needs a screenshot. 7. **SHOULD** write a "Test data left behind" section when the work changed shared state: accounts, records, config overrides, running servers. Say what to delete and how. 8. **MUST** validate: ```sh scripts/validate-report.ts <destination>/index.html ``` Fix every line it prints. The script is the gate, not a suggestion. 9. **SHOULD** open the page and click one screenshot, to confirm the lightbox opens and the caption reads correctly. ## Common mistakes | Mistake | Why it breaks | Fix | |---|---|---| | Guessing `width`/`height` | The page reflows on load; jump links land wrong | Run `scripts/imgsize.ts` | | A `<style>` block "just for this one bit" | The report stops matching every other report | Use a vocabulary class | | `badge--pass` on an unproven check | The report lies, and lies are worse than gaps | `badge--info` plus a "Not covered" row | | Caption repeats the `alt` text | `alt` describes the picture; the caption says what it proves | Write two different sentences | | No "Not covered" section | The reader assumes full coverage | Always write it | | `../plan.md` in a link | The report dies when moved or zipped on its own | Copy into `files/`, link `files/plan.md` | | Editing `report.css` to fix one page | Restyles every past report | New `v2` directory, or ask | ## Reference - `scripts/imgsize.ts` — real pixel sizes from the file header. - `references/markup.md` — the class vocabulary, with an example of each block. - `assets/report-template/index.html` — the skeleton, with slot comments. - `assets/report-template/assets/theme/v1/tokens.css` — every colour, size and radius available. - `assets/report-template/assets/lightbox/v1/lightbox.js` — the header comment lists every `data-*` option the script tag accepts.