Delivered per session under {project}/session-{YYYY-MM-DD}-{shortid}/:
session.yaml # upserted on every issue, always consistent
01-{slug}.md # one markdown file per issue, YAML frontmatter + body
01-{slug}.png # optional screenshot(s)
01-{slug}-frames/ # record-mode clips
clip-01/01.png …
02-{slug}.md
...session.yaml carries the environment (browser, OS, viewport, screen, DPR, language(s), timezone,
color scheme, reduced-motion) plus an index of issues. Each NN-{slug}.md repeats the per-issue
metadata in frontmatter followed by the free-text comment.
The structure and frontmatter are a stable contract intended as input for downstream parsers
and agents — they only ever change additively. session.yaml starts with
format_version: "1.4"; a missing version means "1.0". Within a major version, new fields are
only ever added, never removed or repurposed. The full field dictionary, section rules and
versioning policy live in
SPEC.md — safe to build parsers
against.
Within a major version the format only ever changes additively — new optional fields. A parser written for 1.x keeps working as 1.x grows, so ignore fields you do not know rather than failing on them.
An issue file, annotated
---
id: "01"
url: /dashboard/animals
selector: 'button[aria-label="Save"]'
selector_strategy: aria # how the selector was derived
selector_unique: true # it matches exactly one element
mode: element # element | area | fullpage | comment
category: bug
element_text: "Save"
dom_path: "body > main > form > button"
component: AnimalForm # React component hint (element mode, best-effort)
screen: dashboard
viewport: 1512x982
screenshot: 01-save-does-nothing.png
masked: true # inputs were masked in the render
errors_count: 1
actions_count: 4
recording: true
frames_count: 3
frames_dir: 01-save-does-nothing-frames
created_at: 2026-07-23T14:05:10Z
reporter: # present only when identity is configured
user_id: u_18293
email: "anna@acme.io"
name: Anna K.
---
The Save button does nothing after I edit an animal — the form
just sits there, no toast, no error I can see.
## Errors
- [3s before report] console: PATCH /api/animals/128 500 (Internal Server Error)
- [2s before report] exception: Uncaught TypeError: Cannot read properties of undefined (reading 'id')
at save (/assets/animals-4f2a.js:210:19)
## Actions
- [22s before report] navigate /dashboard → /dashboard/animals
- [12s before report] click #edit-128 ("Edit") — frame 02
- [5s before report] type (11 chars) input#name
- [1s before report] click button[aria-label="Save"] ("Save") — frame 03Sections an issue can carry
## Errors— recent console errors, uncaught exceptions, promise rejections and failed network calls, each with a relative timestamp. See error capture.## Actions— the action trail: clicks, SPA navigations, submits, typing (character count only, never content). Record-mode lines are tagged— clip N, frame NN.## Console errors— programmatic captures can append their own list.
Optional frontmatter blocks
reporter— fromidentityconfig (never collected by default).custom— flat project fields fixed at init.context— live host state fromsetContext, merged at capture time.form— the reporter's own answers (form fields).attachments— files the reporter attached, withoriginal_namekept as data, never as a path.screenshot_failed: true+screenshot_error— when a render failed and the issue was delivered comment-only.scrubbed: true— the artifact went through the PII text scrub.
Checklist verdicts
When checklist mode is active, session.yaml additionally carries a
checklist: block — the coverage map of pass/fail/unchecked verdicts, each linking to the issue
that documents a failure.
Selector quality
Selectors prefer data-testid → id → aria → landmark path, and never emit Tailwind utility or
hashed CSS-Modules classes. selector_strategy names which rung was used and selector_unique
says whether it matches exactly one element — an agent can trust the selector or fall back to
dom_path + element_text.
The report a client reads
The folder is the machine-readable truth; npx sluglist report turns it into one self-contained HTML
file — no external request, opens from file://, forwards as a single attachment.
npx sluglist report # the newest session
npx sluglist report --all --since 2026-08-18 # a week of feedback, one article
npx sluglist report session-a session-b -o week.htmlWith several sessions the reports are ordered by when each was written, not by filename or delivery time — a report captured on the 18th and delivered on the 24th belongs where it happened.
Each report shows a heading, three tags (page, category, time) and the reporter's own words. The full frontmatter, the session context and the action trail fold into one Details and action trail spoiler: a 25-step trail is evidence, so it is never dropped, but it does not get to bury the sentence a human wrote. Every spoiler opens before printing.
Set title in the issue frontmatter (format 1.8), or drop a titles.json beside the sessions, and
the report uses that heading instead of a truncated first sentence. Five to eight words describing
what was seen — and it never replaces the comment, which stays verbatim underneath.
Clicking a thumbnail opens a viewer: arrows walk the images of that report, Esc or a click
anywhere closes it, and the article stays visible behind. A full-page capture (1708 × 13758 is a real
one) is fitted to the width and scrolled, rather than squeezed into an unreadable strip.