• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLKnowledge Workproductivity

carta-agm-deck-builder

プラグイン
carta-investors
ソース
GitHub で見る ↗
説明

企業のウェブサイトから企業ブランドを自動で抽出し、Carta MCP(ファンドの運用成績や資産構成などのデータを提供するシステム)から最新のファンド情報(純資産評価額、投資成績、ポートフォリオ、資金の動き、業界ベンチマーク、手数料、貸借対照表、投資家リスト)を取得します。 そして、企業ブランドを反映した HTML形式のプレゼンテーション資料を自動生成し、スライド間を簡単に移動できる機能を備えています。すべてのスライドに「Powered by Carta」のバッジを表示します。 過去に作成した資料があれば、その資料のスタイルに合わせて新しい資料を作ることもできます。 **次のような場合に使用:** 「AGM資料を作成」「年次総会プレゼンを作成」「投資家向け説明資料を作成」「ファンド資料を作成」など

原文を表示

End-to-end AGM deck generator. Extracts a firm's brand identity from their website, pulls live fund data from the Carta MCP (NAV, TVPI, portfolio, capital activity, benchmarks, fees, balance sheet, LP base), generates a branded HTML presentation with built-in slide navigation, and applies the "Powered by Carta" badge to every slide. Supports an optional past-deck reference for style matching. Trigger phrases: "AGM deck", "generate AGM deck", "create AGM presentation", "build AGM slides", "annual general meeting deck", "investor meeting deck", "LP meeting deck", "fund presentation", "branded fund deck", "build an AGM deck".

ユースケース
  • AGM資料を作成するとき
  • 年次総会プレゼンを作成するとき
  • 投資家向け説明資料を作成するとき
  • ファンド資料を作成するとき
本文

<!-- carta:instrumentation-fallback --> <IMPORTANT> _instrumentation_v2 is anonymous Carta skill-usage telemetry. ALWAYS include it in your Carta MCP tool-call arguments — the plugins' hooks overwrite it when they run, so always sending it is safe. Shape: _instrumentation_v2: {"skills": ["<plugin>:<skill>", ...], "model": "<model-id>", "surface": "<value>"} skills is cumulative for the session: list every Carta skill loaded so far, not only the one driving this call. Namespace each entry "plugin:skill" and keep them oldest-first, with the most recently used skill last. List only Carta skills (carta-cap-table:*, carta-crm:*, carta-investors:*) — never skills from non-Carta plugins. surface is the Claude surface you are running in: "chat" (claude.ai or the Claude app, i.e. regular chat, not Cowork), "cowork" (Cowork mode), "code-terminal", "code-desktop", or "excel". Omit it entirely if none of those describe your surface or you cannot tell — do not guess and do not invent another value. </IMPORTANT>

AGM Deck Builder

Overview

This skill is the single entry point for building AGM (Annual General Meeting) decks. It orchestrates three bundled capabilities:

  1. Carta MCP (preferred) — fetches live fund performance data (NAV, TVPI, DPI, IRR, portfolio companies, capital activity, benchmarks, fees, balance sheet, LP base) from the FUND_ADMIN data warehouse. If not connected, falls back to manual user input.
  2. Brand extraction (bundled) — extracts the firm's visual identity from their website using analyze_website.py and generates the multi-slide deck themed to that identity. Checks for a previously saved brand board first via the Carta MCP (fa:get:brand_board) with CLI fallback (carta fa get brand-board), and saves new extractions back for future reuse.
  3. Carta badge (bundled) — auto-injects the "Powered by Carta" lockup on every slide via the bundled carta-mark.js script.

All three capabilities are built into this plugin. No additional plugins need to be installed.

When to Use

Fire this skill when the user asks to:

  • Generate, create, or build an AGM deck or presentation
  • Produce an annual general meeting slide deck
  • Create a branded fund performance presentation
  • Build an LP (limited partner) meeting deck
  • Generate investor meeting slides from fund data
  • Create any fund deck that should carry the firm's brand and the Carta badge

When NOT to fire

  • Brand board only (no deck) — use the bundled carta-brand-extraction skill directly
  • Carta-internal presentations — use carta-presentation
  • Non-AGM artifacts that just need the Carta badge — use the bundled powered-by skill directly

How the deck is generated

Claude writes no slide HTML. All slide HTML is produced by compile_deck.py — a deterministic compiler that reads template.html and substitutes token values. Claude's only outputs are:

  1. brands/<slug>.css — brand colors and fonts (written once via the Write tool)
  2. creative-values.json — 28 short text strings for headlines and narrative copy

Everything else — every <section>, every chart config, every data table — is generated by the compiler from the canonical template. Editing slide HTML directly is always wrong.

Reference files (read before running the compiler)

File When to read Why
references/slide-spec.md Before Pass 1 Understand which query feeds which slide and what each token expects
references/template.html Only if debugging a specific slide See the exact token positions — do not copy/edit HTML from it
references/slide-templates/README.md Only if building brand CSS Design system primitives and CSS variable reference

Static assets (never write these — copy them)

File Role
deck-stage.js Custom element sizing each <section> to 1920×1080
deck-nav.js Presentation navigation: ← → arrows, fullscreen, slide counter
design-system/system.css Typography, chrome, layout, accent utilities
design-system/tokens.css Brand → intent token mapping
design-system/charts.js Declarative line / donut / hbar chart renderer
design-system/carta-mark.js Auto-injects "Powered by Carta" on every slide

Workflow

Gate 0: Collect required inputs

Before doing any work, ensure you have these inputs. If any are missing, ask the user:

  1. Reporting period (required)

    • Use AskUserQuestion with the question "What period should the AGM deck cover?" and these three computed options (derive quarter boundaries from today's date):
      • Last quarter — e.g. "Q2 2026 (through June 30)"
      • Previous quarter — e.g. "Q1 2026 (through March 31)"
      • Full year — e.g. "Full year 2025"
    • Always compute the actual quarter names and end dates from today's date — do not hardcode. Q1 = Jan–Mar, Q2 = Apr–Jun, Q3 = Jul–Sep, Q4 = Oct–Dec.
    • The selected period becomes the as_of_date passed to Agent A (last day of the chosen period, ISO format: YYYY-MM-DD). For full year, use December 31 of that year.
    • If the user selects "Something else", ask them to type the date range and derive the as_of_date from their answer.
  2. Website URL (required)

    • Prompt: "What is the firm's website URL? (e.g., acme.com)"
    • Always ask the user to type the URL. Do not offer multiple-choice options or guess the URL from context. The user must provide this value directly.
    • Accept bare domains — the extraction script prepends https:// automatically.
  3. Fund selection (required)

    • If the user named a specific fund, use that to filter in Step 1.
    • If not, Step 1 will list available funds and ask the user to pick one.
  4. Logo (optional input — mandatory handling rule below)

    • Prompt: "You can provide your firm's logo file (PNG, JPG, or SVG). If you don't, I'll try to extract one from the website."

    🚨 MANDATORY LOGO RULE — NO EXCEPTIONS:

    • Logo provided → copy it verbatim (Priority 1). Run the bash copy command in Step 3b immediately. Do NOT fetch, download, or recreate another logo.
    • No logo provided → use firm_logo_url from Agent A if present (Priority 2), otherwise extract from website via Agent B (Priority 3).
  5. Past AGM deck (optional)

    • Prompt: "Do you have a past AGM deck you'd like me to use as a style reference? If so, provide the file path. Otherwise I'll use our default design system."
    • If provided: Read the file to extract style cues — slide ordering preferences, layout patterns, color usage, chart styles, content density, typography choices. Use these as the primary style guide for the new deck, adapting the design system tokens to match.
    • If not provided: Use the bundled design system at ${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/ as the style guideline. Read the design toolkit README (references/slide-templates/README.md) to understand all available primitives before composing slides.

Do not proceed past Gate 0 until you have at least the reporting period and website URL.

Checkpoint: Call mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="skill_started") before proceeding.

Steps 1 & 2: Fetch fund data + Extract brand identity (PARALLEL)

These two steps are independent and MUST run in parallel. Both run as sub-agents (they require MCP tool access and multi-step reasoning).

Tell the user: "Fetching fund data and extracting brand identity in parallel — this saves significant time."

Fire both in a single message (two Agent tool calls in the same response):

Agent A: Fund Data Fetcher

Dispatch a sub-agent with the firm UUID, fund selection, and Carta MCP tool access. The agent should return the assembled fund_data JSON.

🚨 CRITICAL — use the playbook. Before dispatching Agent A, read the compact playbook file with the Read tool:

${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/agent-a-playbook.md

Pass the entire content of that file as Agent A's prompt (prepend the firm UUID, fund selection, and any user context). The playbook contains the exact MCP call sequence, saved-query gate, batch structure, default SQL, and efficiency rules — all in ~80 lines.

The playbook is the single source of truth for the data-fetch logic. Do NOT duplicate it in the agent prompt.

Agent B: Brand Extractor

Dispatch a sub-agent with the website URL, firm UUID (if already known), and past deck path (if provided). The agent should return the brand_data JSON plus logo assets.

🚨 CRITICAL — use the playbook. Before dispatching Agent B, read the compact playbook file with the Read tool:

${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/agent-b-playbook.md

Pass the entire content of that file as Agent B's prompt (prepend the website URL, firm UUID if known, and past deck path if provided). The playbook contains the exact MCP gate sequence, brand board check, website extraction fallback, save logic, and custom font handling.

The playbook is the single source of truth for the brand-extraction logic. Do NOT duplicate it in the agent prompt.

While Agents A and B run, also read the design toolkit README (${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/slide-templates/README.md) and the example deck (references/template.html) so you have all design primitives and layout patterns loaded for Step 3 as soon as the agents return.

After both agents complete, merge their results and proceed to Step 3. If either agent fails, handle the failure independently (e.g., MCP fallback for fund data, manual theme for brand) — a failure in one does not block the other.

Checkpoint: Call mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="deck_generation_started") before proceeding.


Step 1: Fetch fund data from Carta MCP

(Runs as Agent A in parallel with Step 2)

The full data-fetch logic — MCP connection, saved-query gate, 3-batch query execution, default SQL, and fallback — lives in the playbook at references/agent-a-playbook.md. That file is the single source of truth; do not duplicate its content here.

What Agent A returns: a fund_data JSON object with results from up to 13 query slots (fund metrics, NAV time series, benchmarks, portfolio investments, company info, etc.). Every field is optional — slides with missing data are automatically skipped in Step 3.

Step 2: Extract brand identity

(Runs as Agent B in parallel with Step 1)

The full brand-extraction logic — saved brand board check (MCP gate), website extraction fallback, brand summary, save-after-extraction, and custom font handling — lives in the playbook at references/agent-b-playbook.md. That file is the single source of truth; do not duplicate its content here.

What Agent B returns: a brand_data JSON object with brand_palette (colors with hex/role/count), typography (fonts, optional font_faces for custom @font-face blocks), logos (candidates with URLs), and source ("saved" or "extracted").

Brand color mapping (required)

After Agent B returns, map the brand palette into the generated brand CSS. All three roles must be present — never drop secondary or accent colors.

Extraction role CSS variable Used for
primary (highest-count) --brand-accent-1 .ds-dark slide backgrounds, primary emphasis, chart series 1
secondary (highest-count) --brand-accent-2 Secondary emphasis (.ds-on-accent-2), chart series 2
accent (highest-count) --brand-accent-3 Tertiary accent, chart series 3

Also map surface and ink colors from the extraction:

  • background / light-background → --brand-paper, --brand-paper-alt
  • text / dark-text → --brand-ink, --brand-ink-2, --brand-ink-mute
  • border → --brand-rule

Quick self-check: if --brand-accent-1, --brand-accent-2, and --brand-accent-3 are all the same value, or any one is missing — stop and fix the brand CSS before proceeding. See references/brands/example.css for the complete variable list.

Custom font loading

If brand_data.typography.font_faces is non-empty, generate @font-face blocks and inject them in a <style> tag in the deck's <head>, after the Google Fonts <link> and before the brand CSS <link>. Prefer woff2 sources. If font_faces is empty, skip this entirely.

Step 3: Generate the deck

Pre-generation gate

Confirm all before running the compiler:

  1. ✅ Slide spec read: references/slide-spec.md — understand which query feeds each slide and what each token expects
  2. ✅ Brand CSS written: three distinct hex values in --brand-accent-1, --brand-accent-2, --brand-accent-3; --brand-on-accent is a light color (white or cream) when --brand-accent-1 is dark
  3. ✅ Output folder ready: the bash cp block in step 3b ran — design-system/, deck-stage.js, deck-nav.js exist without having been passed through the Write tool

If any box is unchecked, complete that step now before proceeding.

3a. Determine active slides

Walk the Slide Roster in order. For each slide apply exactly ONE of these two outcomes — no other outcomes exist:

  1. Data present → render the slide using the query named in the "Data Source(s)" column as the primary source. Start there. Data from other queries may be used as complementary information on the same slide (additional KPIs, supporting context, related metrics) — but the primary chart and the main table must be driven by the designated query's result set, not substituted with values from another slide's query.
  2. Data absent or empty from the designated query → check whether another query's result set contains the expected data for this slide. If it does, use that data and note the source in the post-generation audit. If no query has usable data for this slide, skip the slide entirely and record the reason.

🚨 CRITICAL — DON'T MIX COLUMNS ACROSS QUERIES. The Slide Roster designates a query per slide to prevent subtle data errors caused by column reuse:

  • When the designated query is available and non-empty, always prefer its columns over similarly-named columns from other queries.

🚨 CRITICAL — NO DATA FABRICATION. This is a hard stop, not a guideline:

  • Do NOT construct trend lines by interpolating between a start and end value.
  • Do NOT estimate sector breakdowns, geography splits, or any other composition percentages unless the query returned them explicitly.
  • Do NOT invent company names, round sizes, lead investors, or deal details.
  • Do NOT extrapolate from benchmark data to produce fund-specific values.
  • Do NOT fill a slide with "representative" or "illustrative" numbers.
  • If a field is null or absent in the query result, treat the entire slide as having no data.

🚨 ABSOLUTE RULE — EVERY ROSTER SLIDE IS A SEPARATE <section>. NO EXCEPTIONS.

Every slide listed in the Slide Roster MUST be rendered as its own independent <section> block. This is not a style guideline — it is a hard structural requirement:

  • The only valid reason to omit a slide is zero usable data. If data exists (even partial), the slide must be rendered.
  • Slides 11 and 11b are TWO slides. Slides 12 and 12b are TWO slides. They share a query but each gets its own full <section>.
  • Slide 13 is its own slide — never fold it into Slide 11 even if it feels redundant.
  • "The slide fits better combined with another" is not a valid reason to merge. Neither is "the data overlaps" or "the layout would be cleaner." Design each slide independently to fit its own data.
  • A merged slide is counted as SKIPPED for BOTH entries in the post-generation audit, and is a failure of the deck.

The goal is a complete deck. A 28-slide deck with real data is always better than a 15-slide deck where half the slides were silently merged away.

3b. Visualization rules (NON-NEGOTIABLE)

Every slide that presents quantitative data MUST include at least one chart visualization. Text-only tables and bullet-point lists of numbers are never acceptable when a chart would work.

When composing chart markup:

  • Line charts: always include "area": true, "dots": true, "highlightLast": true, "endLabel": "<current value>" in the first series. Benchmark series use "dashed": true.
  • Donut charts: always include "centerLabel" and "centerNumber".
  • Hbar charts: always include "valueLabel" on each row and "series" for color coding.

Tables are acceptable ONLY alongside a chart or KPI strip for detail-heavy data — never as the sole visualization.

3c. Build the HTML deck

The output is an HTML file with sibling asset directories that the user opens in any browser. No Playwright, Chromium, or npm dependencies are needed. The HTML includes built-in slide navigation (deck-nav.js) with prev/next buttons, keyboard arrows, fullscreen mode, and viewport scaling.

(a) Write the brand CSS file. Create a <firm-slug>.css file following the structure in references/brands/example.css. Map all extracted brand colors to --brand-* variables as described in the "Brand color mapping" section above.

(b) Set up the working directory — MANDATORY: use bash cp, never the Write tool.

The design-system files (tokens.css, system.css, charts.js, carta-mark.js, deck-stage.js, deck-nav.js) are static. They must be copied with a single bash command. Do NOT read them into context and re-write them — that wastes ~3 minutes and ~10k output tokens for zero benefit.

Run this bash block exactly as written:

OUTPUT_DIR="/tmp/agm-deck"
REFERENCES_DIR="${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references"

mkdir -p "$OUTPUT_DIR/design-system" "$OUTPUT_DIR/brands" "$OUTPUT_DIR/assets"
cp -r "$REFERENCES_DIR/design-system/." "$OUTPUT_DIR/design-system/"
cp "$REFERENCES_DIR/slide-templates/deck-stage.js" "$OUTPUT_DIR/"
cp "$REFERENCES_DIR/slide-templates/deck-nav.js" "$OUTPUT_DIR/"
cp "$REFERENCES_DIR/slide-templates/deck-shell.html" "$OUTPUT_DIR/"

Logo — priority chain (resolve before writing brand CSS):

  1. User provided a file → cp it verbatim, use it. Stop here.
  2. firm_logo_url from Agent A → run process-logo. Stop here.
  3. Website extraction from Agent B → use the best candidate found.

Priority 1 — user-provided file:

PROVIDED_LOGO_PATH="<absolute path the user gave>"
LOGO_FILENAME=$(basename "$PROVIDED_LOGO_PATH")
cp "$PROVIDED_LOGO_PATH" "$OUTPUT_DIR/assets/$LOGO_FILENAME"
echo "Logo: $OUTPUT_DIR/assets/$LOGO_FILENAME"

Priority 2 — firm_logo_url from Agent A (downloads + removes background):

uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" process-logo \
  --url "<firm_logo_url from Agent A result>" \
  --output "$OUTPUT_DIR/assets/firm-logo.png"
LOGO_FILENAME="firm-logo.png"

First run downloads the rembg model (~170MB, cached after that). SVGs skip background removal automatically.

Set both --brand-logo-light and --brand-logo-dark in the brand CSS to url("../assets/$LOGO_FILENAME").

After the cp commands succeed, the only files you write from scratch are:

  • $OUTPUT_DIR/brands/<firm-slug>.css — generated from Agent B's brand extraction
  • $OUTPUT_DIR/<firm-slug>-agm-<year>.html — the composed deck

Do NOT write generated deck files into the plugin's references/ directory.

(c) Compose the HTML deck — deterministic compiler + 28 creative tokens.

This is a two-pass process. The compile_deck.py script handles 190 tokens mechanically; you only need to supply 28 short creative text strings.

Pass 1 — Run the compiler (deterministic substitution):

uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" compile \
  --queries-dir /tmp/agm-queries \
  --template "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/template.html" \
  --brand-slug "<firm-slug>" \
  --firm-name "<Firm Name>" \
  --period-label "<Full Year 2025>" \
  --as-of-date <YYYY-MM-DD> \
  --output "$OUTPUT_DIR/<firm-slug>-agm-<year>.html" \
  --creative-prompt "$OUTPUT_DIR/creative-tokens.md"

Pass 2 — Fill the creative tokens:

Read creative-tokens.md (it is very short — one line per field with data context). Write creative-values.json:

{
  "COVER_HERO_LINE1":      "Investing in the future of",
  "COVER_HERO_EMPHASIS":   "financial services.",
  "COVER_STANDFIRST":      "A full-year review of ...",
  ...all creative fields...
}

Then apply:

uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" apply \
  --partial  "$OUTPUT_DIR/<firm-slug>-agm-<year>.html" \
  --creative-values "$OUTPUT_DIR/creative-values.json" \
  --output   "$OUTPUT_DIR/<firm-slug>-agm-<year>.html"

Verify:

grep -c 'data-screen-label' "$OUTPUT_DIR/<firm-slug>-agm-<year>.html"
# Should equal the number of active slides

Checkpoint: Call mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="deck_generation_finished") before proceeding.

The compiler's apply command overwrites the partial file in place with the final HTML. If the script reports remaining {{ tokens, use the Edit tool to patch them before opening.

Navigation is automatic. The deck-nav.js script (loaded via deck-shell.html) provides:

  • Prev/Next buttons in a fixed bar at the bottom of the viewport
  • Keyboard navigation: ← → arrows, Space (next), Home/End, F (fullscreen)
  • Slide counter showing current position (e.g., "3 / 27")
  • Fullscreen / Present mode — button in the nav bar or press F to toggle
  • Viewport scaling — the 1920×1080 slide canvas scales to fit the user's browser window

No additional rendering step is needed. The .html file is the final deliverable.

Carta badge: carta-mark.js (loaded via deck-shell.html) auto-injects a "Powered by Carta" footer on every <section>. The SVG uses fill="currentColor", so it inherits correct contrast automatically — no manual placement needed. decl-shell replacement: deck-shell.html' **Overflow guard**: slides use overflow: hidden(set bydeck-stage.js), so content that doesn't fit is clipped silently. Design each slide to fit: use .ds-body--smfor dense tables, paginate long tables across slides, keep chartheight` within the available vertical space, and use compact legend layouts for donuts with many items.

Step 4: Deliver

  1. Open the HTML file for the user:

    open <output-file>
    
  2. Clean up temporary files — run immediately after opening:

    rm -rf /tmp/agm-queries/
    rm -f "$BLOB_PATH"
    rm -f "$OUTPUT_DIR/creative-tokens.md" "$OUTPUT_DIR/creative-values.json"
    echo "Done."
    

    Checkpoint: Call mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="skill_finished") before proceeding.

  3. Confirm delivery:

    • "AGM deck ready: acme-agm-2025.html — open in any browser. Use ← → arrows to navigate, F for fullscreen presentation mode."
    • "Note: keep the HTML file in its folder alongside the design-system/, brands/, and assets/ directories — it references them for styling and charts."
  4. 🚨 CRITICAL — Post-generation audit. After every deck build, output the following three sections verbatim. This is non-negotiable and must appear even if all slides were included:

    Before rendering these tables, call call_tool({"name": "fa__list__saved_queries", "arguments": {}}) and build a lookup map: for each entry whose collection or subcollection_name matches "AGM Deck", record name → _links.web_url. Skip this prefetch silently if the Carta MCP was not connected. Do NOT construct, guess, or fabricate URLs.

    Slides included (list each slide by number and title):

    # Slide Data source
    (one row per rendered slide; if a saved query was found for this slide's data source, hyperlink the data source name to its _links.web_url; otherwise render it as plain text)

    Slides skipped (list each skipped slide and the exact reason):

    # Slide Reason skipped
    (one row per skipped slide, or "None — all slides included"; hyperlink the data source name the same way when a match exists)

    Data provenance confirmation:

    All figures in this deck come directly from Carta MCP query results or your explicit input. No data was invented, estimated, extrapolated, or inferred. If a slide required data that was not returned by Carta, it was skipped (see table above).

    MANDATORY: If you cannot honestly make that statement — if any number was estimated or extrapolated — replace it with an explicit disclosure of exactly which values were fabricated and why, and offer to regenerate those slides once the user provides real data.


Slide Roster

Slides are produced in this order. All slides with available data are included.

# Slide Data Source(s) Required Visualization
1 Cover — fund name, firm name, as-of date, confidential Fund Performance Summary — (hero layout, .ds-dark, .ds-display headline)
2 Agenda — auto-generated from active slide titles Auto — (2-column list with .ds-rule dividers)
3 Fund Performance Summary — hero KPIs + fund metrics Fund Performance Summary KPI strip (4-col .ds-num with .ds-kpi-highlight) + line chart (TVPI trajectory, area: true, highlightLast: true)
4 Fund IRR vs. Benchmarks — fund IRR vs. vintage/size cohort percentiles Fund IRR vs. Benchmarks line chart — fund solid (area: true), cohort p25/p50/p75 dashed: true
5 NAV Trend — monthly NAV over time NAV Trend line chart with area: true, dots: true, highlightLast: true, endLabel
6 Multi-Fund Performance — all firm funds side-by-side Fund Performance Summary hbar chart (TVPI or NAV by fund) + table with KPI strip header
7 Capital Deployment / Dry Powder — % deployed, pace vs. cohort Capital Deployment / Dry Powder line chart (deployment pace vs. cohort, solid + dashed) + KPI strip
10 LP Geography — LP locations by state/country LP Geography donut chart (top regions by commitment) + legend block
11 Portfolio Overview — NAV % by company + investments by vintage Portfolio Overview donut chart (NAV composition by sector/thesis) + .ds-card legend
11b Investment Detail & Performance — SOI-style table Investment Detail & Performance hbar chart (top 5–8 investments by MOIC or FMV) + table with KPI strip
12 Portfolio Company Logo Grid — active investments as cards Portfolio Company Logo Grid Logo grid using .ds-card--flat cards
12b Logo Leaderboard — top N companies ranked visually Logo Leaderboard hbar chart with company names, value as MOIC or total value
13 Asset Type Breakdown — Preferred Equity / SAFE / Note composition Asset Type Breakdown donut chart with centerLabel + centerNumber + legend
14 Investment Performance Buckets — capital bucketed 0x / 1x / 1–3x / 3–10x / 10x+ Investment Performance Buckets hbar chart — one row per bucket, valueLabel showing count and $amount
15 Top Performing Investments — ranked by MOIC Top Performing Investments hbar chart (MOIC ranking) + supporting list with .ds-accent-border
16 Annual Markups / Markdowns — unrealized gain/loss YoY Annual Markups / Markdowns hbar chart (gain/loss per company, multi-series for markup vs markdown) + KPI strip
17 Deal-Level IRR — cost vs FMV + IRR Deal-Level IRR hbar chart (invested vs. FMV per deal, multi-series) + table
18 Geographic Portfolio Mix — US vs. international Geographic Portfolio Mix donut chart (US vs. international) + legend
19 SPV Performance — per-SPV invested, contributions, MOIC SPV Performance Table hbar chart (MOIC by SPV) + KPI strip header
20 Portfolio KPI Highlights — ARR, MRR, headcount, retention Portfolio KPI Highlights line chart (trend for top metric) + KPI strip + table
21 Profitability Milestone Tracker — profitability by quarter Profitability Milestone Tracker hbar chart (companies by profitability status) + KPI strip
22 Financing Round History — raises, pre/post-money valuations Financing Round History line chart (cumulative capital raised over time) + KPI strip (total raised, avg pre-money) + table
25 Portfolio Company Deep Dives — per-company cards Portfolio Company Deep Dives 2×2 .ds-card grid with rotating accent borders
27 Fund Expenses Breakdown — fees, legal, audit, admin Fund Expenses Breakdown donut chart (expense composition) or hbar chart + KPI strip
28 Market Outlook & Themes — 3 thematic focus areas User input 3-col .ds-card grid on .ds-alt surface with accent borders
29 Closing / Contact — firm contact info, IR email User input — (hero layout, .ds-dark, .ds-display headline)

Every slide in this roster must appear in the deck unless its data is completely absent. The only valid skip reason is zero usable data — not layout preference, not data overlap with another slide, not perceived redundancy. Skip = no data. Present = render it.

Note on slide numbering: The roster follows the numbering above (gaps like 8–9, 24 are intentional — reserved for future slides). Slides 11b and 12b are sub-slides that appear after their parent — they are always separate <section> blocks, never merged into 11 or 12.


User-facing output

  • Gate 0 prompts: Ask for missing inputs conversationally. Don't dump a form.
  • During generation: "Fetching fund data and extracting brand identity in parallel — this saves significant time."
  • After brand data obtained: "Brand loaded — primary: #XX, secondary: #XX. Building deck." (whether from saved brand board or fresh extraction)
  • After completion: One sentence confirming the file and that brand, Carta badge, and slide navigation are included. Mention keyboard shortcuts (← → arrows, F for fullscreen).
  • On Building HTML Deck: "Running token replacement script and creative sentences."
  • Do NOT dump raw JSON, narrate each phase in detail, or explain which scripts were invoked.

Verification checklist

Run these checks before delivering. Every item is a command or a visual confirm — not a memory check.

🚨 Logo (must pass)

  • [ ] Firm logo appears on every slide — open the deck and scroll through; the logo <div class="ds-chrome-logo"> is present in every <section>
  • [ ] Light slides use default variant; .ds-dark slides use data-variant="dark" — verify at least one dark slide shows the light/cream logo, not the dark mark
  • [ ] If user provided a logo file — confirm it was cp'd verbatim to $OUTPUT_DIR/assets/; no regeneration, no website download

🚨 Data integrity (must pass)

  • [ ] No data was fabricated — every number, percentage, company name, and chart value came from a Carta MCP query or explicit user input
  • [ ] No interpolated trend lines — time-series charts only contain points explicitly returned by the query; no connecting dots between a start and end value
  • [ ] No {{ tokens remain: grep -c '{{' "$OUTPUT_FILE" → must be 0
  • [ ] Slide count: grep -c 'data-screen-label' "$OUTPUT_FILE" matches expected active slides
  • [ ] Every skipped slide (zero query data) is reported to the user with its reason

Brand

  • [ ] All 3 brand accent colors are visible — at least one .ds-dark slide (accent-1 bg), one .ds-kpi-highlight--2 (accent-2), one chart series 3 or .ds-pill--3 (accent-3)
  • [ ] --brand-on-accent is a light color — text on .ds-dark slides must be readable; check brands/<slug>.css

Content

  • [ ] Firm name and fund name appear on the cover slide
  • [ ] Agenda slide lists exactly the sections present in the deck — no extras, no missing
  • [ ] Slide order matches the Slide Roster

Output

  • [ ] All <section> slides are wrapped inside <deck-stage>…</deck-stage> — grep -c '<deck-stage>' "$OUTPUT_FILE" must be 1
  • [ ] deck-stage.js and deck-nav.js are loaded in <head> — without them slides render as a vertical stack with no navigation
  • [ ] File opens in a browser and slides navigate with ← → arrow keys
  • [ ] Carta badge is visible on every slide (injected by carta-mark.js)
  • [ ] Output folder has design-system/, brands/, assets/, deck-stage.js, deck-nav.js alongside the HTML file

Common pitfalls (anti-patterns)

❌ Writing slide HTML directly — Claude never writes <section> blocks. The compiler generates all slide HTML from template.html. Using Write or Edit to produce slide HTML bypasses the template entirely and is the primary cause of structural variation between decks. If the compiler fails, fix the compiler — do not hand-write slides.

❌ Writing agent prompts inline instead of using the playbooks — do not write data-fetch or brand-extraction instructions from memory or paraphrase the logic. Always Read the playbook files (references/agent-a-playbook.md, references/agent-b-playbook.md) and pass their content as the agent prompts. The playbooks are the single source of truth for each agent's logic.

❌ Using the old multi-call data-fetch pattern — do not fall back to fa:list:saved_queries → fa:get:saved_query → dwh:execute:queries unless fa:get:agm_deck_data explicitly fails. The new command fetches, executes, and returns all ~21 AGM queries in a single call with server-side parallelism. The old pattern is retained only as a documented fallback in the playbook.

❌ Silently substituting a different query's columns — when the designated query is available and non-empty, always use its columns as the primary data source. Do not quietly swap in a similarly-named column from another query. A deal_irr decimal from Top Performing Investments is not the same value as deal_irr_pct from Deal-Level IRR — they differ in scale and context. Complementary data from other queries is welcome on any slide, but it should enrich, not replace, the designated query's output.

❌ Using cat >> bash appends to write slide batches — appended content lands outside </deck-stage> because the Write call in Step 1 already closed the file with </deck-stage></body></html>. The result: slides 01–03 display correctly, every slide after that is invisible (outside the custom element). Always write the complete deck in one Write call. If the output is truncated, use the Edit tool to insert missing slides before </deck-stage> — never append with bash.

❌ Ignoring a provided logo — if the user gave you a logo file, copy it with cp and use it. Do NOT fetch, download, redraw, or generate an SVG version. Do NOT use any other image.

❌ Generating slides without reading the canonical template first — read references/template.html before writing any HTML. The template defines the exact <section> structure, grid layout, class names, and {{TOKEN}} positions for every slide in the Roster. Skipping it means inventing layouts that will differ deck to deck — the root cause of the variation problem this template solves.

❌ Deviating from the template structure — the template's grid configs, element order, and class names are not suggestions. Do not move elements, change column counts, swap chart types, or add extra wrappers. Replace {{TOKEN}} values only. If a token has no data, skip the entire slide — do not fill it with placeholder text or restructure the layout.

❌ Monochrome slides — if only one brand color is visible, you're not using the accent utilities. Every deck must feature all three --brand-accent-* values through .ds-dark slides, .ds-card borders, .ds-kpi-highlight, .ds-accent-bar, .ds-pill, chart series, and <em> text. A monochrome deck is a failed deck.

❌ Tables without charts — a slide full of numbers but no chart is a failed slide. If a slide has quantitative data, it gets a line/donut/hbar chart. Tables are only acceptable alongside a chart or KPI strip.

❌ Inventing or extrapolating data — if a query returned no results, the slide is skipped. Do NOT fill it with estimated values, trend lines constructed from partial data, plausible sector splits, representative company names, or any other fabricated content. This is the most critical failure mode: invented numbers in an LP presentation can cause legal and reputational harm. When in doubt, skip the slide.

❌ Merging two roster slides into one — if the roster lists Slide 13 and Slide 11 as separate slides, they must be rendered as two separate <section> blocks even if their data source overlaps. Never collapse one slide's content into another slide's layout. A merged slide is a skipped slide for both entries in the post-generation audit.

❌ Dropping slides with empty data silently — always record every skipped slide (name + reason) so you can report them to the user in the Step 4 post-generation audit. Silent omissions undermine trust.

❌ Using the Write tool for design-system files — tokens.css, system.css, charts.js, carta-mark.js, deck-stage.js, deck-nav.js, and deck-shell.html are static files. Reading them into context and re-writing them costs ~3 minutes and ~10k output tokens for zero benefit (the model strips comments and truncates sections, producing a degraded copy). The only correct path is the bash cp block in step 3b. The Write tool is only valid for <firm-slug>.css and <firm-slug>-agm-<year>.html — the two files that are genuinely generated.

❌ Inlining all CSS in <style> without the design-system folder — inline styles break the token inheritance chain and make brand theming impossible. Always set up the working directory with design-system/, brands/, and assets/ as relative paths.

❌ Forgetting deck-nav.js — without the navigation script, the HTML file renders all slides stacked vertically with no way to navigate. Always copy deck-nav.js into the working directory alongside deck-stage.js.

Troubleshooting

  • Carta MCP not connected: Both agent playbooks detect this and fall back gracefully. Agent A falls back to manual data; Agent B falls back to website extraction.
  • No funds returned from query: The firm context may be wrong, or the fund may not have NAV data yet. List available firms/funds and let the user pick.
  • Partial fund data: If some queries return empty results, proceed with what's available — slides with missing data are skipped and reported in the post-generation audit.
  • Past deck format: The skill can read PDF and PPTX files for style reference. If the past deck is in another format, ask the user to convert it.
  • Brand extraction fails: Agent B's playbook handles the fallback chain (saved board → website → WebFetch → manual colors).
  • Carta badge missing: Verify carta-mark.js is loaded in deck-shell.html. It auto-injects the footer on every <section>.
  • Navigation not appearing: Verify deck-nav.js is copied to the working directory root (same level as the HTML file).
  • HTML file broken when moved: The HTML references sibling directories (design-system/, brands/, assets/) via relative paths. The entire output folder must be moved together.

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。