From recoup-deals
The dashboard is the agent's interactive deliverable. The report is the
How this skill is triggered — by the user, by Claude, or both
Slash command
/recoup-deals:recoup-deal-reportThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The dashboard is the agent's interactive deliverable. The report is the
scripts/_helpers.pyscripts/build-deal-readiness.pyscripts/run-deal-checks.pyscripts/validate-dashboard.pyscripts/validate-deal-workspace.pyscripts/validate-evidence-ledger.pyscripts/validate-findings-evidence.pyscripts/validate-normalized-ledger.pyscripts/validate-workspace-consistency.pytemplates/deal-workspace/assumptions.yamltemplates/deal-workspace/evidence-ledger.jsontemplates/deal-workspace/findings.jsontemplates/deal-workspace/memos/financing-pack.mdtemplates/deal-workspace/memos/ic-memo.mdtemplates/deal-workspace/memos/seller-cleanup-report.mdtemplates/deal-workspace/missing-files.mdThe dashboard is the agent's interactive deliverable. The report is the file the customer attaches to an email. Same trust contract, same story — different medium and a different consumption pattern. A reader who opens this PDF on their phone in a noisy boardroom should grasp the headline in 10 seconds and have the receipts on the next page.
/recoup-deal-start finishes, when the user wants to
share the deal externally.deals/{deal-id}/REPORT.pdfdeals/{deal-id}/reports/<package-type>.pdf — e.g.
reports/ic-memo.pdf, reports/seller-cleanup.pdf,
reports/financing-pack.pdf, reports/post-close-admin.pdf.You have full creative freedom on layout, sectioning, conversion path, typography, and depth. Use that freedom to fit the deal's story to a medium the recipient can scan, sign, and forward.
These elements must be visible on a printed page (not behind a tab, not in an appendix that gets dropped):
ready / review_needed / blocked). This page comes before
anything else.workpapers/recommendations.json (or restructured by the agent when
the deal calls for it). Concrete asks; concrete impact.Confidential. Print without these
and the reader has no provenance when they hand it to counsel.workpapers/valuation-summary.json.normalized/royalty-ledger.csv.findings/missing-files.md.assumptions.yaml.If a workpaper does not exist, render a one-line placeholder ("Data not yet computed — see findings/missing-files.md") rather than silently dropping the section.
The PDF goes to people outside the agent's session — IC, lender, counsel, broker. Every claim must be defensible.
The trust rules are identical to the dashboard's. Re-read the
recoup-deal-dashboard skill's "Trust contract" section before
authoring fresh PDF content.
In short:
$-figure must match a value in workpapers/*.json /
normalized/royalty-ledger.csv within 5%, ORdata-evidence="EV-NNN" (resolves to an
evidence-ledger.json entry), ORdata-derived="<reason>" (explains the
math the agent did on top of primary numbers).When the report is converted from DASHBOARD.html, the dashboard
validator has already passed and the trust contract is inherited.
No further validation needed for the same numbers.
When the report is authored as a separate print-styled HTML before conversion, run the dashboard validator against the print HTML first:
python3 scripts/validate-dashboard.py deals/{deal-id} \
--dashboard-path deals/{deal-id}/.report-source.html
If the validator doesn't support --dashboard-path, temporarily copy
the print HTML over DASHBOARD.html, validate, then move it back —
or simply embed the report content INSIDE the dashboard via a
@media print stylesheet so a single validated source serves both
purposes. Never skip validation when authoring fresh dollar-figures.
The report does not invent numbers. It pulls from the same source set the dashboard reads:
| Path | What's in it |
|---|---|
deals/{deal-id}/DASHBOARD.html | The validated interactive artifact. Convert this when possible. |
deals/{deal-id}/memos/ic-memo.md (or seller / financing / post-close memo) | The longer narrative for the report's body. |
deals/{deal-id}/assumptions.yaml | Deal name, workflow type, valuation date, currency, materiality thresholds. |
deals/{deal-id}/workpapers/valuation-summary.json | Normalized NPS/NLS, scenario brackets. |
deals/{deal-id}/workpapers/nps-bridge.json | Reported→normalized NPS waterfall. |
deals/{deal-id}/workpapers/nls-bridge.json | Reported→normalized NLS waterfall. |
deals/{deal-id}/workpapers/concentration-analysis.json | Top-N asset / provider / territory shares. |
deals/{deal-id}/workpapers/recommendations.json | "What you can do next." |
deals/{deal-id}/findings/findings.json | Every structured finding with severity and status. |
deals/{deal-id}/findings/missing-files.md | Open requests for the seller. |
deals/{deal-id}/evidence-ledger.json | Evidence entries cited via data-evidence. |
The dashboard's quality bar applies (hierarchy, restraint, typography, accessibility), plus these print-only rules:
page-break-before: always on <section> boundaries.You pick the conversion path. Suggested order of preference (use what works in the user's environment without forcing an install they don't need):
Works out of the box on any machine with Chrome / Chromium / Edge installed. Renders Chart.js, D3, Plotly, and modern CSS perfectly.
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--headless --disable-gpu --no-pdf-header-footer \
--print-to-pdf="deals/{deal-id}/REPORT.pdf" \
"file://$(pwd)/deals/{deal-id}/DASHBOARD.html"
# Linux
google-chrome --headless --disable-gpu --no-pdf-header-footer \
--print-to-pdf="deals/{deal-id}/REPORT.pdf" \
"file://$(pwd)/deals/{deal-id}/DASHBOARD.html"
Drawback: Chrome's headless PDF mode doesn't fully respect every
@page directive. If margins / page breaks come out wrong, jump to
Path B.
pip3 install playwright
python3 -m playwright install chromium
Then a small Python script (write it inline, optionally saving it as
render-report.py in this skill's scripts/ if the user wants to reuse it):
from playwright.sync_api import sync_playwright
from pathlib import Path
deal_dir = Path("deals/{deal-id}")
src = deal_dir / "DASHBOARD.html" # or .report-source.html
out = deal_dir / "REPORT.pdf"
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(src.absolute().as_uri())
page.emulate_media(media="print")
page.pdf(
path=str(out),
format="Letter",
margin={"top": "0.6in", "bottom": "0.6in",
"left": "0.5in", "right": "0.5in"},
print_background=True,
display_header_footer=True,
header_template="<div></div>",
footer_template=(
'<div style="font-size:9px;width:100%;'
'padding:0 0.5in;color:#666;display:flex;'
'justify-content:space-between;">'
'<span>{deal-id} · Confidential</span>'
'<span class="pageNumber"></span>/'
'<span class="totalPages"></span>'
"</div>"
),
)
browser.close()
pip3 install weasyprint
WeasyPrint does NOT execute JavaScript — Chart.js / D3 / Plotly won't
render. Only use this path if the report HTML's charts are
pre-rendered as inline SVG or PNG. Beautiful CSS print support
(@page, running headers, footnotes).
Use when you want a layout that doesn't map naturally to HTML — heavy typography, complex tables, or a deck-style report. Higher effort. Only reach for this when Paths A–C give a poor result.
This skill produces both the written package (the memo) and its
distributable form (the PDF). Before converting anything, make sure the
right memo exists under deals/{deal-id}/memos/. Pick the package that
matches the deal's workflow type:
| Package | Memo file | Template |
|---|---|---|
ic-memo (buy-side default) | memos/ic-memo.md | templates/deal-workspace/memos/ic-memo.md |
seller-cleanup | memos/seller-cleanup-report.md | templates/deal-workspace/memos/seller-cleanup-report.md |
financing-pack | memos/financing-pack.md | templates/deal-workspace/memos/financing-pack.md |
post-close-admin | memos/post-close-admin-plan.md | derive from the recoup-deal-analysis skill's post-close-admin playbook |
Rules for memo assembly:
memos/ if the memo does not
exist yet, then fill every section. Pull every material number from
the workpapers (workpapers/*.json) — never from prose memory.$-figure obeys the trust contract above — it matches a
workpaper value within 5%, or it cites an evidence-ledger.json
entry. No unsupported numbers.findings/findings.json are closed, accepted, or shown as open —
never silently dropped.The PDF is the same story formatted for distribution. Once the memo is ready, convert as below.
Confirm the deal workspace is ready. Read assumptions.yaml,
confirm the matching memo exists under memos/ (assemble it per the
section above if not), and confirm DASHBOARD.html exists and was
validated this session (or run
python3 scripts/validate-dashboard.py deals/{deal-id} first).
Without a validated dashboard, the report has no source of truth.
Decide the source HTML. Two viable choices:
deals/{deal-id}/.report-source.html and validate it the same
way the dashboard is validated. Alternatively, add a
@media print stylesheet inside DASHBOARD.html that
restructures the page for print, then convert the dashboard
itself.Pick a conversion path (A → B → C → D in order of preference).
For Path B you may need pip3 install playwright && python3 -m playwright install chromium first — ask the user before
installing globally if you're not sure.
Convert to deals/{deal-id}/REPORT.pdf. If the user requested
multiple flavors (IC, seller, financing, post-close), write each to
deals/{deal-id}/reports/<package-type>.pdf in addition to the
default REPORT.pdf.
Verify the output. At minimum:
pdftotext extract).Quick text-extract sanity check (if pdftotext from poppler is
installed):
pdftotext -layout deals/{deal-id}/REPORT.pdf - | head -50
Look for the deal name, "Executive Summary", and at least one
$-figure that matches the dashboard.
Print one line to the user: the file path, page count, and approximate size. Don't recap the whole deal — that's the report's job.
✅ Report exported.
File: deals/{deal-id}/REPORT.pdf
Pages: <n>
Size: <X.X MB>
Source: deals/{deal-id}/DASHBOARD.html (validated)
Converted: <Chrome headless | Playwright | WeasyPrint>
Open it locally to scan, then attach to the email.
The dashboard taught the agent how to render a deal's story. The report skill is the same story, formatted for someone who's reading it on a phone with no Wi-Fi.
npx claudepluginhub recoupable/skillsProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.