success-plan-canvas
$
npx mdskill add t0ddc3by/claude-for-customer-success/success-plan-canvasGenerates structured Customer Success Plan canvases for specific accounts and lifecycle stages
- Identifies and generates a structured success plan canvas based on account lifecycle stage (onboarding, expansion, renewal review).
- Deploys an OCV-aware system that reads Outcome & Value Catalog snapshot data to identify gaps and delivered outcomes.
- Decides the appropriate plan type for each account based on lifecycle stage and supports three types: initial onboarding, pre-expansion, and pre-renewal review.
- Delivers a standalone exportable Markdown artifact as the success plan canvas document.
SKILL.md
.github/skills/success-plan-canvasView on GitHub ↗
--- name: success-plan-canvas description: "Generates and refreshes structured Customer Success Plan canvas documents for a specific account and lifecycle stage. Supports three plan types: initial onboarding, pre-expansion, and pre-renewal review. OCV-aware: reads Outcome & Value Catalog snapshot data to surface gaps and delivered outcomes." version: "1.0.0" author: [email protected] tags: [csm, success-plan, canvas, customer-success] deployment_target: plugin --- # csm:success-plan-canvas [PROPOSED] ## Overview `csm:success-plan-canvas` generates structured Customer Success Plan canvas documents tied to a specific account and lifecycle stage. The canvas is saved as a standalone exportable Markdown artifact and serves as the upstream input to `csm:success-plan-progress-review`. Three plan types are supported, each producing a distinct document structure: - **`initial`** — New customer onboarding plan; all 7 CCSM-104 components present; labeled "Initial Success Plan" - **`expansion`** — Pre-expansion motion; labeled "Expansion Canvas" with explicit expansion framing; distinct from initial plan - **`renewal-refresh`** — Pre-renewal review; includes OCV gap analysis surfacing committed-but-not-delivered outcomes ## Use When - The organization uses the OCV (Outcome-to-Customer Value) system and a structured 7-component canvas format is required — if OCV is not in use, use `/csm:success-plan-builder` instead - A CSM needs to generate a structured success plan canvas for a specific account at a lifecycle stage (initial onboarding, pre-expansion, pre-renewal review) - An existing canvas needs to be refreshed with updated objectives, OCV data, or notes without generating a new dated artifact ## Do NOT Use For - Progress tracking or scorecard generation — use `csm:success-plan-progress-review` instead - Sending customer communications — use `csm:customer-comms` instead - CRM integration or external system writes - Multi-account batch generation - Modifying OCV files (this skill is read-only with respect to OCV data) ## Typical Activation "/csm:success-plan-canvas Acme Corp" (requires OCV system to be in use) "/csm:success-plan-canvas Acme Corp --update" "Create a success plan canvas for [account]" (OCV-aligned 7-component canvas format) "Update the canvas for [customer]" --- ## Operations ### Operation: `generate` Creates a new success plan canvas file for an account at a specified lifecycle stage. **Input fields:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `operation` | string | Yes | Must be `"generate"` | | `account_name` | string | Yes | Account name — used for file naming and canvas header | | `plan_type` | string | Yes | One of: `initial`, `expansion`, `renewal-refresh` | | `csm_name` | string | Yes | CSM who owns this plan | | `account_stage` | string | No | Customer lifecycle stage (e.g., Onboarding, Adoption, Expansion, Renewal) | | `ocv_snapshot` | object | No | Structured OCV data — list of outcomes: `{outcome_name, status, owner}` | | `key_objectives` | list | No | CSM-provided list of key objectives to feature in the canvas | | `notes` | string | No | Freeform CSM notes appended to canvas footer | **Auto-generated fields (set at generate; immutable thereafter):** - `plan_id`: `CANVAS-[ACCT]-[YYYYMMDD]` — ACCT = first 4 alpha chars of `account_name`, uppercased; non-alpha stripped - `created_at`: ISO datetime of generation - `created_by`: session user identity **safe_account derivation (used for file path only):** 1. Lowercase `account_name` 2. Replace all non-alphanumeric characters with `-` 3. Collapse consecutive hyphens to single hyphen 4. Trim to 30 characters maximum Examples: - `"Acme Corp"` → `acme-corp` - `"123 Widgets Inc."` → `123-widgets-inc-` (trimmed if over 30 chars) - `"TechCo Solutions LLC"` → `techco-solutions-llc` **Plan-type behavior:** | Plan Type | Document Label | Section Structure | OCV Role | |-----------|---------------|-------------------|----------| | `initial` | Initial Success Plan | Goals, Onboarding Milestones, Responsibilities, Success Metrics, Timelines, Risks and Assumptions, Communication Strategy, Next Steps | OCV outcomes listed informally if provided | | `expansion` | Expansion Canvas | Expansion Rationale, Current Outcomes, Expansion Opportunity, Proposed Outcomes, Responsibilities, Success Metrics, Risks and Assumptions, Communication Strategy, Next Steps | OCV outcomes mapped to expansion thesis | | `renewal-refresh` | Renewal-Refresh Plan | Renewal Context, OCV Gap Analysis, Delivered Outcomes, At-Risk Outcomes, Renewal Objectives, Responsibilities, Communication Strategy, Next Steps | OCV gap analysis required when `ocv_snapshot` provided | **Behavior:** - Derives `safe_account` from `account_name` for all filesystem path construction - `display_account` (original `account_name`) used only in document output - Creates `context/success-plan-[safe_account]-[YYYY-MM-DD].md` - If a canvas for the same account and date already exists, it is overwritten - Returns console summary: `plan_id`, file path, plan type, and account name **Output example (console summary):** ``` Canvas generated. plan_id: CANVAS-ACME-20260517 plan_type: initial account: Acme Corp file: context/success-plan-acme-corp-2026-05-17.md ``` --- ### Operation: `refresh` Updates an existing canvas in place without creating a new dated artifact. **Input fields:** | Field | Type | Required | Description | |-------|------|----------|-------------| | `operation` | string | Yes | Must be `"refresh"` | | `account_name` | string | Yes | Account name — used to locate the existing canvas file | | `canvas_date` | string | No | ISO date (YYYY-MM-DD) of canvas to refresh; defaults to most recent canvas for account | | `key_objectives` | list | No | Replacement objectives list (replaces prior objectives section) | | `ocv_snapshot` | object | No | Updated OCV data — replaces prior OCV section | | `notes` | string | No | Appended to Notes section (append-only; prior notes are preserved) | **Immutable fields — rejected if included in refresh payload:** | Field | Error response | |-------|---------------| | `plan_id` | `Immutable field error: plan_id cannot be modified after generation.` | | `created_at` | `Immutable field error: created_at cannot be modified after generation.` | | `created_by` | `Immutable field error: created_by cannot be modified after generation.` | | `plan_type` | `Immutable field error: plan_type cannot be modified after generation.` | | `account_name` | `Immutable field error: account_name cannot be modified after generation.` | **Canvas not found error:** ``` No success plan canvas found for [account_name]. Run generate first. ``` **Behavior:** - Locates `context/success-plan-[safe_account]-[canvas_date].md` - If `canvas_date` not provided, uses most recent canvas for account (by filename date) - Updates mutable sections: `key_objectives`, `ocv_snapshot`, and appends to `notes` - Sets `refreshed_at` to current ISO datetime - Returns updated file path and refresh timestamp **Output example (console summary):** ``` Canvas refreshed. plan_id: CANVAS-ACME-20260517 account: Acme Corp file: context/success-plan-acme-corp-2026-05-17.md refreshed_at: 2026-05-19T14:30:00Z ``` --- ## Output Format ### File naming pattern ``` context/success-plan-[safe_account]-[YYYY-MM-DD].md ``` - `safe_account`: lowercase, alphanumeric + hyphens, max 30 chars (derived from `account_name`) - `YYYY-MM-DD`: generation date (set at `generate`; preserved on `refresh`) - One file per account per date ### YAML frontmatter fields ```yaml --- plan_id: CANVAS-ACME-20260517 account_name: Acme Corp plan_type: initial csm_name: Jane Smith account_stage: Onboarding created_at: 2026-05-17T09:00:00Z created_by: [email protected] refreshed_at: null --- ``` ### Document structure ```markdown --- [YAML frontmatter as above] --- # [Initial Success Plan | Expansion Canvas | Renewal-Refresh Plan]: [account_name] **CSM:** [csm_name] **Date:** [YYYY-MM-DD] **Stage:** [account_stage] --- ## [Plan-type-specific sections — see plan-type-guide.md] ## OCV Outcomes [Rendered OCV snapshot with status indicators — omitted if no ocv_snapshot provided] ## Notes [CSM notes — append-only on refresh] ``` See `references/success-plan-canvas-schema.md` for complete field definitions and section structure per plan type. --- ## Pre-flight Read `~/.claude/plugins/config/claude-for-customer-success/csm/CLAUDE.md` and `~/.claude/plugins/config/claude-for-customer-success/company-profile.md`. If either is missing or contains `[PLACEHOLDER]` markers, stop and prompt for `/csm:cold-start-interview`. Note from config: - CS motion — shapes how directive vs. collaborative the canvas framing is - Health model — determines context for lifecycle stage assessment - Integrations — determines which data sources are available for OCV snapshot **G-code dependency:** All G-code guardrails referenced in this skill (G1–G9) are defined in the CLAUDE.md config loaded above. If Pre-flight halts or config is missing, G-codes are undefined — do not proceed with partial config. --- ## Reasoning Protocol > Blueprint: `references/reasoning-blueprint.md` (on-demand only) Before generating output, apply these primers: 1. **CLASSIFY** — Determine operation and validate inputs before proceeding: - Is `operation` present and one of `generate` or `refresh`? If absent or invalid → AskUserQuestion before proceeding. - Is `account_name` non-empty? If not → reject immediately with a clear error before any output. - For `generate`: is `plan_type` one of `initial`, `expansion`, or `renewal-refresh`? If not → return `Invalid plan_type` error. - For `refresh`: does a canvas file exist for this account? If not → return `No success plan canvas found` error before attempting any update. - CLASSIFY is complete when: operation confirmed, `account_name` validated, operation-specific preconditions pass. 2. **CONSTRAINTS** — Apply before generating any output (blocking before non-blocking): - **C-1 BLOCKING**: `account_name` must be non-empty — reject all operations if absent. - **C-2 BLOCKING (generate)**: `plan_type` must be one of `initial`, `expansion`, `renewal-refresh` — return `Invalid plan_type` error immediately; do not attempt to infer or default. - **C-3 BLOCKING (refresh)**: canvas file must exist for the target account before applying any mutable updates — return `No success plan canvas found` before attempting any field write. - **C-4 BLOCKING (refresh)**: if the refresh payload includes any immutable field (`plan_id`, `created_at`, `created_by`, `plan_type`, `account_name`) → return immutable field error for that specific field; do not apply partial updates. - **C-5 Non-blocking**: `safe_account` derivation (lowercase → replace non-alphanumeric with `-` → collapse hyphens → trim to 30 chars) must be applied before any file path construction — never use raw `account_name` in a path. - G5: Internal data (health scores, ARR, expansion signals) must never appear in customer-facing output - G7: Flag any data older than 30 days with source date and staleness indicator 3. **EXPERT CHECK** — What a veteran CSM verifies before generating or refreshing a success plan canvas: - Does the `plan_type` match the account's current lifecycle stage? An `initial` canvas for an account in active renewal review, or a `renewal-refresh` canvas for a brand-new onboarding, signals a misconfiguration — flag it. - For `initial` plans: are all 7 required CCSM-104 components present (Goals, Onboarding Milestones, Responsibilities, Success Metrics, Timelines, Risks and Assumptions, Communication Strategy)? An initial canvas missing structural sections is incomplete before it's shared. - For `renewal-refresh` with `ocv_snapshot`: does the OCV data contain enough outcome detail to drive meaningful gap analysis? An empty or single-outcome snapshot produces a shallow renewal canvas — flag the data gap. - For `refresh` with `notes` append: are prior notes preserved? Append-only discipline on notes is critical — replacing prior notes destroys the account narrative history. - Is the `key_objectives` content customer-sourced? Objectives written by the CSM without customer language anchor produce plans that get ignored at QBR. 4. **ANTI-PATTERNS** — Mistakes to catch before generating output: - **AP-1 Missing key_objectives on initial generate**: producing an initial plan without `key_objectives` — creates a canvas with no outcome anchor; the plan cannot be meaningfully reviewed. - **AP-2 renewal-refresh without ocv_snapshot**: generating a renewal-refresh canvas without OCV data — skips gap analysis entirely, which is the primary value of the renewal-refresh plan type. - **AP-3 Refresh targeting immutable fields**: attempting to update `plan_type`, `account_name`, `plan_id`, `created_at`, or `created_by` — these define plan identity; changing them corrupts the record. - **AP-4 Wrong plan_type for lifecycle stage**: generating an `initial` canvas for an account in renewal, or `expansion` for a net-new account — the section structure will be wrong and the CSM context misaligned. - **AP-5 Notes replacement instead of append**: overwriting prior notes content on a refresh — destroys the longitudinal account narrative; notes are always append-only. **After execution**, verify: - Does the output match the classified operation (`generate` or `refresh`) and apply the correct plan-type section structure? - For `generate`: are all plan-type-specific sections present (e.g., all 8 sections for `initial`, all 9 for `expansion`, all 8 for `renewal-refresh`)? - For `renewal-refresh` with `ocv_snapshot`: is the OCV Gap Analysis section populated and are outcomes correctly split between gap and delivered tables? - For `refresh`: are all immutable field constraints (C-4) confirmed clear? Are prior notes preserved if `notes` was in the payload? - Is the `safe_account` derivation applied correctly before the file path is constructed? - Confidence: [High] if `ocv_snapshot` provided with full outcome data and plan_type matches confirmed account lifecycle stage / [Medium] if plan_type or account stage is CSM-provided without system confirmation / [Low] if operating without OCV data on a renewal-refresh or without key_objectives on an initial — state which. ### When operation = `generate` 1. **Validate `plan_type`** — confirm value is one of `[initial, expansion, renewal-refresh]`. If not, return: `Invalid plan_type: [value]. Must be one of: initial, expansion, renewal-refresh.` 2. **Derive `safe_account`** — apply the four-step derivation: lowercase → replace non-alphanumeric with `-` → collapse consecutive hyphens → trim to 30 chars. If trimming occurs, proceed silently (no error). If `safe_account` after trim ends with a hyphen, that is acceptable. 3. **Generate `plan_id`** — extract first 4 alpha characters from `account_name`, strip non-alpha, uppercase; format as `CANVAS-[ACCT]-[YYYYMMDD]` using today's date. 4. **Select section structure** from plan type: - `initial` → Goals, Onboarding Milestones, Responsibilities, Success Metrics, Timelines, Risks and Assumptions, Communication Strategy, Next Steps - `expansion` → Expansion Rationale, Current Outcomes, Expansion Opportunity, Proposed Outcomes, Responsibilities, Success Metrics, Risks and Assumptions, Communication Strategy, Next Steps - `renewal-refresh` → Renewal Context, OCV Gap Analysis, Delivered Outcomes, At-Risk Outcomes, Renewal Objectives, Responsibilities, Communication Strategy, Next Steps 5. **Render OCV outcomes** if `ocv_snapshot` is provided — render per plan type rules in `reference/plan-type-guide.md`. 6. **For `renewal-refresh` with `ocv_snapshot`** — classify all outcomes with `status != "delivered"` as gaps; render gap table in OCV Gap Analysis section; render delivered outcomes separately in Delivered Outcomes section. 7. **Write file** to `context/success-plan-[safe_account]-[YYYY-MM-DD].md` with YAML frontmatter and full document body. 8. **Return console summary** with `plan_id`, `plan_type`, `account`, and `file` path. ### When operation = `refresh` 1. **Derive `safe_account`** from `account_name` using the same four-step derivation as generate. 2. **Locate canvas file** — resolve `context/success-plan-[safe_account]-[canvas_date].md`; if `canvas_date` is omitted, select the most recent canvas for the account by filename date sort. 3. **If file not found** — return: `No success plan canvas found for [account_name]. Run generate first.` 4. **Check for immutable field violations first** — if the refresh payload includes any of `plan_id`, `created_at`, `created_by`, `plan_type`, or `account_name`, return the corresponding immutable field error immediately before making any changes. 5. **Apply mutable updates:** - `key_objectives` — replace existing objectives section if provided - `ocv_snapshot` — replace existing OCV section if provided - `notes` — append to Notes section (never replace; prior notes are preserved) 6. **Set `refreshed_at`** to current ISO datetime. 7. **Return console summary** with `plan_id`, `account`, `file` path, and `refreshed_at`. ### For `renewal-refresh` with `ocv_snapshot` - Iterate all outcomes in `ocv_snapshot.outcomes` - Outcomes with `status != "delivered"` → classified as gap, rendered in OCV Gap Analysis table with Gap Risk = `⚠ Gap` - Outcomes with `status == "delivered"` → rendered in Delivered Outcomes table only, not in gap table - At-risk classification detail: `at_risk` status outcomes appear in both the gap table and the At-Risk Outcomes section ### Escalation rules - If `account_name` produces a `safe_account` that exceeds 30 chars after trim: truncate at char 30 without error or warning - If no `account_stage` is provided: omit Stage line from canvas header (do not substitute a default) - If `ocv_snapshot` is provided but `outcomes` array is empty: render OCV section with note `No outcomes recorded in this snapshot.` --- ## Reviewer note > **⚠️ Reviewer note** > - **Sources:** [CRM ✓ live — contract terms, stakeholder contacts | CRM [configured but unverified] | document storage: existing canvas or kickoff notes | user provided | not connected — conversation context only] > - **Data as of:** [timestamp per source] > - **Flagged for your judgment:** [N items marked `[review]` inline | none] > - **Before sending:** Verify success criteria in the canvas have been reviewed and agreed with the customer sponsor before treating as a mutual plan. Canvas contains no internal health scores or expansion signals. --- ## Security & Permissions - **Network access:** none - **Filesystem read scope:** `context/success-plan-*` only (for refresh file lookup); OCV data is passed as the `ocv_snapshot` input parameter — it is NOT read from the filesystem by this skill - **Filesystem write scope:** `context/success-plan-*` only - **Subprocess execution:** none - **Dynamic code execution:** none - **OCV files:** this skill NEVER writes to OCV files or any context file type other than `context/success-plan-*` - **External integrations:** none --- ## Trust & Verification **Path construction:** - `account_name` is always sanitized via the `safe_account` function (lowercase, alphanumeric + hyphen, max 30 chars) before use in any filesystem path - `display_account` (the original, unsanitized `account_name`) is used only in document content — never in filesystem path construction **Display-only fields (never used in path construction or skill logic):** - `ocv_snapshot` content is stored as advisory display data — it is rendered into the canvas document but never executed or interpolated into skill logic - `notes` and `key_objectives` are treated as display-only freetext — sanitized for path use only if they were referenced in naming (they are not) - `csm_name` is display-only — never used in filesystem path construction **Immutable field enforcement:** - Fields `plan_id`, `created_at`, `created_by`, `plan_type`, and `account_name` are set at `generate` and rejected at `refresh` with an explicit error message - No silent overwrites of immutable fields **OCV advisory contract:** - OCV data received via `ocv_snapshot` parameter is rendered for human review only - This skill NEVER writes to OCV files under any condition - OCV gap analysis (for `renewal-refresh`) is computed and displayed — not stored back to any OCV source --- ## Reference Files The following reference files govern this skill's detailed behavior. They are loaded on-demand when the relevant behavior is being applied — they are not front-loaded into every response. | File | Purpose | |------|---------| | `references/success-plan-canvas-schema.md` | Canonical canvas record format, complete YAML frontmatter field list with types and validation rules, section structure per plan type, auto-ID generation rules, immutable field list and enforcement behavior | | `references/plan-type-guide.md` | CCSM-104 7-component framework definition, per-plan-type section templates with placeholder content guidance, OCV integration rules by plan type, expansion canvas distinction rules (header branding and framing language), renewal-refresh OCV gap detection logic, component presence rules (required vs optional per plan type) | | `references/ocv-integration-contract.md` | OCV snapshot input format spec, valid status values, field mappings (`outcome_name`, `status`, `owner`), rendering format for OCV outcomes in canvas sections per plan type, gap detection logic for renewal-refresh, advisory-only contract (skill NEVER writes to OCV files) | | `references/reasoning-blueprint.md` | Problem classification taxonomy, domain heuristics, common failure modes, and expert judgment patterns for this skill | --- ## Examples ### Example 1: Generate an initial success plan **Input:** ```json { "operation": "generate", "account_name": "Acme Corp", "plan_type": "initial", "csm_name": "Jane Smith", "account_stage": "Onboarding", "key_objectives": [ "Complete technical onboarding within 30 days", "Achieve first value milestone by day 45", "Establish executive sponsor alignment" ], "ocv_snapshot": { "outcomes": [ {"outcome_name": "Reduce manual reporting time", "status": "committed", "owner": "Jane Smith"}, {"outcome_name": "Improve team visibility into pipeline", "status": "not_started", "owner": "Jane Smith"} ] }, "notes": "Champion is Sarah Lee (VP Operations). Executive sponsor is Mark Torres (CFO). Kickoff completed 2026-05-15." } ``` **Output (console summary):** ``` Canvas generated. plan_id: CANVAS-ACME-20260517 plan_type: initial account: Acme Corp file: context/success-plan-acme-corp-2026-05-17.md ``` **Output (canvas document excerpt):** ```markdown --- plan_id: CANVAS-ACME-20260517 account_name: Acme Corp plan_type: initial csm_name: Jane Smith account_stage: Onboarding created_at: 2026-05-17T09:00:00Z created_by: [email protected] refreshed_at: null --- # Initial Success Plan: Acme Corp **CSM:** Jane Smith **Date:** 2026-05-17 **Stage:** Onboarding --- ## Goals - Complete technical onboarding within 30 days - Achieve first value milestone by day 45 - Establish executive sponsor alignment ## Onboarding Milestones | Milestone | Target Date | Owner | Status | |-----------|-------------|-------|--------| | [Add milestone] | [Date] | [Owner] | Not Started | ## Responsibilities ... ``` --- ### Example 2: Generate a renewal-refresh canvas with OCV gap analysis **Input:** ```json { "operation": "generate", "account_name": "Globex Inc", "plan_type": "renewal-refresh", "csm_name": "Carlos Rivera", "account_stage": "Renewal", "ocv_snapshot": { "outcomes": [ {"outcome_name": "Automate monthly close reporting", "status": "delivered", "owner": "Carlos Rivera"}, {"outcome_name": "Reduce onboarding time by 30%", "status": "committed", "owner": "Carlos Rivera"}, {"outcome_name": "Expand usage to 3 new departments", "status": "in_progress", "owner": "Carlos Rivera"} ] }, "key_objectives": [ "Demonstrate ROI ahead of renewal conversation", "Close outstanding OCV gaps before renewal date" ] } ``` **Output (console summary):** ``` Canvas generated. plan_id: CANVAS-GLOB-20260517 plan_type: renewal-refresh account: Globex Inc file: context/success-plan-globex-inc-2026-05-17.md ``` **OCV Gap Analysis section in canvas:** ```markdown ## OCV Gap Analysis The following outcomes are committed or in progress with no delivered resolution. These represent renewal-risk gaps requiring attention before the renewal conversation. | Outcome | Status | Owner | Gap Risk | |---------|--------|-------|----------| | Reduce onboarding time by 30% | committed | Carlos Rivera | ⚠ Gap | | Expand usage to 3 new departments | in_progress | Carlos Rivera | ⚠ Gap | **Delivered Outcomes** | Outcome | Status | Owner | |---------|--------|-------| | Automate monthly close reporting | delivered | Carlos Rivera | ``` --- ### Example 3: Refresh an existing canvas with updated notes **Input:** ```json { "operation": "refresh", "account_name": "Acme Corp", "canvas_date": "2026-05-17", "notes": "QBR scheduled for 2026-06-01. Champion confirmed renewal intent pending gap closure." } ``` **Output (console summary):** ``` Canvas refreshed. plan_id: CANVAS-ACME-20260517 account: Acme Corp file: context/success-plan-acme-corp-2026-05-17.md refreshed_at: 2026-05-19T14:30:00Z ``` --- ### Example 4: Refresh error — canvas not found **Input:** ```json { "operation": "refresh", "account_name": "Unknown Customer", "notes": "Some update" } ``` **Output:** ``` No success plan canvas found for Unknown Customer. Run generate first. ```