--- name: generate-qbr description: Generate a Quarterly Business Review (QBR) document for a specific partner using EULER MCP tools. Use this skill whenever the user mentions a QBR, quarterly review, partner business review, quarterly performance summary, or asks to "review", "summarize", or "report on" how a specific partner has been doing — even if they only describe the intent without using the term "QBR". --- # Generate QBR — Quarterly Business Review for a partner ## When to use this skill Invoke this skill when the user types any of: - "QBR for " - "Quarterly review of " - "Generate Q business review for " - "Make a quarterly summary for " - `/euler-for-partner-managers:generate-qbr` DO NOT invoke for: - Company-wide reviews (use `performance(action: 'company')` directly) - Customer-level QBRs (different audience, different metrics) - Non-partner accounts ## Inputs needed from user Before running, confirm with the user: ### 1. Which partner? - Accept either a partner name or a `partner_id`. - Resolution order: 1. Call `list_accounts` — if the user has an account with that partner (rare; user is usually customer-side), match `affiliate_company_name` (case-insensitive). 2. Otherwise call `partners(action: 'list', filter_name: '')` — this is the customer-admin path. Match against `"Partner name"` in the response (case-insensitive substring). - If multiple matches, list them with their `status` field and ask the user to pick. - If no match, tell the user the partner isn't visible in their account and offer to list all partners (`partners(action: 'list')` without filter, page through if needed). ### 2. (Optional) JBP target for the quarter - If the user offers a target (revenue or deal count for the quarter), capture it. Used for the **vs-target column** in the headline table and to compute attainment % in the TL;DR. - If not offered, do NOT ask — proceed without targets. The TL;DR narrative adapts (focuses on pipeline health and partner activation signals instead of attainment). - Future versions will fetch JBP targets from a dedicated MCP tool. ### 3. Which quarter? - Accept any of: `"Q1 2026"`, `"Q4 2025"`, explicit ISO dates, `"last quarter"`, `"this quarter"`. - Convert to `start_date` / `end_date` in **`YYYY-MM-DD`** format: - Q1 = Jan 1 – Mar 31 - Q2 = Apr 1 – Jun 30 - Q3 = Jul 1 – Sep 30 - Q4 = Oct 1 – Dec 31 - If `"last quarter"` or ambiguous, infer from today's date and **CONFIRM with the user before proceeding**. Never silently guess. > ⚠️ **Date format gotcha:** the `performance` tool's schema description says > "ISO 8601 UTC datetime (e.g. '2024-04-07T00:00:00.000Z')". Empirically > (validated 2026-05-25) that format is broken — the backend returns > corrupted years like "Nov 28, 4763". Use `YYYY-MM-DD` for ALL date > params across all tools. If a future MCP release fixes the parser, > revisit. ## Orchestration sequence Run these EULER MCP tools in order. Default to running them all for a standard QBR. Skip a step only if the user's framing explicitly excludes it (e.g. "QBR without commissions"). | # | Tool call | Provides | |---|-----------|----------| | 1 | `list_accounts` | Customer-side `name` for the QBR header (the customer hosting the partnership). | | 2 | `partners(action: 'list', filter_name: '')` | Resolves `partner_id` from a name. Skip if user provided `partner_id` directly. | | 3 | `performance(action: 'partner', partner_id, start_date, end_date)` | **Period-filtered** headline metrics: deal count, booking/billings revenue, win rate, sales cycle, ACV. | | 4 | `partner_artifacts(action: 'deals', partner_id, page: 1, limit: 20)` | **All-time** deals pipeline (NOT period-filtered — see disclaimer rule below). | | 5 | `commissions(action: 'partner', partner_id, start_date, end_date)` | Period-filtered commissions paid + breakdown. | | 6 | `referrals(action: 'for_partner', partner_id, page: 1, limit: 20)` | **All-time** referrals submitted by the partner (NOT period-filtered). | | 7 | `partner_artifacts(action: 'agreements', partner_id)` | Agreement list with `Status` + `Signed On`. No `expires_on` field available. | | 8 | `partner_artifacts(action: 'invoices', partner_id, page: 1, limit: 20)` | All-time invoices. Include only if non-empty. | | 9 | `influenced_sourced_deals(partner_id, start_date, end_date)` | Deal-attribution split (Sourced vs Influenced vs Sourced-and-Influenced). Critical for tier conversations — partners want credit for the deals they touched, not just the ones they originated. | | 10 | `partners(action: 'summary')` | Company-wide context for anchoring: total partner count, status distribution. Used in the TL;DR ("one of only N partners in "). | | 11 | `performance(action: 'partner', partner_id, prev_quarter_dates)` | Previous quarter for Q-over-Q deltas (see "Q-over-Q rules" below). | | 12 | `performance(action: 'partner', partner_id, quarter_-2/-3/-4_dates)` | Up to 4 additional historical quarters for quarter-over-quarter trend context (rendered as deltas in the hero `.fact-sub` / spotlight prose — the modern template has no sparklines). Skip if user explicitly asks for a fast/lite QBR. | ### Tool-by-tool response field paths The MCP backend returns inconsistent field names (Bubble-side quirks). The exact paths and serialization bugs per tool are documented in [`references/mcp-field-paths.md`](references/mcp-field-paths.md) — consult that file when extracting fields from a specific response. Key gotchas to keep in mind (the file has the full detail): - Some keys have spaces, lowercase first letters, or unicode noise (`"Deal name"`, `"agreement Name"`, `ïd`) - All numeric fields come back as strings - `referrals(for_partner)` has a JSON serialization bug (commas instead of colons in `result_per_page`) — parse loosely - `last_stage_change_date` on deals is a duration string, not a timestamp (see Rule 15) ### Error handling during orchestration - **`partner_not_in_consent`** → abort. Tell the user to disconnect + reconnect and include this partner in their consent selection. Do not generate a partial QBR. - **`backend_data_issue`** on `list_accounts` → continue with `partners(list)` for partner_id resolution; surface the `support_email` in a banner at the top of the output. - **`euler_session_expired` / `euler_user_token_missing`** → instruct the user to follow Claude's inline reconnect prompt, then retry. - **Any single tool returning empty data mid-sequence** → continue. The output format handles missing sections gracefully (see Rule 1). - **A tool errors mid-run** → continue with the remaining tools, then surface a banner at the top of the output listing which sections are incomplete and why. ## Product how-to questions (`euler_help`) If the user asks how EULER itself works or how to do something in the product — not about their own data — e.g. "how do I register a deal", "where do I find X in the portal", "how does onboarding work" — call `euler_help` with their question and answer briefly from its result. Do not guess about product behavior. This is a tangent to this skill's main job: answer in 1–3 sentences (no HTML report) and return to the task. ## Output format Render a **single self-contained HTML file** — no external CSS, no external fonts, no script tags. A partner manager should be able to open it in a browser, paste it into email, save as PDF, or share by link, all from the same artifact. The document is **executive-readable**: skimmed in 30 seconds, drilled into in 2 minutes. No internal field paths, no system terminology. ### How to produce the HTML 1. Read [`assets/styles.css`](assets/styles.css) and inline its full contents into a single `