Claude Cursor Skill

account-executive

Expert sales execution covering pipeline management, discovery, demos, negotiation, and deal closing. Use when qualifying opportunities, running MEDDIC discovery, building account plans, handling objections, structuring proposals, or forecasting pipeline.

LLM Mart · 0 points · 1 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download aaaaqwq-agi-super-team-skills_account-executive-cdb04e8.zip · 15 KB
Part of aaaaqwq/agi-super-team — 46 skills

Install

skills CLI npx skills add https://github.com/aAAaqwq/AGI-Super-Team/tree/main/skills/account-executive
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install aaaaqwq-agi-super-team@llmmart
Git git clone https://github.com/aAAaqwq/AGI-Super-Team.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole aaaaqwq/agi-super-team collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Account Executive

The agent operates as an expert account executive, driving revenue through disciplined pipeline management, structured discovery, value-based selling, strategic negotiation, and accurate forecasting.

Workflow

  1. Qualify the opportunity -- Score the lead against ICP criteria and MEDDIC dimensions. Confirm budget, authority, need, and timeline before advancing. Validate: qualification score reaches 18+ out of 30.
  2. Run discovery -- Execute MEDDIC framework to map Metrics, Economic Buyer, Decision Criteria, Decision Process, Identify Pain, and Champion. Document findings in the discovery template. Validate: all six MEDDIC fields populated.
  3. Deliver demo / evaluation -- Present solution mapped to the prospect's specific pain points and use cases. Engage all stakeholders identified during discovery. Validate: technical fit confirmed and champion provides positive feedback.
  4. Build and deliver proposal -- Construct pricing aligned to the prospect's budget and value expectations. Include ROI justification. Validate: proposal accepted or objections documented for negotiation.
  5. Negotiate and close -- Apply trade-based negotiation (never give without getting). Handle objections using the response framework. Validate: contract signed and payment terms confirmed.
  6. Hand off to Customer Success -- Transfer account context including success criteria, stakeholder map, and implementation expectations. Validate: CS acknowledges receipt and kickoff is scheduled.
  7. Update forecast -- Categorize deal accurately by confidence tier. Maintain pipeline hygiene weekly. Validate: all open opportunities have current close dates and documented next steps.

Sales Stages

Stage Probability Entry Criteria Exit Criteria
Prospect 10% Lead meets ICP Meeting scheduled
Discovery 20% Meeting held MEDDIC qualified
Demo/Evaluation 40% Technical fit confirmed Demo delivered, stakeholders engaged
Proposal 60% Budget approved Proposal accepted
Negotiation 80% Terms discussed Contract agreed
Closed Won 100% Signed Payment terms confirmed, CS handoff

MEDDIC Discovery Framework

The agent uses MEDDIC to qualify every opportunity:

  • Metrics -- "What measurable outcomes does the customer want? How would they measure success?"
  • Economic Buyer -- "Who ultimately approves this purchase and controls the budget?"
  • Decision Criteria -- "What are the must-haves vs. nice-to-haves driving the decision?"
  • Decision Process -- "What steps, stakeholders, and timeline define the evaluation?"
  • Identify Pain -- "What is the cost of inaction? What happens if this problem persists?"
  • Champion -- "Who internally advocates for this solution and shares the vision?"

Discovery Questions by Category

Situation: Current process, existing tools/systems, team structure. Problem: What is working, what is not, frequency and severity of pain. Impact: Cost of the problem, team and business effects, consequences of inaction. Need: Ideal solution characteristics, priorities, required timeline.

Qualification Scorecard

Criteria Score (1-5) Notes
Budget
Authority
Need
Timeline
Champion
Competition
Total /30
  • 25-30: Strong opportunity -- prioritize and advance aggressively.
  • 18-24: Viable -- develop weak areas before proposal stage.
  • Below 18: Needs further qualification or deprioritize.

Pipeline Management

Weekly Pipeline Hygiene

  • Update all opportunity stages to reflect current reality
  • Verify close dates are realistic (move or close stale deals)
  • Confirm documented next steps with specific dates and owners
  • Remove deals inactive for 30+ days without engagement
  • Add newly qualified opportunities

Coverage Targets

Pipeline Coverage = Total Pipeline Value / Quota

  Early quarter: 4-5x coverage
  Mid quarter:   3x coverage
  Late quarter:  1.5-2x coverage

Forecast Categories

Category Definition Probability
Commit Will close this period 90%+
Best Case Strong chance to close 60-90%
Pipeline In active evaluation 20-60%
Upside Early stage, possible <20%

Negotiation Framework

Principles:

  1. Never negotiate against yourself -- wait for the counter, use silence.
  2. Trade, don't give -- "If I do X, will you commit to Y?"
  3. Understand their constraints -- budget limits, approval thresholds, timing pressures.
  4. Create win-win -- find creative structures (multi-year, phased rollout, usage tiers).

Objection Handling

Objection Response Approach
"Too expensive" Reframe to ROI: "Compared to the cost of [problem], this pays for itself in [timeframe]."
"Need to think about it" Surface concerns: "What specific questions should we address to move forward?"
"Competitor is cheaper" Shift to total value: "Let's compare total cost of ownership including [implementation, support, outcomes]."
"Bad timing" Understand triggers: "What would need to change? Let's plan for when the timing is right."
"Need more features" Map to goals: "Which capabilities map to your top priorities? Let's focus there."

Discount Guidelines

Standard (0-10%):   AE authority, no approval needed.
Moderate (10-20%):  Manager approval, documented justification.
Deep (20-30%):      Director approval, strategic justification, quid pro quo required.
Exception (30%+):   VP approval, executive sponsor, documented business case.

Account Plan Template

# Account Plan: [Account Name]

## Account Overview
- Industry: [Industry] | Revenue: $[Amount] | Employees: [Number]
- Current ARR: $[Amount] | Whitespace: $[Amount]

## Relationship Map
| Name | Title | Role | Influence |
|------|-------|------|-----------|
| [Name] | [Title] | Champion | High |
| [Name] | [Title] | Economic Buyer | High |

## Strategy
- 90-day goals: [Goal 1], [Goal 2]
- 12-month goals: [Goal 1], [Goal 2]

## Action Plan
| Action | Owner | Due Date | Status |
|--------|-------|----------|--------|
| [Action] | [Name] | [Date] | [Status] |

## Risks
- [Risk]: [Mitigation plan]

Example: Deal Progression

Opportunity: Acme Corp - Enterprise Platform
  Stage:       Proposal (60%)
  Amount:      $180,000 ACV
  Close Date:  2026-03-28
  Champion:    VP Engineering (confirmed)
  Econ Buyer:  CTO (met, aligned on budget)
  Next Step:   Legal review of MSA by 2026-03-15
  Risk:        Procurement cycle may extend 2 weeks
  Action:      Send ROI summary to CTO for internal justification

Scripts

# Pipeline analyzer
python scripts/pipeline_analyzer.py --data opportunities.csv

# Forecast calculator
python scripts/forecast.py --pipeline pipeline.csv --quarter Q4

# Win/loss analyzer
python scripts/win_loss.py --deals closed_deals.csv

# Account planner
python scripts/account_plan.py --account "Account Name"

Troubleshooting

Problem Root Cause Resolution
Deals stalling at Discovery stage Incomplete MEDDPICC qualification; missing Economic Buyer access Re-qualify using the scorecard. If Economic Buyer is inaccessible, ask Champion for a warm introduction. Research shows early decision-maker involvement boosts win rates by 55%.
Forecast accuracy below 70% Over-reliance on rep gut feel; inconsistent stage definitions Enforce stage entry/exit criteria. Require documented next steps with dates. Switch to weighted pipeline forecasting and validate commit deals weekly.
Win rate declining quarter-over-quarter Poor upfront qualification; 63% of losses happen before needs assessment Raise minimum qualification score to 20/30 before advancing past Discovery. Implement mandatory MEDDPICC field updates at every stage gate.
Champion goes dark mid-cycle Single-threaded relationship; Champion may have changed roles or priorities Multi-thread every deal with 3+ contacts. Reach out to other mapped stakeholders within 48 hours. Refresh the relationship map monthly.
Discounting eroding margins Negotiating on price before establishing value; skipping ROI justification Always present ROI analysis before any pricing discussion. Use trade-based negotiation: never concede without a reciprocal commitment.
Pipeline coverage drops below 3x Insufficient prospecting activity; over-reliance on inbound Dedicate 20% of weekly time to outbound prospecting. Set minimum weekly meeting targets. Review pipeline coverage every Monday.
Deals lost to competitors Weak competitive positioning; late discovery of competitive evaluation Ask about competitive alternatives in first Discovery call. Prepare battle cards and landmine questions. Engage sales engineering early for technical differentiation.

Success Criteria

Metric Target Measurement Method
Quota attainment 100%+ quarterly CRM closed-won revenue vs. assigned quota
Win rate 25%+ overall; 35%+ for qualified pipeline Won / (Won + Lost) excluding disqualified
Average deal size Trending upward QoQ Mean ACV of closed-won deals
Sales cycle length Under 60 days for mid-market; under 90 for enterprise Average days from Discovery to Closed Won
Pipeline coverage 3-4x quota at all times Total weighted pipeline / remaining quota
Forecast accuracy Within 10% of actual Abs(Forecast - Actual) / Actual per quarter
MEDDPICC completion 100% for deals past Discovery Percentage of qualified deals with all 6+ fields populated
Activity-to-close ratio Improving QoQ Meetings booked / Deals closed

Scope & Limitations

In Scope:

  • Full-cycle deal management from qualification through close and CS handoff
  • MEDDPICC and BANT qualification frameworks for B2B enterprise and mid-market
  • Pipeline management, forecasting, and weekly hygiene
  • Negotiation strategy, objection handling, and proposal construction
  • Account planning for strategic and named accounts
  • Multi-stakeholder selling with 3-10 decision participants

Out of Scope:

  • Lead generation and top-of-funnel prospecting strategy (see marketing/demand-acquisition)
  • Post-sale customer success execution (see customer-success-manager)
  • CRM administration, territory design, and comp plan architecture (see sales-operations)
  • Technical demo delivery and POC management (see sales-engineer)
  • Complex enterprise integration architecture (see solutions-architect)
  • Legal contract review and procurement negotiation beyond commercial terms

Limitations:

  • Qualification frameworks assume B2B SaaS or technology selling motions; adapt scoring weights for hardware, services, or transactional sales
  • Pipeline velocity benchmarks are calibrated to mid-market ($50K-$500K ACV); adjust thresholds for SMB or enterprise segments
  • Discount guidelines require alignment with your organization's specific approval matrix
  • Scripts process local CSV/JSON data only; no CRM API integration

Integration Points

Integration Direction Purpose Handoff Artifact
Sales Engineer AE -> SE Technical validation, demo delivery, POC support Discovery notes, stakeholder map, demo requirements
Sales Operations Bidirectional Pipeline data, territory assignments, forecast rollups, quota tracking CRM opportunity records, forecast submissions
Customer Success Manager AE -> CSM Post-close handoff with account context Success criteria doc, stakeholder map, implementation expectations, signed contract
Marketing (Demand Gen) Marketing -> AE MQL-to-SQL conversion, lead routing, campaign attribution Qualified lead with engagement history and ICP score
Solutions Architect AE -> SA Complex enterprise deals requiring architecture design Technical requirements, integration constraints, compliance needs
Product Team AE -> Product Feature requests, competitive intel, market feedback Win/loss reports, feature gap analysis, competitive battle cards
Finance Bidirectional Deal desk approval, revenue recognition, payment terms Signed MSA, order form, discount justification

Workflow Handoff Protocol:

  1. AE completes MEDDPICC qualification before requesting SE or SA engagement
  2. AE submits forecast to Sales Ops weekly by end-of-day Friday
  3. AE initiates CS handoff within 24 hours of contract signature using the handoff template
  4. AE logs competitive intel in battle card repository after every competitive deal

Reference Materials

  • references/discovery.md -- Discovery framework
  • references/negotiation.md -- Negotiation tactics
  • references/objections.md -- Objection handling
  • references/forecasting.md -- Forecasting best practices
Files (agi-super-team)
  • scripts
    • deal_scorer.py 6.7 KB
      #!/usr/bin/env python3
      """Score deal health using MEDDPICC qualification framework.
      
      Reads deal data from CSV or JSON and produces a qualification score
      for each opportunity based on MEDDPICC dimensions plus BANT criteria.
      
      Usage:
          python deal_scorer.py --data deals.csv
          python deal_scorer.py --data deals.json --json
          python deal_scorer.py --data deals.csv --threshold 60
      """
      
      import argparse
      import csv
      import json
      import os
      import sys
      from datetime import datetime
      
      MEDDPICC_DIMENSIONS = [
          "metrics",
          "economic_buyer",
          "decision_criteria",
          "decision_process",
          "paper_process",
          "identify_pain",
          "champion",
          "competition",
      ]
      
      BANT_DIMENSIONS = ["budget", "authority", "need", "timeline"]
      
      SCORE_LABELS = {
          (0, 30): ("Critical", "Needs immediate qualification or disqualification"),
          (30, 50): ("Weak", "Significant gaps; address before advancing"),
          (50, 70): ("Developing", "Viable but requires work on weak dimensions"),
          (70, 85): ("Strong", "Well-qualified; advance with confidence"),
          (85, 101): ("Exceptional", "Top-tier opportunity; prioritize and close"),
      }
      
      
      def load_data(filepath):
          """Load deal data from CSV or JSON file."""
          ext = os.path.splitext(filepath)[1].lower()
          if ext == ".json":
              with open(filepath, "r") as f:
                  data = json.load(f)
                  return data if isinstance(data, list) else [data]
          elif ext == ".csv":
              with open(filepath, "r") as f:
                  reader = csv.DictReader(f)
                  return list(reader)
          else:
              print(f"Error: Unsupported file format '{ext}'. Use .csv or .json.", file=sys.stderr)
              sys.exit(1)
      
      
      def parse_score(value, max_val=5):
          """Parse a score value, clamping to 0-max_val range."""
          try:
              score = float(value)
              return max(0, min(score, max_val))
          except (ValueError, TypeError):
              return 0
      
      
      def score_deal(deal, mode="meddpicc"):
          """Score a single deal using MEDDPICC or BANT framework.
      
          Each dimension is scored 0-5. Total is normalized to 0-100.
          """
          if mode == "meddpicc":
              dimensions = MEDDPICC_DIMENSIONS
          else:
              dimensions = BANT_DIMENSIONS
      
          scores = {}
          for dim in dimensions:
              raw = deal.get(dim, deal.get(dim.replace("_", " "), 0))
              scores[dim] = parse_score(raw, 5)
      
          max_possible = len(dimensions) * 5
          raw_total = sum(scores.values())
          normalized = (raw_total / max_possible) * 100 if max_possible > 0 else 0
      
          label = "Unknown"
          advice = ""
          for (lo, hi), (lbl, adv) in SCORE_LABELS.items():
              if lo <= normalized < hi:
                  label = lbl
                  advice = adv
                  break
      
          weak_dimensions = [dim for dim, score in scores.items() if score < 3]
          strong_dimensions = [dim for dim, score in scores.items() if score >= 4]
      
          return {
              "deal_name": deal.get("deal_name", deal.get("name", deal.get("opportunity", "Unknown"))),
              "stage": deal.get("stage", "Unknown"),
              "amount": deal.get("amount", deal.get("acv", "N/A")),
              "framework": mode.upper(),
              "dimension_scores": scores,
              "raw_total": round(raw_total, 1),
              "max_possible": max_possible,
              "normalized_score": round(normalized, 1),
              "label": label,
              "advice": advice,
              "weak_dimensions": weak_dimensions,
              "strong_dimensions": strong_dimensions,
          }
      
      
      def format_human(results, threshold):
          """Format results for human-readable output."""
          lines = []
          lines.append("=" * 70)
          lines.append("DEAL QUALIFICATION SCORECARD")
          lines.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
          lines.append(f"Threshold: {threshold}/100")
          lines.append("=" * 70)
      
          above = [r for r in results if r["normalized_score"] >= threshold]
          below = [r for r in results if r["normalized_score"] < threshold]
      
          for result in sorted(results, key=lambda x: x["normalized_score"], reverse=True):
              lines.append("")
              lines.append(f"  Deal: {result['deal_name']}")
              lines.append(f"  Stage: {result['stage']}  |  Amount: {result['amount']}")
              lines.append(f"  Framework: {result['framework']}")
              lines.append(f"  Score: {result['normalized_score']}/100 ({result['raw_total']}/{result['max_possible']})")
              lines.append(f"  Rating: {result['label']}")
              lines.append(f"  Assessment: {result['advice']}")
              lines.append("")
              lines.append("  Dimension Scores:")
              for dim, score in result["dimension_scores"].items():
                  bar = "#" * int(score) + "." * (5 - int(score))
                  flag = " << WEAK" if score < 3 else ""
                  lines.append(f"    {dim:20s} [{bar}] {score}/5{flag}")
      
              if result["weak_dimensions"]:
                  lines.append(f"\n  Action Required: Strengthen {', '.join(result['weak_dimensions'])}")
              if result["strong_dimensions"]:
                  lines.append(f"  Strengths: {', '.join(result['strong_dimensions'])}")
      
              status = "ABOVE" if result["normalized_score"] >= threshold else "BELOW"
              lines.append(f"  Threshold Status: {status}")
              lines.append("-" * 70)
      
          lines.append("")
          lines.append("SUMMARY")
          lines.append(f"  Total deals scored: {len(results)}")
          lines.append(f"  Above threshold ({threshold}): {len(above)}")
          lines.append(f"  Below threshold ({threshold}): {len(below)}")
          if results:
              avg = sum(r["normalized_score"] for r in results) / len(results)
              lines.append(f"  Average score: {avg:.1f}/100")
      
          return "\n".join(lines)
      
      
      def main():
          parser = argparse.ArgumentParser(
              description="Score deal health using MEDDPICC or BANT qualification framework."
          )
          parser.add_argument("--data", required=True, help="Path to deals CSV or JSON file")
          parser.add_argument(
              "--mode",
              choices=["meddpicc", "bant"],
              default="meddpicc",
              help="Qualification framework (default: meddpicc)",
          )
          parser.add_argument(
              "--threshold",
              type=float,
              default=60,
              help="Minimum qualification score 0-100 (default: 60)",
          )
          parser.add_argument("--json", action="store_true", help="Output results as JSON")
      
          args = parser.parse_args()
      
          if not os.path.exists(args.data):
              print(f"Error: File not found: {args.data}", file=sys.stderr)
              sys.exit(1)
      
          deals = load_data(args.data)
          if not deals:
              print("Error: No deals found in input file.", file=sys.stderr)
              sys.exit(1)
      
          results = [score_deal(deal, args.mode) for deal in deals]
      
          if args.json:
              print(json.dumps(results, indent=2))
          else:
              print(format_human(results, args.threshold))
      
          below = [r for r in results if r["normalized_score"] < args.threshold]
          sys.exit(1 if below else 0)
      
      
      if __name__ == "__main__":
          main()
      
    • pipeline_analyzer.py 11.2 KB
      #!/usr/bin/env python3
      """Analyze sales pipeline for forecast accuracy, stage velocity, and health.
      
      Reads opportunity data from CSV or JSON and produces pipeline coverage,
      stage conversion rates, deal aging, velocity metrics, and forecast projections.
      
      Usage:
          python pipeline_analyzer.py --data opportunities.csv --quota 2500000
          python pipeline_analyzer.py --data opportunities.json --quota 5000000 --json
      """
      
      import argparse
      import csv
      import json
      import os
      import sys
      from collections import defaultdict
      from datetime import datetime, timedelta
      
      STAGE_ORDER = {
          "prospect": 0,
          "discovery": 1,
          "demo": 2,
          "evaluation": 3,
          "proposal": 4,
          "negotiation": 5,
          "closed_won": 6,
          "closed_lost": 7,
      }
      
      STAGE_PROBABILITIES = {
          "prospect": 0.10,
          "discovery": 0.20,
          "demo": 0.40,
          "evaluation": 0.40,
          "proposal": 0.60,
          "negotiation": 0.80,
          "closed_won": 1.00,
          "closed_lost": 0.00,
      }
      
      AGING_THRESHOLDS = {
          "prospect": 14,
          "discovery": 21,
          "demo": 14,
          "evaluation": 21,
          "proposal": 14,
          "negotiation": 21,
      }
      
      
      def load_data(filepath):
          """Load opportunity data from CSV or JSON file."""
          ext = os.path.splitext(filepath)[1].lower()
          if ext == ".json":
              with open(filepath, "r") as f:
                  data = json.load(f)
                  return data if isinstance(data, list) else [data]
          elif ext == ".csv":
              with open(filepath, "r") as f:
                  return list(csv.DictReader(f))
          else:
              print(f"Error: Unsupported file format '{ext}'. Use .csv or .json.", file=sys.stderr)
              sys.exit(1)
      
      
      def parse_amount(value):
          """Parse monetary amount from string."""
          if not value:
              return 0.0
          cleaned = str(value).replace("$", "").replace(",", "").strip()
          try:
              return float(cleaned)
          except ValueError:
              return 0.0
      
      
      def parse_date(value):
          """Parse date from common formats."""
          if not value:
              return None
          for fmt in ["%Y-%m-%d", "%m/%d/%Y", "%d/%m/%Y", "%Y-%m-%dT%H:%M:%S"]:
              try:
                  return datetime.strptime(str(value).strip(), fmt)
              except ValueError:
                  continue
          return None
      
      
      def normalize_stage(stage):
          """Normalize stage name to standard key."""
          if not stage:
              return "unknown"
          s = stage.lower().strip().replace(" ", "_").replace("/", "_")
          for key in STAGE_ORDER:
              if key in s:
                  return key
          return s
      
      
      def analyze_pipeline(opportunities, quota):
          """Run full pipeline analysis."""
          today = datetime.now()
          results = {
              "total_opportunities": 0,
              "total_pipeline_value": 0,
              "weighted_pipeline_value": 0,
              "quota": quota,
              "coverage_ratio": 0,
              "weighted_coverage": 0,
              "stage_summary": {},
              "aging_alerts": [],
              "velocity_metrics": {},
              "forecast": {},
          }
      
          stage_deals = defaultdict(list)
          stage_values = defaultdict(float)
          stage_counts = defaultdict(int)
          cycle_times = []
          won_values = []
          lost_values = []
      
          for opp in opportunities:
              stage = normalize_stage(opp.get("stage", ""))
              amount = parse_amount(opp.get("amount", opp.get("acv", opp.get("value", 0))))
              created_date = parse_date(opp.get("created_date", opp.get("create_date", "")))
              close_date = parse_date(opp.get("close_date", opp.get("expected_close", "")))
              stage_date = parse_date(opp.get("stage_date", opp.get("last_stage_change", "")))
      
              if stage in ("closed_won", "closed_lost"):
                  if stage == "closed_won":
                      won_values.append(amount)
                      if created_date and close_date:
                          days = (close_date - created_date).days
                          if days > 0:
                              cycle_times.append(days)
                  else:
                      lost_values.append(amount)
                  continue
      
              results["total_opportunities"] += 1
              prob = STAGE_PROBABILITIES.get(stage, 0.20)
              weighted = amount * prob
      
              results["total_pipeline_value"] += amount
              results["weighted_pipeline_value"] += weighted
      
              stage_deals[stage].append({
                  "name": opp.get("name", opp.get("deal_name", opp.get("opportunity", "Unknown"))),
                  "amount": amount,
                  "weighted": round(weighted, 2),
                  "close_date": close_date.strftime("%Y-%m-%d") if close_date else "Not set",
              })
              stage_values[stage] += amount
              stage_counts[stage] += 1
      
              # Check aging
              if stage_date:
                  days_in_stage = (today - stage_date).days
                  threshold = AGING_THRESHOLDS.get(stage, 21)
                  if days_in_stage > threshold:
                      results["aging_alerts"].append({
                          "deal": opp.get("name", opp.get("deal_name", "Unknown")),
                          "stage": stage,
                          "days_in_stage": days_in_stage,
                          "threshold": threshold,
                          "amount": amount,
                      })
      
          # Coverage ratios
          if quota > 0:
              results["coverage_ratio"] = round(results["total_pipeline_value"] / quota, 2)
              results["weighted_coverage"] = round(results["weighted_pipeline_value"] / quota, 2)
      
          # Stage summary
          for stage in sorted(stage_counts.keys(), key=lambda s: STAGE_ORDER.get(s, 99)):
              results["stage_summary"][stage] = {
                  "count": stage_counts[stage],
                  "total_value": round(stage_values[stage], 2),
                  "avg_deal_size": round(stage_values[stage] / stage_counts[stage], 2) if stage_counts[stage] > 0 else 0,
                  "probability": STAGE_PROBABILITIES.get(stage, 0.20),
                  "weighted_value": round(stage_values[stage] * STAGE_PROBABILITIES.get(stage, 0.20), 2),
              }
      
          # Velocity metrics
          total_won = len(won_values)
          total_lost = len(lost_values)
          total_decided = total_won + total_lost
          results["velocity_metrics"] = {
              "avg_cycle_time_days": round(sum(cycle_times) / len(cycle_times), 1) if cycle_times else 0,
              "median_cycle_time_days": sorted(cycle_times)[len(cycle_times) // 2] if cycle_times else 0,
              "win_rate": round(total_won / total_decided * 100, 1) if total_decided > 0 else 0,
              "avg_won_deal_size": round(sum(won_values) / total_won, 2) if won_values else 0,
              "avg_lost_deal_size": round(sum(lost_values) / total_lost, 2) if lost_values else 0,
              "total_won": total_won,
              "total_lost": total_lost,
          }
      
          # Forecast
          gap = quota - results["weighted_pipeline_value"]
          open_pipeline = results["total_pipeline_value"]
          win_rate = results["velocity_metrics"]["win_rate"]
          required_win_rate = (gap / open_pipeline * 100) if open_pipeline > 0 and gap > 0 else 0
      
          results["forecast"] = {
              "weighted_forecast": round(results["weighted_pipeline_value"], 2),
              "gap_to_quota": round(max(gap, 0), 2),
              "gap_percentage": round(max(gap, 0) / quota * 100, 1) if quota > 0 else 0,
              "required_win_rate": round(required_win_rate, 1),
              "current_win_rate": win_rate,
              "on_track": gap <= 0,
          }
      
          results["total_pipeline_value"] = round(results["total_pipeline_value"], 2)
          results["weighted_pipeline_value"] = round(results["weighted_pipeline_value"], 2)
      
          return results
      
      
      def format_human(results):
          """Format results for human-readable output."""
          lines = []
          lines.append("=" * 70)
          lines.append("PIPELINE ANALYSIS REPORT")
          lines.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
          lines.append("=" * 70)
      
          lines.append(f"\n  Open Opportunities:    {results['total_opportunities']}")
          lines.append(f"  Total Pipeline Value:  ${results['total_pipeline_value']:,.2f}")
          lines.append(f"  Weighted Pipeline:     ${results['weighted_pipeline_value']:,.2f}")
          lines.append(f"  Quota:                 ${results['quota']:,.2f}")
          lines.append(f"  Coverage Ratio:        {results['coverage_ratio']}x")
          lines.append(f"  Weighted Coverage:     {results['weighted_coverage']}x")
      
          cov = results["coverage_ratio"]
          if cov >= 4:
              lines.append("  Coverage Status:       HEALTHY (4x+)")
          elif cov >= 3:
              lines.append("  Coverage Status:       ADEQUATE (3x)")
          elif cov >= 2:
              lines.append("  Coverage Status:       WARNING (below 3x)")
          else:
              lines.append("  Coverage Status:       CRITICAL (below 2x)")
      
          lines.append(f"\n{'STAGE BREAKDOWN':^70}")
          lines.append("-" * 70)
          lines.append(f"  {'Stage':<16} {'Count':>6} {'Value':>14} {'Prob':>6} {'Weighted':>14}")
          lines.append("  " + "-" * 58)
          for stage, data in results["stage_summary"].items():
              lines.append(
                  f"  {stage:<16} {data['count']:>6} "
                  f"${data['total_value']:>12,.2f} "
                  f"{data['probability']:>5.0%} "
                  f"${data['weighted_value']:>12,.2f}"
              )
      
          vm = results["velocity_metrics"]
          lines.append(f"\n{'VELOCITY METRICS':^70}")
          lines.append("-" * 70)
          lines.append(f"  Avg Sales Cycle:     {vm['avg_cycle_time_days']} days")
          lines.append(f"  Median Sales Cycle:  {vm['median_cycle_time_days']} days")
          lines.append(f"  Win Rate:            {vm['win_rate']}%")
          lines.append(f"  Avg Won Deal Size:   ${vm['avg_won_deal_size']:,.2f}")
          lines.append(f"  Won Deals:           {vm['total_won']}")
          lines.append(f"  Lost Deals:          {vm['total_lost']}")
      
          fc = results["forecast"]
          lines.append(f"\n{'FORECAST':^70}")
          lines.append("-" * 70)
          lines.append(f"  Weighted Forecast:     ${fc['weighted_forecast']:,.2f}")
          lines.append(f"  Gap to Quota:          ${fc['gap_to_quota']:,.2f} ({fc['gap_percentage']}%)")
          lines.append(f"  Required Win Rate:     {fc['required_win_rate']}%")
          lines.append(f"  Current Win Rate:      {fc['current_win_rate']}%")
          status = "ON TRACK" if fc["on_track"] else "AT RISK"
          lines.append(f"  Status:                {status}")
      
          if results["aging_alerts"]:
              lines.append(f"\n{'AGING ALERTS':^70}")
              lines.append("-" * 70)
              for alert in sorted(results["aging_alerts"], key=lambda a: a["days_in_stage"], reverse=True):
                  lines.append(
                      f"  {alert['deal']:<30} {alert['stage']:<14} "
                      f"{alert['days_in_stage']}d (threshold: {alert['threshold']}d)  "
                      f"${alert['amount']:,.2f}"
                  )
      
          return "\n".join(lines)
      
      
      def main():
          parser = argparse.ArgumentParser(
              description="Analyze sales pipeline for coverage, velocity, and forecast accuracy."
          )
          parser.add_argument("--data", required=True, help="Path to opportunities CSV or JSON file")
          parser.add_argument(
              "--quota", type=float, default=2500000, help="Quarterly quota target (default: 2500000)"
          )
          parser.add_argument("--json", action="store_true", help="Output results as JSON")
      
          args = parser.parse_args()
      
          if not os.path.exists(args.data):
              print(f"Error: File not found: {args.data}", file=sys.stderr)
              sys.exit(1)
      
          opportunities = load_data(args.data)
          if not opportunities:
              print("Error: No opportunities found in input file.", file=sys.stderr)
              sys.exit(1)
      
          results = analyze_pipeline(opportunities, args.quota)
      
          if args.json:
              print(json.dumps(results, indent=2))
          else:
              print(format_human(results))
      
          sys.exit(0 if results["forecast"]["on_track"] else 1)
      
      
      if __name__ == "__main__":
          main()
      
    • win_loss_analyzer.py 10.1 KB
      #!/usr/bin/env python3
      """Analyze win/loss patterns from closed deal data.
      
      Reads closed deal data from CSV or JSON and identifies patterns in wins vs.
      losses across dimensions: deal size, sales cycle, competitor, industry,
      lead source, and qualification score.
      
      Usage:
          python win_loss_analyzer.py --data closed_deals.csv
          python win_loss_analyzer.py --data deals.json --json
          python win_loss_analyzer.py --data deals.csv --min-deals 5
      """
      
      import argparse
      import csv
      import json
      import math
      import os
      import sys
      from collections import defaultdict
      from datetime import datetime
      
      
      def load_data(filepath):
          """Load closed deal data from CSV or JSON file."""
          ext = os.path.splitext(filepath)[1].lower()
          if ext == ".json":
              with open(filepath, "r") as f:
                  data = json.load(f)
                  return data if isinstance(data, list) else [data]
          elif ext == ".csv":
              with open(filepath, "r") as f:
                  return list(csv.DictReader(f))
          else:
              print(f"Error: Unsupported file format '{ext}'. Use .csv or .json.", file=sys.stderr)
              sys.exit(1)
      
      
      def parse_amount(value):
          """Parse monetary amount from string."""
          if not value:
              return 0.0
          cleaned = str(value).replace("$", "").replace(",", "").strip()
          try:
              return float(cleaned)
          except ValueError:
              return 0.0
      
      
      def parse_days(value):
          """Parse numeric days value."""
          try:
              return int(float(str(value).strip()))
          except (ValueError, TypeError):
              return 0
      
      
      def is_won(deal):
          """Determine if a deal was won."""
          outcome = str(deal.get("outcome", deal.get("stage", deal.get("status", "")))).lower().strip()
          return outcome in ("won", "closed_won", "closed won", "win", "1", "true")
      
      
      def bucket_amount(amount):
          """Categorize deal amount into size buckets."""
          if amount < 25000:
              return "SMB (<$25K)"
          elif amount < 100000:
              return "Mid-Market ($25K-$100K)"
          elif amount < 500000:
              return "Enterprise ($100K-$500K)"
          else:
              return "Strategic ($500K+)"
      
      
      def bucket_cycle(days):
          """Categorize sales cycle length into buckets."""
          if days <= 0:
              return "Unknown"
          elif days <= 30:
              return "Fast (0-30d)"
          elif days <= 60:
              return "Normal (31-60d)"
          elif days <= 90:
              return "Extended (61-90d)"
          else:
              return "Long (90d+)"
      
      
      def analyze_dimension(deals, get_key, min_deals=3):
          """Analyze win/loss rates by a given dimension."""
          groups = defaultdict(lambda: {"won": 0, "lost": 0, "won_value": 0, "lost_value": 0})
          for deal in deals:
              key = get_key(deal)
              if not key or key == "Unknown" or key == "":
                  key = "Unspecified"
              amount = parse_amount(deal.get("amount", deal.get("acv", deal.get("value", 0))))
              if is_won(deal):
                  groups[key]["won"] += 1
                  groups[key]["won_value"] += amount
              else:
                  groups[key]["lost"] += 1
                  groups[key]["lost_value"] += amount
      
          results = {}
          for key, data in groups.items():
              total = data["won"] + data["lost"]
              if total >= min_deals:
                  results[key] = {
                      "won": data["won"],
                      "lost": data["lost"],
                      "total": total,
                      "win_rate": round(data["won"] / total * 100, 1),
                      "won_value": round(data["won_value"], 2),
                      "lost_value": round(data["lost_value"], 2),
                      "avg_won_value": round(data["won_value"] / data["won"], 2) if data["won"] > 0 else 0,
                  }
          return dict(sorted(results.items(), key=lambda x: x[1]["win_rate"], reverse=True))
      
      
      def find_patterns(analysis_results):
          """Identify key patterns and actionable insights."""
          patterns = []
      
          for dimension, data in analysis_results.items():
              if not data:
                  continue
      
              rates = [(k, v["win_rate"], v["total"]) for k, v in data.items()]
              if len(rates) < 2:
                  continue
      
              best = max(rates, key=lambda x: x[1])
              worst = min(rates, key=lambda x: x[1])
      
              if best[1] - worst[1] > 15:
                  patterns.append({
                      "dimension": dimension,
                      "finding": f"Win rate varies significantly: {best[0]} ({best[1]}%) vs {worst[0]} ({worst[1]}%)",
                      "spread": round(best[1] - worst[1], 1),
                      "recommendation": f"Investigate what drives success in '{best[0]}' and apply lessons to '{worst[0]}'",
                      "priority": "high" if best[1] - worst[1] > 30 else "medium",
                  })
      
          return sorted(patterns, key=lambda p: p["spread"], reverse=True)
      
      
      def analyze_loss_reasons(deals):
          """Analyze primary loss reasons if provided."""
          reasons = defaultdict(lambda: {"count": 0, "total_value": 0})
          for deal in deals:
              if is_won(deal):
                  continue
              reason = deal.get("loss_reason", deal.get("close_reason", deal.get("reason", "")))
              if reason:
                  reason = str(reason).strip()
                  amount = parse_amount(deal.get("amount", deal.get("acv", 0)))
                  reasons[reason]["count"] += 1
                  reasons[reason]["total_value"] += amount
      
          return dict(sorted(reasons.items(), key=lambda x: x[1]["count"], reverse=True))
      
      
      def format_human(results, patterns, loss_reasons):
          """Format results for human-readable output."""
          lines = []
          lines.append("=" * 70)
          lines.append("WIN/LOSS ANALYSIS REPORT")
          lines.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
          lines.append("=" * 70)
      
          summary = results.get("summary", {})
          lines.append(f"\n  Total Deals Analyzed: {summary.get('total_deals', 0)}")
          lines.append(f"  Won: {summary.get('total_won', 0)}  |  Lost: {summary.get('total_lost', 0)}")
          lines.append(f"  Overall Win Rate: {summary.get('overall_win_rate', 0)}%")
          lines.append(f"  Total Won Revenue: ${summary.get('total_won_value', 0):,.2f}")
          lines.append(f"  Total Lost Revenue: ${summary.get('total_lost_value', 0):,.2f}")
      
          for dimension, data in results.items():
              if dimension == "summary":
                  continue
              if not data:
                  continue
      
              title = dimension.replace("_", " ").upper()
              lines.append(f"\n{'WIN RATE BY ' + title:^70}")
              lines.append("-" * 70)
              lines.append(f"  {'Category':<30} {'Won':>5} {'Lost':>5} {'Total':>6} {'Win Rate':>9}")
              lines.append("  " + "-" * 57)
      
              for category, stats in data.items():
                  wr = stats["win_rate"]
                  indicator = " ***" if wr >= 40 else " !" if wr < 15 else ""
                  lines.append(
                      f"  {category:<30} {stats['won']:>5} {stats['lost']:>5} "
                      f"{stats['total']:>6} {wr:>8.1f}%{indicator}"
                  )
      
          if loss_reasons:
              lines.append(f"\n{'LOSS REASONS':^70}")
              lines.append("-" * 70)
              lines.append(f"  {'Reason':<40} {'Count':>6} {'Lost Value':>14}")
              lines.append("  " + "-" * 62)
              for reason, data in loss_reasons.items():
                  lines.append(f"  {reason:<40} {data['count']:>6} ${data['total_value']:>12,.2f}")
      
          if patterns:
              lines.append(f"\n{'KEY PATTERNS & RECOMMENDATIONS':^70}")
              lines.append("-" * 70)
              for i, p in enumerate(patterns, 1):
                  lines.append(f"\n  {i}. [{p['priority'].upper()}] {p['dimension'].replace('_', ' ').title()}")
                  lines.append(f"     Finding: {p['finding']}")
                  lines.append(f"     Action:  {p['recommendation']}")
      
          return "\n".join(lines)
      
      
      def main():
          parser = argparse.ArgumentParser(
              description="Analyze win/loss patterns from closed deal data."
          )
          parser.add_argument("--data", required=True, help="Path to closed deals CSV or JSON file")
          parser.add_argument(
              "--min-deals",
              type=int,
              default=3,
              help="Minimum deals per category to include in analysis (default: 3)",
          )
          parser.add_argument("--json", action="store_true", help="Output results as JSON")
      
          args = parser.parse_args()
      
          if not os.path.exists(args.data):
              print(f"Error: File not found: {args.data}", file=sys.stderr)
              sys.exit(1)
      
          deals = load_data(args.data)
          if not deals:
              print("Error: No deals found in input file.", file=sys.stderr)
              sys.exit(1)
      
          total_won = sum(1 for d in deals if is_won(d))
          total_lost = len(deals) - total_won
          won_value = sum(parse_amount(d.get("amount", d.get("acv", 0))) for d in deals if is_won(d))
          lost_value = sum(parse_amount(d.get("amount", d.get("acv", 0))) for d in deals if not is_won(d))
      
          results = {
              "summary": {
                  "total_deals": len(deals),
                  "total_won": total_won,
                  "total_lost": total_lost,
                  "overall_win_rate": round(total_won / len(deals) * 100, 1) if deals else 0,
                  "total_won_value": round(won_value, 2),
                  "total_lost_value": round(lost_value, 2),
              },
              "deal_size": analyze_dimension(
                  deals,
                  lambda d: bucket_amount(parse_amount(d.get("amount", d.get("acv", 0)))),
                  args.min_deals,
              ),
              "sales_cycle": analyze_dimension(
                  deals,
                  lambda d: bucket_cycle(parse_days(d.get("cycle_days", d.get("sales_cycle", 0)))),
                  args.min_deals,
              ),
              "competitor": analyze_dimension(
                  deals,
                  lambda d: d.get("competitor", d.get("primary_competitor", "")),
                  args.min_deals,
              ),
              "industry": analyze_dimension(
                  deals, lambda d: d.get("industry", ""), args.min_deals
              ),
              "lead_source": analyze_dimension(
                  deals, lambda d: d.get("lead_source", d.get("source", "")), args.min_deals
              ),
          }
      
          all_dimension_data = {k: v for k, v in results.items() if k != "summary"}
          patterns = find_patterns(all_dimension_data)
          loss_reasons = analyze_loss_reasons(deals)
      
          if args.json:
              output = {
                  **results,
                  "patterns": patterns,
                  "loss_reasons": loss_reasons,
              }
              print(json.dumps(output, indent=2))
          else:
              print(format_human(results, patterns, loss_reasons))
      
          sys.exit(0)
      
      
      if __name__ == "__main__":
          main()
      
  • SKILL.md 13.3 KB
    ---
    name: account-executive
    description: >
      Expert sales execution covering pipeline management, discovery, demos,
      negotiation, and deal closing. Use when qualifying opportunities, running
      MEDDIC discovery, building account plans, handling objections, structuring
      proposals, or forecasting pipeline.
    license: MIT + Commons Clause
    metadata:
      version: 1.0.0
      author: borghei
      category: sales-success
      updated: 2026-03-31
      tags: [sales, pipeline, negotiation, closing, deals]
    ---
    # Account Executive
    
    The agent operates as an expert account executive, driving revenue through disciplined pipeline management, structured discovery, value-based selling, strategic negotiation, and accurate forecasting.
    
    ## Workflow
    
    1. **Qualify the opportunity** -- Score the lead against ICP criteria and MEDDIC dimensions. Confirm budget, authority, need, and timeline before advancing. Validate: qualification score reaches 18+ out of 30.
    2. **Run discovery** -- Execute MEDDIC framework to map Metrics, Economic Buyer, Decision Criteria, Decision Process, Identify Pain, and Champion. Document findings in the discovery template. Validate: all six MEDDIC fields populated.
    3. **Deliver demo / evaluation** -- Present solution mapped to the prospect's specific pain points and use cases. Engage all stakeholders identified during discovery. Validate: technical fit confirmed and champion provides positive feedback.
    4. **Build and deliver proposal** -- Construct pricing aligned to the prospect's budget and value expectations. Include ROI justification. Validate: proposal accepted or objections documented for negotiation.
    5. **Negotiate and close** -- Apply trade-based negotiation (never give without getting). Handle objections using the response framework. Validate: contract signed and payment terms confirmed.
    6. **Hand off to Customer Success** -- Transfer account context including success criteria, stakeholder map, and implementation expectations. Validate: CS acknowledges receipt and kickoff is scheduled.
    7. **Update forecast** -- Categorize deal accurately by confidence tier. Maintain pipeline hygiene weekly. Validate: all open opportunities have current close dates and documented next steps.
    
    ## Sales Stages
    
    | Stage | Probability | Entry Criteria | Exit Criteria |
    |-------|------------|----------------|---------------|
    | Prospect | 10% | Lead meets ICP | Meeting scheduled |
    | Discovery | 20% | Meeting held | MEDDIC qualified |
    | Demo/Evaluation | 40% | Technical fit confirmed | Demo delivered, stakeholders engaged |
    | Proposal | 60% | Budget approved | Proposal accepted |
    | Negotiation | 80% | Terms discussed | Contract agreed |
    | Closed Won | 100% | Signed | Payment terms confirmed, CS handoff |
    
    ## MEDDIC Discovery Framework
    
    The agent uses MEDDIC to qualify every opportunity:
    
    - **Metrics** -- "What measurable outcomes does the customer want? How would they measure success?"
    - **Economic Buyer** -- "Who ultimately approves this purchase and controls the budget?"
    - **Decision Criteria** -- "What are the must-haves vs. nice-to-haves driving the decision?"
    - **Decision Process** -- "What steps, stakeholders, and timeline define the evaluation?"
    - **Identify Pain** -- "What is the cost of inaction? What happens if this problem persists?"
    - **Champion** -- "Who internally advocates for this solution and shares the vision?"
    
    ### Discovery Questions by Category
    
    **Situation:** Current process, existing tools/systems, team structure.
    **Problem:** What is working, what is not, frequency and severity of pain.
    **Impact:** Cost of the problem, team and business effects, consequences of inaction.
    **Need:** Ideal solution characteristics, priorities, required timeline.
    
    ### Qualification Scorecard
    
    | Criteria | Score (1-5) | Notes |
    |----------|-------------|-------|
    | Budget | | |
    | Authority | | |
    | Need | | |
    | Timeline | | |
    | Champion | | |
    | Competition | | |
    | **Total** | **/30** | |
    
    - **25-30:** Strong opportunity -- prioritize and advance aggressively.
    - **18-24:** Viable -- develop weak areas before proposal stage.
    - **Below 18:** Needs further qualification or deprioritize.
    
    ## Pipeline Management
    
    ### Weekly Pipeline Hygiene
    
    - [ ] Update all opportunity stages to reflect current reality
    - [ ] Verify close dates are realistic (move or close stale deals)
    - [ ] Confirm documented next steps with specific dates and owners
    - [ ] Remove deals inactive for 30+ days without engagement
    - [ ] Add newly qualified opportunities
    
    ### Coverage Targets
    
    ```
    Pipeline Coverage = Total Pipeline Value / Quota
    
      Early quarter: 4-5x coverage
      Mid quarter:   3x coverage
      Late quarter:  1.5-2x coverage
    ```
    
    ### Forecast Categories
    
    | Category | Definition | Probability |
    |----------|------------|-------------|
    | Commit | Will close this period | 90%+ |
    | Best Case | Strong chance to close | 60-90% |
    | Pipeline | In active evaluation | 20-60% |
    | Upside | Early stage, possible | <20% |
    
    ## Negotiation Framework
    
    **Principles:**
    1. Never negotiate against yourself -- wait for the counter, use silence.
    2. Trade, don't give -- "If I do X, will you commit to Y?"
    3. Understand their constraints -- budget limits, approval thresholds, timing pressures.
    4. Create win-win -- find creative structures (multi-year, phased rollout, usage tiers).
    
    ### Objection Handling
    
    | Objection | Response Approach |
    |-----------|-------------------|
    | "Too expensive" | Reframe to ROI: "Compared to the cost of [problem], this pays for itself in [timeframe]." |
    | "Need to think about it" | Surface concerns: "What specific questions should we address to move forward?" |
    | "Competitor is cheaper" | Shift to total value: "Let's compare total cost of ownership including [implementation, support, outcomes]." |
    | "Bad timing" | Understand triggers: "What would need to change? Let's plan for when the timing is right." |
    | "Need more features" | Map to goals: "Which capabilities map to your top priorities? Let's focus there." |
    
    ### Discount Guidelines
    
    ```
    Standard (0-10%):   AE authority, no approval needed.
    Moderate (10-20%):  Manager approval, documented justification.
    Deep (20-30%):      Director approval, strategic justification, quid pro quo required.
    Exception (30%+):   VP approval, executive sponsor, documented business case.
    ```
    
    ## Account Plan Template
    
    ```markdown
    # Account Plan: [Account Name]
    
    ## Account Overview
    - Industry: [Industry] | Revenue: $[Amount] | Employees: [Number]
    - Current ARR: $[Amount] | Whitespace: $[Amount]
    
    ## Relationship Map
    | Name | Title | Role | Influence |
    |------|-------|------|-----------|
    | [Name] | [Title] | Champion | High |
    | [Name] | [Title] | Economic Buyer | High |
    
    ## Strategy
    - 90-day goals: [Goal 1], [Goal 2]
    - 12-month goals: [Goal 1], [Goal 2]
    
    ## Action Plan
    | Action | Owner | Due Date | Status |
    |--------|-------|----------|--------|
    | [Action] | [Name] | [Date] | [Status] |
    
    ## Risks
    - [Risk]: [Mitigation plan]
    ```
    
    ## Example: Deal Progression
    
    ```
    Opportunity: Acme Corp - Enterprise Platform
      Stage:       Proposal (60%)
      Amount:      $180,000 ACV
      Close Date:  2026-03-28
      Champion:    VP Engineering (confirmed)
      Econ Buyer:  CTO (met, aligned on budget)
      Next Step:   Legal review of MSA by 2026-03-15
      Risk:        Procurement cycle may extend 2 weeks
      Action:      Send ROI summary to CTO for internal justification
    ```
    
    ## Scripts
    
    ```bash
    # Pipeline analyzer
    python scripts/pipeline_analyzer.py --data opportunities.csv
    
    # Forecast calculator
    python scripts/forecast.py --pipeline pipeline.csv --quarter Q4
    
    # Win/loss analyzer
    python scripts/win_loss.py --deals closed_deals.csv
    
    # Account planner
    python scripts/account_plan.py --account "Account Name"
    ```
    
    ## Troubleshooting
    
    | Problem | Root Cause | Resolution |
    |---------|-----------|------------|
    | Deals stalling at Discovery stage | Incomplete MEDDPICC qualification; missing Economic Buyer access | Re-qualify using the scorecard. If Economic Buyer is inaccessible, ask Champion for a warm introduction. Research shows early decision-maker involvement boosts win rates by 55%. |
    | Forecast accuracy below 70% | Over-reliance on rep gut feel; inconsistent stage definitions | Enforce stage entry/exit criteria. Require documented next steps with dates. Switch to weighted pipeline forecasting and validate commit deals weekly. |
    | Win rate declining quarter-over-quarter | Poor upfront qualification; 63% of losses happen before needs assessment | Raise minimum qualification score to 20/30 before advancing past Discovery. Implement mandatory MEDDPICC field updates at every stage gate. |
    | Champion goes dark mid-cycle | Single-threaded relationship; Champion may have changed roles or priorities | Multi-thread every deal with 3+ contacts. Reach out to other mapped stakeholders within 48 hours. Refresh the relationship map monthly. |
    | Discounting eroding margins | Negotiating on price before establishing value; skipping ROI justification | Always present ROI analysis before any pricing discussion. Use trade-based negotiation: never concede without a reciprocal commitment. |
    | Pipeline coverage drops below 3x | Insufficient prospecting activity; over-reliance on inbound | Dedicate 20% of weekly time to outbound prospecting. Set minimum weekly meeting targets. Review pipeline coverage every Monday. |
    | Deals lost to competitors | Weak competitive positioning; late discovery of competitive evaluation | Ask about competitive alternatives in first Discovery call. Prepare battle cards and landmine questions. Engage sales engineering early for technical differentiation. |
    
    ## Success Criteria
    
    | Metric | Target | Measurement Method |
    |--------|--------|--------------------|
    | Quota attainment | 100%+ quarterly | CRM closed-won revenue vs. assigned quota |
    | Win rate | 25%+ overall; 35%+ for qualified pipeline | Won / (Won + Lost) excluding disqualified |
    | Average deal size | Trending upward QoQ | Mean ACV of closed-won deals |
    | Sales cycle length | Under 60 days for mid-market; under 90 for enterprise | Average days from Discovery to Closed Won |
    | Pipeline coverage | 3-4x quota at all times | Total weighted pipeline / remaining quota |
    | Forecast accuracy | Within 10% of actual | Abs(Forecast - Actual) / Actual per quarter |
    | MEDDPICC completion | 100% for deals past Discovery | Percentage of qualified deals with all 6+ fields populated |
    | Activity-to-close ratio | Improving QoQ | Meetings booked / Deals closed |
    
    ## Scope & Limitations
    
    **In Scope:**
    - Full-cycle deal management from qualification through close and CS handoff
    - MEDDPICC and BANT qualification frameworks for B2B enterprise and mid-market
    - Pipeline management, forecasting, and weekly hygiene
    - Negotiation strategy, objection handling, and proposal construction
    - Account planning for strategic and named accounts
    - Multi-stakeholder selling with 3-10 decision participants
    
    **Out of Scope:**
    - Lead generation and top-of-funnel prospecting strategy (see marketing/demand-acquisition)
    - Post-sale customer success execution (see customer-success-manager)
    - CRM administration, territory design, and comp plan architecture (see sales-operations)
    - Technical demo delivery and POC management (see sales-engineer)
    - Complex enterprise integration architecture (see solutions-architect)
    - Legal contract review and procurement negotiation beyond commercial terms
    
    **Limitations:**
    - Qualification frameworks assume B2B SaaS or technology selling motions; adapt scoring weights for hardware, services, or transactional sales
    - Pipeline velocity benchmarks are calibrated to mid-market ($50K-$500K ACV); adjust thresholds for SMB or enterprise segments
    - Discount guidelines require alignment with your organization's specific approval matrix
    - Scripts process local CSV/JSON data only; no CRM API integration
    
    ## Integration Points
    
    | Integration | Direction | Purpose | Handoff Artifact |
    |-------------|-----------|---------|-----------------|
    | **Sales Engineer** | AE -> SE | Technical validation, demo delivery, POC support | Discovery notes, stakeholder map, demo requirements |
    | **Sales Operations** | Bidirectional | Pipeline data, territory assignments, forecast rollups, quota tracking | CRM opportunity records, forecast submissions |
    | **Customer Success Manager** | AE -> CSM | Post-close handoff with account context | Success criteria doc, stakeholder map, implementation expectations, signed contract |
    | **Marketing (Demand Gen)** | Marketing -> AE | MQL-to-SQL conversion, lead routing, campaign attribution | Qualified lead with engagement history and ICP score |
    | **Solutions Architect** | AE -> SA | Complex enterprise deals requiring architecture design | Technical requirements, integration constraints, compliance needs |
    | **Product Team** | AE -> Product | Feature requests, competitive intel, market feedback | Win/loss reports, feature gap analysis, competitive battle cards |
    | **Finance** | Bidirectional | Deal desk approval, revenue recognition, payment terms | Signed MSA, order form, discount justification |
    
    **Workflow Handoff Protocol:**
    1. AE completes MEDDPICC qualification before requesting SE or SA engagement
    2. AE submits forecast to Sales Ops weekly by end-of-day Friday
    3. AE initiates CS handoff within 24 hours of contract signature using the handoff template
    4. AE logs competitive intel in battle card repository after every competitive deal
    
    ## Reference Materials
    
    - `references/discovery.md` -- Discovery framework
    - `references/negotiation.md` -- Negotiation tactics
    - `references/objections.md` -- Objection handling
    - `references/forecasting.md` -- Forecasting best practices
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related