# Visual Recaps

Visual recaps turn a PR, a Graphite stack, or a subset of PRs in a stack into a reviewable HTML artifact under `visual-recaps/`. They are for changes whose shape is hard to understand from a raw diff: multi-file work, UI changes, schema or API changes, permissions, architecture moves, migrations, or review-critical behavior.

Skip a recap when the change is tiny and a reviewer will understand it faster in GitHub.

## Scope Modes

Every recap must declare exactly one scope mode near the top of the page.

| Mode | Use For | Shape |
|---|---|---|
| `single-pr` | One PR | Diff-first, concise, focused on reviewer risk. |
| `stack` | A complete Graphite stack | Narrative-first, longer, organized by the work arc and PR sequence. |
| `stack-subset` | Selected PRs from a stack | Same as `stack`, but with an explicit included/excluded scope block. |

The scope panel should include:

- `Scope`: `Single PR`, `Stack`, or `Stack subset`.
- `Included`: PR numbers, branch names, or commits covered.
- `Excluded`: only for `stack-subset`, list nearby PRs deliberately left out.
- `Base` and `Head`: enough information for a reviewer to recreate the diff.
- `Date`: visible publication date.
- `Sources`: GitHub PRs, Graphite stack, Linear, design links, or relevant discussion.

Use Graphite CLI to understand stack shape and PR order. This repo's agent instruction is to use Graphite CLI for branch and remote operations; do not replace that with raw `git` branch or push commands.

## Required Page Contract

Put recaps at:

```text
visual-recaps/<topic>-YYYY-MM-DD/index.html
```

Use the same self-contained HTML rules as every other preview:

- inline CSS in one `<style>` block;
- inline JS in one `<script>` block only when interaction is useful;
- no runtime `fetch()` except the sanctioned comments widget;
- no secrets, credentials, or customer-identifying data;
- visible date, author, status, and source links;
- comments script before `</body>`:

```html
<script src="/assets/comments.js" data-doc="visual-recaps-<slug>" defer></script>
```

Visual recaps use the warm editorial design system from `AGENTS.md`: Bricolage Grotesque display type, Inter body type, cream background, terracotta accent, amber highlight, and the animated gradient hero for substantial pages. For compact recap indexes or utility pages, follow the existing category index styling.

## Content Skeleton

A strong recap follows this order:

1. Hero: title, status, author, publication date, scope mode, source links.
2. Review map: what changed, why it matters, and what to review first.
3. Scope panel: included/excluded PRs or commits, base/head, stack position.
4. Change narrative: one to three paragraphs for `single-pr`, longer guided walkthrough for `stack` and `stack-subset`.
5. Visual impact: before/after or state wireframes when rendered UI changed.
6. Contract changes: API, schema, permissions, events, data models, or public behavior.
7. File map: grouped changed files with add/modify/delete flags and risk labels.
8. Key changes: annotated excerpts from the load-bearing files.
9. Review checklist: risks, tests to inspect, rollout concerns, follow-ups.
10. Footer: sources, author, publication date.

Critical content must render without JS. Interactions can enhance the recap, but the reviewer should still get the story with scripts disabled.

In file maps, render diff counts as separate color-coded tokens: additions in a muted green, deletions in terracotta/red, and neutral totals in muted text. Do not collapse `+9 / -3` into a single plain string when both sides exist; it should scan visually as two numbers with different meanings.

For annotated code excerpts, render each displayed source row as its own line element and collapse whitespace between generated rows. The recommended pattern is a block `<code>` wrapper with `font-size: 0; line-height: 0;`, then restoring `font-size` and `line-height` on `.line` rows. This prevents preserved newlines between generated `<span class="line">` elements from creating large visual gaps, while keeping line numbers and highlighted rows aligned. Style diff states as row-level treatments: added lines get a muted green left rail and row tint, deleted lines get a muted red/terracotta left rail and row tint, and focused rows keep the amber highlight background even when they are also added or deleted. Let syntax highlighting own the code text color; do not recolor whole added/deleted lines or use strikethrough, because both hurt readability.

Use semantic CSS custom properties for code colors. Inline code chips must not hardcode a light background, because they also appear inside dark code notes. Prefer `color-scheme` plus `light-dark()` for reusable inline-code tokens, then set `color-scheme: dark` on dark code panels so chips, borders, text, and highlights switch correctly inside the container.

## Deterministic Helpers

Use helper scripts for PR facts, source retrieval, syntax-highlighted excerpts, and validation. The LLM should choose the recap story, prose, diagrams, excerpt ranges, focused lines, and review notes; scripts should own deterministic data collection and rendering.

Before writing or regenerating a recap, ask the helpers for their LLM-oriented instructions:

```bash
node scripts/visual-recaps/collect-pr.mjs --llms
node scripts/visual-recaps/fetch-source.mjs --llms
node scripts/visual-recaps/render-code-excerpts.mjs --llms
node scripts/visual-recaps/validate-recap.mjs --llms
```

The default code-excerpt flow is:

```bash
node scripts/visual-recaps/collect-pr.mjs --repo <owner>/<repo> --pr <number> --out /tmp/recap-pr.json
node scripts/visual-recaps/fetch-source.mjs --pr-json /tmp/recap-pr.json --files <comma-separated-files> --out /tmp/source-manifest.json
node scripts/visual-recaps/render-code-excerpts.mjs --plan /tmp/excerpt-plan.json --source-manifest /tmp/source-manifest.json --out /tmp/excerpts.html
node scripts/visual-recaps/validate-recap.mjs --html visual-recaps/<slug>/index.html
```

`fetch-source.mjs` must fetch raw files by PR head SHA through `gh api`; do not check out or mutate a user's local copy of the target repo. `render-code-excerpts.mjs` tokenizes the entire cached source file with Shiki before extracting requested ranges, so snippets get syntax context without relying on manual span markup. Do not hand-author syntax spans such as `<span class="k">`; paste the generated code-card fragments instead.

## User-Facing Copy Rules

Recaps are artifacts for engineers and product reviewers, not explanations of the prompt that produced them. Write every visible sentence as if it was authored directly for the page.

Do:

- use product- and code-facing language: "This layer defines...", "The key trade-off is...", "Check that...";
- explain why a contract, adapter, UI state, migration, or test matters;
- label annotated code notes with concrete words such as `Why it matters`, `Check`, `Risk`, or `Follow-up`;
- date the page with a neutral publication date such as `3 July 2026` or `Published 3 July 2026`.

Do not expose process or prompt language in page copy:

- no "the PR is easier to review if...", "good recap", "review utility", "review focus", "load-bearing review", "prompt", "generated by", "UI noise", or "trivia from the diff";
- no sentences that describe how the recap should work instead of describing the change itself;
- no footer text naming the agent, model, prompt, local CLI commands, or generation workflow unless the source itself is relevant to the change.

Before finishing, search the generated HTML and `visual-recaps/index.json` for prompt-shaped terms:

```bash
rg -n "easier to review|review focus|good recap|generated by|prompt|UI noise|trivia from the diff|load-bearing review" visual-recaps/<slug>/index.html visual-recaps/index.json
```

## Single-PR Recap Prompt

Use this prompt shape for one PR:

```text
Create a Lawhive visual recap for this single PR.

Scope mode: single-pr
Output path: visual-recaps/<topic>-YYYY-MM-DD/index.html

Read the actual PR diff and changed files. Produce a self-contained HTML recap that follows AGENTS.md and docs/content-types/visual-recaps.md.

Focus the recap on review utility:
- what changed and why;
- the touched product, API, schema, permission, and architecture surfaces;
- a grouped file map;
- UI before/after or state wireframes if rendered UI changed;
- contract or data-model summaries when relevant;
- 3-8 annotated key-change excerpts from load-bearing files;
- reviewer risks, tests to inspect, rollout concerns, and follow-ups.

Keep it concise. Do not paste the full diff. Prefer excerpts under roughly 150 lines per key-change section.

Copy guard:
- Write user-facing prose as product documentation, not as instructions to the reviewer or a trace of this prompt.
- Do not include phrases such as "review focus", "good recap", "generated by", "prompt", "UI noise", or "easier to review".
- Use neutral labels such as "Why it matters", "Check", "Risk", and "Published".
```

## Stack Recap Prompt

Use this prompt shape for a whole Graphite stack:

```text
Create a Lawhive visual recap for this complete Graphite stack.

Scope mode: stack
Output path: visual-recaps/<topic>-YYYY-MM-DD/index.html

Use Graphite CLI and the PRs' actual diffs to understand stack order, dependency shape, and cumulative behavior. Produce a self-contained HTML recap that follows AGENTS.md and docs/content-types/visual-recaps.md.

Make the recap longer and more guided than a single-PR recap. Explain:
- the stack thesis: what the whole stack accomplishes;
- the PR sequence: why the PRs are ordered this way;
- the cumulative behavior change after the whole stack lands;
- which PRs can be reviewed independently and which require cross-PR context;
- dependency and contract changes across the stack;
- UI or state transitions that only make sense across multiple PRs;
- risk accumulation from interactions between PRs;
- a PR-by-PR lane or timeline;
- annotated key-change excerpts across the stack, grouped by theme or PR.

Do not produce several unrelated single-PR summaries pasted together. The recap should explain the arc of the work.

Copy guard:
- Write user-facing prose as product documentation, not as instructions to the reviewer or a trace of this prompt.
- Do not include phrases such as "review focus", "good recap", "generated by", "prompt", "UI noise", or "easier to review".
- Use neutral labels such as "Why it matters", "Check", "Risk", and "Published".
```

## Stack-Subset Recap Prompt

Use this prompt shape for selected PRs within a stack:

```text
Create a Lawhive visual recap for a subset of PRs in this Graphite stack.

Scope mode: stack-subset
Included PRs: <list>
Excluded PRs: <list, if known>
Output path: visual-recaps/<topic>-YYYY-MM-DD/index.html

Use Graphite CLI and the selected PR diffs to understand the subset's position in the larger stack. Produce a self-contained HTML recap that follows AGENTS.md and docs/content-types/visual-recaps.md.

Make the scope boundary explicit:
- what this subset covers;
- what nearby stack PRs are intentionally excluded;
- what context the reviewer still needs from excluded PRs;
- how the selected PRs depend on each other;
- how behavior changes across the selected PRs.

Use the longer guided stack format, but keep the review map focused on the included PRs.

Copy guard:
- Write user-facing prose as product documentation, not as instructions to the reviewer or a trace of this prompt.
- Do not include phrases such as "review focus", "good recap", "generated by", "prompt", "UI noise", or "easier to review".
- Use neutral labels such as "Why it matters", "Check", "Risk", and "Published".
```

## Budgets

Single-PR recap:

- 3-8 key-change excerpts.
- One file map.
- One UI visual section only when UI changed.
- One contract section only when contracts changed.

Stack or stack-subset recap:

- 5-12 key-change excerpts, grouped by PR or theme.
- PR-by-PR lane, stack timeline, or dependency diagram.
- More prose is allowed, but it must guide review order and cross-PR understanding.
- Include a "review independently / review together" section when the stack has separable slices.

## Quality Checks

Before finishing a recap:

- Serve the site locally with `python3 -m http.server 4173`.
- Open `/visual-recaps/` and the new recap URL.
- Verify root navigation links to the category.
- Run `node scripts/visual-recaps/validate-recap.mjs --html visual-recaps/<slug>/index.html`.
- Run `node scripts/build-index.mjs visual-recaps`.
- Confirm the generated page includes `meta name="description"` so the listing card is useful.
- Confirm the comments script has a unique stable `data-doc`.
- Search the generated HTML and `visual-recaps/index.json` for prompt/process leakage listed in "User-Facing Copy Rules".
- Check no customer names, secrets, tokens, or live credentials are present.
