{"id":"646c1496-5878-41d6-896c-0314f53b0d2a","slug":"deep-report","kind":"skill","name":"deep-report","summary":"Claude Code plugin that turns a research question into a claim-verified, deep-dive PDF.","owner":"Hook12aaa","repoUrl":"https://github.com/Hook12aaa/deep-report","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-05-20T08:22:35.000Z","addedAt":"2026-10-22T02:54:08.407Z","logoUrl":"https://avatars.githubusercontent.com/u/28310645?u=481ad089f7afeae5b50033766eff08d47c2b03c3&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","files-documents"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T10:14:22.360Z","sample":false,"url":"https://conduits.dev/tools/deep-report","language":"JavaScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# deep-report\n\nA Claude Code plugin that turns a research question into a claim-verified, deep-dive PDF — by spawning research agents, grounding every load-bearing fact against a fetched source, and rendering the document through a headless browser before a single byte of PDF is written.\n\n**Status:** 0.1.0 · MIT · requires Node 20+ and Graphviz `dot`.\n\n## Why this exists\n\nI have been generating research reports ad hoc with single-prompt write-ups for months. The output reads beautifully and lies confidently. Once it told me the LNER runs the London-to-Cambridge line — it does not; that is Great Northern. Single-pass write-ups produce fluent prose with hallucinated specifics: wrong operator, wrong date, wrong agency name. A reader cannot tell which sentences carry weight and which were invented.\n\nThe other failure was visuals. Asking the model to \"draw a diagram\" produces scattered mind-map layouts with overlapping lines that re-prompting will not fix. Asking for a PDF through a Python PDF library produces output where the padding has lost the will to live.\n\n`/deep-report` exists to refuse both. Every load-bearing claim sits in a ledger that the verifier fetches and confirms before synthesis begins. Every figure is restricted to one of four structured families — hierarchy, sequence, matrix, table — and every figure passes a deterministic measurement gate before it is inlined. The PDF is rendered from styled HTML through a headless browser. Nothing else.\n\n\n## Install\n\n```bash\n/plugin marketplace add hook12aaa/deep-report\n/plugin install deep-report@deep-report\n```\n\nIf you don't have GraphVis Install it!\n\n```bash\nbrew install graphviz\ncd skills/deep-report && npm install\n```\n\n## Prerequisites\n\n- **Node.js 20+.** Puppeteer needs it; `package.json` declares `engines.node >= 20`.\n- **Graphviz `dot` on PATH.** `brew install graphviz` on macOS, `apt install graphviz` on Debian. The hierarchy renderer shells out to `dot -Tsvg`.\n- **Puppeteer.** Installed via `npm install` inside `skills/deep-report/`. Bundles Chromium for Testing (~420 MB).\n\n## Triggers\n\n| Command | Use |\n|---|---|\n| `/deep-report` | The only entry point. Provide a topic, a voice anchor, and a depth mode. |\n\nThere is no auto-trigger on keyword phrases. The slash command is explicit so you do not accidentally start a half-hour pipeline on a passing remark.\n\n## How it works\n\nNine stages, in order. Each emits to disk so the next stage reads the previous one's artifact, not memory.\n\n```mermaid\nflowchart TB\n  A[Confirm topic, voice, depth] --> B[Decompose into components]\n  B --> C[Per-component research subagents]\n  C --> D[Extract load-bearing claims into ledger]\n  D --> E[Run claim verification sidecar]\n  E -->|every claim verified| F[Synthesise unified draft]\n  E -->|any claim unverified| X1[CLAIMS_UNVERIFIED]\n  F --> G[Spec figures via figure-spec-author]\n  G --> H[Render + measurement gate]\n  H -->|all pass| I[Build HTML, print to PDF]\n  H -->|any fail| G\n  I --> J[REPORT_SHIPPED]\n  A -->|topic too vague| X2[SCOPE_TOO_VAGUE]\n```\n\nThe figure stage is the part most people skip. It works like this:\n\n1. The spec-author subagent picks one of four families per figure, or refuses with a tagged reason. It never emits SVG, Mermaid, or DOT.\n2. `scripts/render-figure.js` dispatches by family — Graphviz `dot` for hierarchies with uniform-width nodes computed from the longest label; hand-rolled SVG for sequences; CSS Grid for matrices; semantic `<table>` for tables.\n3. `scripts/measure-figure.js` parses the rendered output and reports numbers — sibling-width spread, horizontal sibling-spacing spread, bounding-box overlap count, edge-endpoint snap distance, connector-length spread, no inline bolding in cells. A figure with any `pass: false` check is rejected.\n4. `scripts/build-pdf.js` assembles draft markdown plus measured-passed figures plus print CSS, then prints to PDF via Puppeteer after `document.fonts.ready`.\n5. `scripts/verify-pdf.js` runs post-render checks: figure-fit-content-width, WCAG AA text contrast, byte-equal determinism after metadata strip.\n\n## Verdicts\n\n| Verdict | Meaning |\n|---|---|\n| `REPORT_SHIPPED` | PDF rendered, every load-bearing claim is `verified`, every figure passed its measurement gate, the verifier returned pass. |\n| `CLAIMS_UNVERIFIED` | One or more load-bearing claims failed verification after the corrective pass. No PDF is shipped. |\n| `SCOPE_TOO_VAGUE` | The topic could not be narrowed into a researchable question at the confirmation step. |\n\nNo fourth verdict. No \"shipped with warnings\".\n\n## Repository layout\n\n```\n.\n├── .claude-plugin/\n│   ├── plugin.json                    plugin manifest\n│   └── marketplace.json               local marketplace stub\n├── CLAUDE.md                          plugin context\n├── README.md\n├── LICENSE                            MIT\n├── CHANGELOG.md\n├── hooks/\n│   ├── hooks.json                     SessionStart wiring\n│   ├── session-start                  bootstrap loader (exec)\n│   └── lib/emit-context.sh\n├── commands/\n│   └── deep-report.md                 /deep-report slash stub\n├── skills/\n│   ├── using-deep-report/SKILL.md     SessionStart bootstrap\n│   └── deep-report/\n│       ├── SKILL.md                   the authored skill\n│       ├── package.json               puppeteer dependency\n│       ├── schemas/\n│       │   └── figure-spec.schema.json\n│       ├── scripts/\n│       │   ├── render-figure.js       spec → inline SVG/HTML\n│       │   ├── measure-figure.js      deterministic quality gate\n│       │   ├── build-pdf.js           render + measure + print\n│       │   └── verify-pdf.js          post-render checks\n│       ├── assets/\n│       │   └── print.css              header-bold only, no cell bolding\n│       ├── agents/\n│       │   └── figure-spec-author.md  subagent prompt\n│       └── references/                voice, depth, verifier, layouts, render\n├── tests/\n│   ├── run-tests.sh\n│   └── hooks/test-session-start.sh\n└── docs/skill-cheat/skills-in-progress/deep-report/\n    ├── scope.{md,json}\n    ├── design.{md,json}\n    ├── design.md.sha256               immutable contract sidecar\n    └── evals/                         behavioural benchmark seeds\n```\n\n\n## The Key principles\n\n1. **Ground every load-bearing claim before synthesis.** Names, numbers, dates, operators, routes, percentages, identifiers — all live in the ledger, all carry a `verified` verdict before a sentence is written.\n2. **Refuse scattered figure layouts.** Four families only. Mind-map, radial, scatter, free-form — out.\n3. **Render PDF only through a real browser.** Python PDF libraries mishandle padding and spacing; their output is not repairable in-line.\n4. **Measure, do not eyeball.** The quality gate emits numbers and tolerances. No vision-LLM \"this looks fine\" pass.\n5. **No agent grades its own work.** The verifier sidecar runs in fresh context against fetched sources, not the research agent's memory.\n6. **Header rows bold, cell text not.** Bold in body cells adds no information when most cells are short labels. Cell bold is opt-in via a single `emphasis` flag on the spec.\n7. **One verdict, three values.** Reports either ship verified or do not ship.\n\n## Troubleshooting\n\n- **`/plugin install` says plugin not found** → `/plugin marketplace update deep-report`, then retry.\n- **Skills do not appear after install** → run `/reload-plugins`; check `/plugin` Errors tab.\n- **Hook does not fire** → `ls -la hooks/session-start` must show the executable bit; first line must be `#!/usr/bin/env bash`.\n- **`dot: command not found`** → install Graphviz (`brew install graphviz` / `apt install graphviz`).\n- **Puppeteer fails to launch Chromium** → `npx puppeteer browsers install chrome` inside `skills/deep-report/`.\n- **Edits to the local plugin do not show up** → `rm -rf ~/.claude/plugins/cache/deep-report` and reinstall, or develop with `claude --plugin-dir .`.\n- **A figure fails the measurement gate** → read the JSON report; the failing check names the exact tolerance and the measured number.\n\n## Inspirations\n\n- **OmniSVG (arXiv 2504.06263)** — documents coordinate hallucination as the dominant failure mode of LLM-generated vector graphics. Justifies the JSON-spec-only contract for the spec-author subagent. https://arxiv.org/html/2504.06263v1\n- **DiagrammerGPT (COLM 2024, arXiv 2310.12128)** — the two-pass planner/renderer pattern. The planner emits a spec; deterministic code draws it. https://arxiv.org/abs/2310.12128\n- **MermaidSeqBench (arXiv 2511.14967)** — six-dimension evaluator that confirms LLMs fail at Mermaid syntax often enough to put it on the renderer side, not the model side. https://arxiv.org/html/2511.14967v1\n\n## Contributing\n\nOpen invitation. If you have a better way to enforce sibling-width uniformity, ground a claim, or print HTML to PDF deterministically, send a PR — or open an issue with the numbers that prove it. The measurement gate is deliberately replaceable; swap the rules, keep the discipline.\n\n## Licence\n\nMIT. Use it. Fork it. Build on it. Attribution welcome, not required.\n"}