---
name: html-report
description: Take all documentation, discoveries, and structured knowledge gathered in the current conversation and produce a self-contained HTML report (plus its Markdown source). Use when the user says "/html-report", asks to "generate a report", "write this up as a report", "save this session as a report", or wants a shareable artifact summarizing what was figured out in the session.
---

# html-report

Produce a report pair — **Markdown first** (canonical source), then **HTML rendered from it** (self-contained, single file, no external assets). Files are written side-by-side into the user's configured output directory.

## Step 0 — First-run setup (one time only)

Check for `~/.claude/html-report-config.json`.

- **If it exists**, read `output_dir` from it and use that for the rest of this run. Do not prompt.
- **If it does NOT exist**, ask the user ONCE, in one short sentence:
  > "First run — where should reports be written? (default: `./reports/` in your current directory)"

  Accept their answer. Acceptable forms:
  - Empty / "default" → use literal string `./reports` (resolved against cwd at write time, so reports land next to whatever project you're in)
  - Absolute path (e.g. `/Users/x/Documents/reports`) → use as-is
  - `~`-prefixed (e.g. `~/reports`) → expand `~` to `$HOME`

  Save the answer:
  ```bash
  mkdir -p ~/.claude
  printf '{"output_dir": "%s"}\n' "$CHOSEN" > ~/.claude/html-report-config.json
  ```

  Confirm in one sentence: "Saved. Reports will go to `<path>`. Re-run to change: `rm ~/.claude/html-report-config.json`."

Then proceed to Step 1. Create the resolved output dir with `mkdir -p` if it doesn't exist.

## Step 1 — Pick a filename

Base: `<YYYY-MM-DD>-<kebab-topic>` where:
- Date is today (system date).
- `<kebab-topic>` comes from `$ARGUMENTS` if provided, else inferred from the dominant topic of the session in 1–4 kebab words (e.g. `auth-migration-research`, `db-migration-tutorial`, `vendor-eval`).

If the resulting `<base>.md` already exists in the output dir, append `-2`, `-3`, etc. until unique.

Final paths:
- `MD="$OUTPUT_DIR/<base>.md"`
- `HTML="$OUTPUT_DIR/<base>.html"`

## Step 2 — Generate the Markdown (canonical source)

Write `$MD`. Required structure:

**Frontmatter:**
```yaml
---
title: <Human-readable title>
date: <YYYY-MM-DD today>
type: report
tags: [report, <other-relevant-tags>]
---
```

**Body:** all session content in rich Markdown. Use:
- Headings (`#`, `##`, `###`) — `##` defines top-level sections used by Step 3.
- Tables for schemas, configs, comparisons.
- Fenced code blocks with language tags (` ```go `, ` ```python `, ` ```bash `).
- Callouts using GitHub/Obsidian syntax: `> [!note]`, `> [!warning]`, `> [!tip]`, `> [!info]`, `> [!danger]`, `> [!success]`.
- Task lists: `- [ ]` / `- [x]` for open questions or follow-ups.
- Mermaid diagrams in ` ```mermaid ` fences.
- Inline emphasis (`**bold**`, `*italic*`, `` `code` ``).

No raw HTML inside the Markdown unless absolutely needed.

## Step 3 — Generate the HTML (skeleton + sequential per-section fills)

> **Why this is the way it is:** the most common failure mode is the agent stalling on a single huge `Write`. Writing the full HTML at once exceeds the output token cap (~20K tokens) and hangs. Fix: write a small skeleton once, then fill sections incrementally with ONE `Edit` per turn.
>
> If you catch yourself "designing" the layout, picking colors from a menu, or batching Edits "for speed" — STOP. That's the stuck-state path.

### 3.1 — Pick design in ONE sentence (no menus, no deliberation)

State your two choices in one plain sentence and move on. Examples:
- "Using teal palette, single-column layout."
- "Using amber palette, sidebar layout (16 sections)."

**Palette** (pick exactly one keyword): `teal` (research/data) · `amber` (RFC/decision) · `red-amber` (audit) · `green` (tutorial) · `neutral` (reference).

**Layout** (pick exactly one keyword):
- `single-column` — default. Max-width 900px, no sidebar, no scroll-spy.
- `sidebar` — ONLY if section count `N ≥ 12`. Static sidebar TOC, no scroll-spy JS.

Do not invent additional palettes, layouts, or "decorations" (back-to-top buttons, scroll-spy, SVG charts, etc.). **Content is the product, not styling.**

### 3.2 — Count sections (one command)

```bash
N=$(grep -c '^## ' "$MD")
echo "N=$N"
```

If `N > 25`, tell the user once: "Report has $N sections — HTML fill will take ~$N turns. Continuing." Then proceed without waiting.

### 3.3 — Write the skeleton (ONE Write, target 4–7 KB, hard cap 8 KB)

The skeleton must be a complete valid HTML file with these — and ONLY these — pieces:

1. `<!DOCTYPE html>`, `<html>`, `<head>` with one inline `<style>` block. CSS budget: ~2 KB. Include only:
   - Body font, base typography, max-width container (or sidebar grid if `layout=sidebar`).
   - `h1`/`h2`/`h3` styling.
   - `table` (striped + padding), `pre`/`code` styling, `pre.mermaid-source` styling.
   - 5 callout classes — `.callout-note` (blue), `.callout-tip` (green), `.callout-warning` (amber), `.callout-danger` (red), `.callout-info` (purple). Each: colored left border + tinted background.
   - `.tasks li::before` for task-list checkboxes.
2. Hero header: title (from frontmatter) and date as plain text.
3. Main container.
4. **Exactly N placeholder lines**, in order:
   ```html
   <!-- SECTION-0 --><!-- /SECTION-0 -->
   <!-- SECTION-1 --><!-- /SECTION-1 -->
   ...
   ```
5. Closing tags.

**FORBIDDEN in the skeleton:** `<script>` tags of any kind, IntersectionObserver / scroll-spy code, back-to-top buttons, sidebar TOC pre-populated with section titles, fancy responsive grids, `@media` queries beyond a single max-width fallback, any external CSS/JS link.

If your skeleton draft exceeds 8 KB, delete CSS rules until it fits.

### 3.4 — Fill sections (ONE Edit per turn, with checkpoint)

**HARD RULES — do not violate:**

1. **ONE `Edit` per response. Never two. Never parallel.** Sequential is the whole point. If you're tempted to batch 2-3 Edits "to save time," that IS the stuck state — stop and send one.
2. **Cap per Edit `new_string`: 3 KB.** If a section's rendered HTML would exceed 3 KB, render only the first H3 subsection and append an inner placeholder `<!-- SECTION-i.1 --><!-- /SECTION-i.1 -->` to fill next turn.
3. **After every Edit, run the checkpoint** (3.4.1) BEFORE doing anything else. Do not chain into the next section in the same turn.
4. **Keep text output to ≤ 1 short sentence per turn** ("Filled section 3."). No narration, no re-explaining the plan, no progress tables.

#### 3.4.1 — The checkpoint (run after EVERY Edit)

```bash
grep -c '<!-- SECTION-' "$HTML"
```

The number must decrement by exactly 1 after each successful Edit. If it does not, stop and inspect — do NOT keep sending Edits.

#### 3.4.2 — Per-section render loop

For each `i` from `0` to `N-1`, in its OWN turn:

1. Locate the `i`-th `## ` heading in the markdown; capture everything until the next `## ` or EOF.
2. Render to HTML following 3.5 (compact reference).
3. ONE `Edit`:
   - `old_string`: `<!-- SECTION-i --><!-- /SECTION-i -->` (literal, substitute `i`)
   - `new_string`: `<section id="sec-i"><h2>Heading text</h2>…rendered…</section>` (≤ 3 KB)
4. Run 3.4.1 checkpoint.
5. End the turn.

### 3.5 — Rendering reference (compact)

- **Tables** → `<table>` (CSS already handles striping + padding).
- **Code blocks** → `<pre><code class="lang-X">…</code></pre>`. **MUST** escape `<` `>` `&` to `&lt;` `&gt;` `&amp;`. NO syntax-highlighting library, NO regex tokenizer — CSS-only styling.
- **Callouts** `> [!type]` → `<div class="callout callout-type">…</div>`. Map: note→note, tip→tip, info→info, warning→warning, danger→danger, success→tip.
- **Mermaid** ` ```mermaid ` → `<pre class="mermaid-source">📊 Mermaid — paste into mermaid.live to render\n\n<ESCAPED source>\n</pre>`. Never try to render visually.
- **Task lists** `- [ ]` / `- [x]` → `<ul class="tasks"><li class="task-open">…</li><li class="task-done">…</li></ul>`.
- No raw Markdown (`**bold**`, `###`, etc.) in the HTML output — render everything.

### 3.6 — Recovery (if a previous run stalled)

Don't restart. Run:

```bash
grep -nE '<!-- SECTION-[0-9]+ -->' "$HTML"
```

Resume from the lowest remaining `i` using 3.4.2. The skeleton is already correct.

### 3.7 — Final verification

```bash
remaining=$(grep -c '<!-- SECTION-' "$HTML")
size=$(wc -c < "$HTML")
echo "remaining=$remaining size=$size"
```

`remaining` MUST be `0`. `size` should land in 20 000–200 000 bytes. If non-zero, return to 3.4.2 — do NOT rewrite the skeleton.

## Step 4 — Report back

Output to the user (concise):
- Markdown path
- HTML path
- One-line `open <html-path>` command they can paste

Do not include any other commentary unless the user asked questions.
