Files
claude-skills-reference/c-level-advisor/cfo-advisor/scripts/burn_rate_calculator.py
Alireza Rezvani 466aa13a7b feat: C-Suite expansion — 8 new executive advisory roles (2→10) (#264)
* feat: C-Suite expansion — 8 new executive advisory roles

Add COO, CPO, CMO, CFO, CRO, CISO, CHRO advisors and Executive Mentor.
Expands C-level advisory from 2 to 10 roles with 74 total files.

Each role includes:
- SKILL.md (lean, <5KB, ~1200 tokens for context efficiency)
- Reference docs (loaded on demand, not at startup)
- Python analysis scripts (stdlib only, runnable CLI)

Executive Mentor features /em: slash commands (challenge, board-prep,
hard-call, stress-test, postmortem) with devil's advocate agent.

21 Python tools, 24 reference frameworks, 28,379 total lines.
All SKILL.md files combined: ~17K tokens (8.5% of 200K context window).

Badge: 88 → 116 skills

* feat: C-Suite orchestration layer + 18 complementary skills

ORCHESTRATION (new):
- cs-onboard: Founder interview → company-context.md
- chief-of-staff: Routing, synthesis, inter-agent orchestration
- board-meeting: 6-phase multi-agent deliberation protocol
- decision-logger: Two-layer memory (raw transcripts + approved decisions)
- agent-protocol: Inter-agent invocation with loop prevention
- context-engine: Company context loading + anonymization

CROSS-CUTTING CAPABILITIES (new):
- board-deck-builder: Board/investor update assembly
- scenario-war-room: Cascading multi-variable what-if modeling
- competitive-intel: Systematic competitor tracking + battlecards
- org-health-diagnostic: Cross-functional health scoring (8 dimensions)
- ma-playbook: M&A strategy (acquiring + being acquired)
- intl-expansion: International market entry frameworks

CULTURE & COLLABORATION (new):
- culture-architect: Values → behaviors, culture code, health assessment
- company-os: EOS/Scaling Up operating system selection + implementation
- founder-coach: Founder development, delegation, blind spots
- strategic-alignment: Strategy cascade, silo detection, alignment scoring
- change-management: ADKAR-based change rollout framework
- internal-narrative: One story across employees/investors/customers

UPGRADES TO EXISTING ROLES:
- All 10 roles get reasoning technique directives
- All 10 roles get company-context.md integration
- All 10 roles get board meeting isolation rules
- CEO gets stage-adaptive temporal horizons (seed→C)

Key design decisions:
- Two-layer memory prevents hallucinated consensus from rejected ideas
- Phase 2 isolation: agents think independently before cross-examination
- Executive Mentor (The Critic) sees all perspectives, others don't
- 25 Python tools total (stdlib only, no dependencies)

52 new files, 10 modified, 10,862 new lines.
Total C-suite ecosystem: 134 files, 39,131 lines.

* fix: connect all dots — Chief of Staff routes to all 28 skills

- Added complementary skills registry to routing-matrix.md
- Chief of Staff SKILL.md now lists all 28 skills in ecosystem
- Added integration tables to scenario-war-room and competitive-intel
- Badge: 116 → 134 skills
- README: C-Level Advisory count 10 → 28

Quality audit passed:
 All 10 roles: company-context, reasoning, isolation, invocation
 All 6 phases in board meeting
 Two-layer memory with DO_NOT_RESURFACE
 Loop prevention (no self-invoke, max depth 2, no circular)
 All /em: commands present
 All complementary skills cross-reference roles
 Chief of Staff routes to every skill in ecosystem

* refactor: CEO + CTO advisors upgraded to C-suite parity

Both roles now match the structural standard of all new roles:
- CEO: 11.7KB → 6.8KB SKILL.md (heavy content stays in references)
- CTO: 10KB → 7.2KB SKILL.md (heavy content stays in references)

Added to both:
- Integration table (who they work with and when)
- Key diagnostic questions
- Structured metrics dashboard table
- Consistent section ordering (Keywords → Quick Start → Responsibilities → Questions → Metrics → Red Flags → Integration → Reasoning → Context)

CEO additions:
- Stage-adaptive temporal horizons (seed=3m/6m/12m → B+=1y/3y/5y)
- Cross-references to culture-architect and board-deck-builder

CTO additions:
- Key Questions section (7 diagnostic questions)
- Structured metrics table (DORA + debt + team + architecture + cost)
- Cross-references to all peer roles

All 10 roles now pass structural parity:  Keywords  QuickStart  Questions  Metrics  RedFlags  Integration

* feat: add proactive triggers + output artifacts to all 10 roles

Every C-suite role now specifies:
- Proactive Triggers: 'surface these without being asked' — context-driven
  early warnings that make advisors proactive, not reactive
- Output Artifacts: concrete deliverables per request type (what you ask →
  what you get)

CEO: runway alerts, board prep triggers, strategy review nudges
CTO: deploy frequency monitoring, tech debt thresholds, bus factor flags
COO: blocker detection, scaling threshold warnings, cadence gaps
CPO: retention curve monitoring, portfolio dog detection, research gaps
CMO: CAC trend monitoring, positioning gaps, budget staleness
CFO: runway forecasting, burn multiple alerts, scenario planning gaps
CRO: NRR monitoring, pipeline coverage, pricing review triggers
CISO: audit overdue alerts, compliance gaps, vendor risk
CHRO: retention risk, comp band gaps, org scaling thresholds
Executive Mentor: board prep triggers, groupthink detection, hard call surfacing

This transforms the C-suite from reactive advisors into proactive partners.

* feat: User Communication Standard — structured output for all roles

Defines 3 output formats in agent-protocol/SKILL.md:

1. Standard Output: Bottom Line → What → Why → How to Act → Risks → Your Decision
2. Proactive Alert: What I Noticed → Why It Matters → Action → Urgency (🔴🟡)
3. Board Meeting: Decision Required → Perspectives → Agree/Disagree → Critic → Action Items

10 non-negotiable rules:
- Bottom line first, always
- Results and decisions only (no process narration)
- What + Why + How for every finding
- Actions have owners and deadlines ('we should consider' is banned)
- Decisions framed as options with trade-offs
- Founder is the highest authority — roles recommend, founder decides
- Risks are concrete (if X → Y, costs $Z)
- Max 5 bullets per section
- No jargon without explanation
- Silence over fabricated updates

All 10 roles reference this standard.
Chief of Staff enforces it as a quality gate.
Board meeting Phase 4 uses the Board Meeting Output format.

* feat: Internal Quality Loop — verification before delivery

No role presents to the founder without passing verification:

Step 1: Self-Verification (every role, every time)
  - Source attribution: where did each data point come from?
  - Assumption audit: [VERIFIED] vs [ASSUMED] tags on every finding
  - Confidence scoring: 🟢 high / 🟡 medium / 🔴 low per finding
  - Contradiction check against company-context + decision log
  - 'So what?' test: every finding needs a business consequence

Step 2: Peer Verification (cross-functional)
  - Financial claims → CFO validates math
  - Revenue projections → CRO validates pipeline backing
  - Technical feasibility → CTO validates
  - People/hiring impact → CHRO validates
  - Skip for single-domain, low-stakes questions

Step 3: Critic Pre-Screen (high-stakes only)
  - Irreversible decisions, >20% runway impact, strategy changes
  - Executive Mentor finds weakest point before founder sees it
  - Suspicious consensus triggers mandatory pre-screen

Step 4: Course Correction (after founder feedback)
  - Approve → log + assign actions
  - Modify → re-verify changed parts
  - Reject → DO_NOT_RESURFACE + learn why
  - 30/60/90 day post-decision review

Board meeting contributions now require self-verified format with
confidence tags and source attribution on every finding.

* fix: resolve PR review issues 1, 4, and minor observation

Issue 1: c-level-advisor/CLAUDE.md — completely rewritten
  - Was: 2 skills (CEO, CTO only), dated Nov 2025
  - Now: full 28-skill ecosystem map with architecture diagram,
    all roles/orchestration/cross-cutting/culture skills listed,
    design decisions, integration with other domains

Issue 4: Root CLAUDE.md — updated all stale counts
  - 87 → 134 skills across all 3 references
  - C-Level: 2 → 33 (10 roles + 5 mentor commands + 18 complementary)
  - Tool count: 160+ → 185+
  - Reference count: 200+ → 250+

Minor observation: Documented plugin.json convention
  - Explained in c-level-advisor/CLAUDE.md that only executive-mentor
    has plugin.json because only it has slash commands (/em: namespace)
  - Other skills are invoked by name through Chief of Staff or directly

Also fixed: README.md 88+ → 134 in two places (first line + skills section)

* fix: update all plugin/index registrations for 28-skill C-suite

1. c-level-advisor/.claude-plugin/plugin.json — v2.0.0
   - Was: 2 skills, generic description
   - Now: all 28 skills listed with descriptions, all 25 scripts,
     namespace 'cs', full ecosystem description

2. .codex/skills-index.json — added 18 complementary skills
   - Was: 10 roles only
   - Now: 28 total c-level entries (10 roles + 6 orchestration +
     6 cross-cutting + 6 culture)
   - Each with full description for skill discovery

3. .claude-plugin/marketplace.json — updated c-level-skills entry
   - Was: generic 2-skill description
   - Now: v2.0.0, full 28-skill ecosystem description,
     skills_count: 28, scripts_count: 25

* feat: add root SKILL.md for c-level-advisor ClawHub package

---------

Co-authored-by: Leo <leo@openclaw.ai>
2026-03-06 01:35:08 +01:00

403 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Burn Rate & Runway Calculator
==============================
Models startup runway across base/bull/bear scenarios, incorporating
a hiring plan and revenue trajectory. Outputs months of runway,
cash-out dates, and decision trigger points.
Usage:
python burn_rate_calculator.py
python burn_rate_calculator.py --csv # export to CSV
Stdlib only. No dependencies.
"""
import argparse
import csv
import io
import sys
from dataclasses import dataclass, field
from datetime import date, timedelta
from typing import Optional
# ---------------------------------------------------------------------------
# Data structures
# ---------------------------------------------------------------------------
@dataclass
class HiringEntry:
"""A planned hire."""
month: int # months from model start (1-indexed)
role: str
department: str # "sales", "engineering", "cs", "ga"
annual_salary: float
benefits_pct: float = 0.22 # benefits as % of salary
recruiting_cost: float = 0.0 # one-time recruiting fee
@dataclass
class RevenueEntry:
"""Monthly revenue data point (historical or projected)."""
month: int
mrr: float # monthly recurring revenue
one_time: float = 0.0
@dataclass
class ModelConfig:
"""Master configuration for a runway scenario."""
name: str
starting_cash: float
starting_mrr: float
starting_headcount: int
avg_loaded_salary: float # average fully-loaded salary per current employee
base_non_headcount_opex: float # monthly non-headcount costs (infra, tools, etc.)
gross_margin_pct: float # 0.01.0
mrr_growth_rate: float # monthly MoM growth rate, 0.01.0
hiring_plan: list[HiringEntry] = field(default_factory=list)
model_months: int = 24
start_date: Optional[date] = None
@dataclass
class MonthResult:
"""Single month output."""
month: int
label: str # e.g. "Month 1 (Apr 2025)"
mrr: float
gross_profit: float
headcount: int
headcount_cost: float # total loaded headcount cost this month
other_opex: float
gross_burn: float
net_burn: float
cash_start: float
cash_end: float
runway_months: float # projected runway from this month
cumulative_new_arr: float # for burn multiple
# ---------------------------------------------------------------------------
# Core calculator
# ---------------------------------------------------------------------------
class RunwayCalculator:
def __init__(self, config: ModelConfig):
self.cfg = config
def run(self) -> list[MonthResult]:
cfg = self.cfg
results = []
# Build headcount schedule: month -> list of new hires starting that month
hire_by_month: dict[int, list[HiringEntry]] = {}
for h in cfg.hiring_plan:
hire_by_month.setdefault(h.month, []).append(h)
# Track existing employees
active_employees: list[dict] = []
for _ in range(cfg.starting_headcount):
active_employees.append({
"monthly_loaded": cfg.avg_loaded_salary / 12 * 1.0,
"start_month": 0,
})
cash = cfg.starting_cash
mrr = cfg.starting_mrr
cumulative_new_arr = 0.0
starting_mrr = cfg.starting_mrr
for m in range(1, cfg.model_months + 1):
# Process new hires this month
one_time_recruiting = 0.0
if m in hire_by_month:
for hire in hire_by_month[m]:
monthly_loaded = (
hire.annual_salary * (1 + hire.benefits_pct) / 12
)
active_employees.append({
"monthly_loaded": monthly_loaded,
"start_month": m,
})
one_time_recruiting += hire.recruiting_cost
# Revenue this month
mrr = mrr * (1 + cfg.mrr_growth_rate)
gross_profit = mrr * cfg.gross_margin_pct
# Headcount cost
headcount_cost = sum(e["monthly_loaded"] for e in active_employees)
headcount_cost += one_time_recruiting
# Other opex (infra, SaaS tools, office, etc.)
other_opex = cfg.base_non_headcount_opex
# Burn
gross_burn = headcount_cost + other_opex
net_burn = gross_burn - gross_profit
# Cash
cash_start = cash
cash = cash - net_burn
cash_end = cash
# Projected runway from this month (using current net burn rate)
runway = cash_end / net_burn if net_burn > 0 else float("inf")
# Cumulative new ARR (for burn multiple calc)
new_mrr_added = mrr - starting_mrr if m == 1 else mrr - results[-1].mrr
cumulative_new_arr += new_mrr_added * 12
# Label
if cfg.start_date:
month_date = date(
cfg.start_date.year,
cfg.start_date.month,
1,
) + timedelta(days=32 * (m - 1))
month_date = month_date.replace(day=1)
label = f"Month {m:02d} ({month_date.strftime('%b %Y')})"
else:
label = f"Month {m:02d}"
results.append(MonthResult(
month=m,
label=label,
mrr=mrr,
gross_profit=gross_profit,
headcount=len(active_employees),
headcount_cost=headcount_cost,
other_opex=other_opex,
gross_burn=gross_burn,
net_burn=net_burn,
cash_start=cash_start,
cash_end=cash_end,
runway_months=runway,
cumulative_new_arr=cumulative_new_arr,
))
# Stop if cash runs out
if cash_end <= 0:
break
return results
def cash_out_date(self, results: list[MonthResult]) -> Optional[str]:
"""Return the label of the month cash runs out, or None if model survives."""
for r in results:
if r.cash_end <= 0:
return r.label
return None
def burn_multiple(self, results: list[MonthResult]) -> float:
"""Burn multiple = total net burn / total net new ARR over model period."""
total_net_burn = sum(r.net_burn for r in results if r.net_burn > 0)
first_mrr = results[0].mrr / (1 + self.cfg.mrr_growth_rate) # starting mrr
total_new_arr = (results[-1].mrr - first_mrr) * 12
if total_new_arr <= 0:
return float("inf")
return total_net_burn / total_new_arr
# ---------------------------------------------------------------------------
# Reporting
# ---------------------------------------------------------------------------
def fmt_k(value: float) -> str:
"""Format as $Xk or $X.XM."""
if abs(value) >= 1_000_000:
return f"${value/1_000_000:.2f}M"
if abs(value) >= 1_000:
return f"${value/1_000:.0f}K"
return f"${value:.0f}"
def print_summary(name: str, results: list[MonthResult], calc: RunwayCalculator) -> None:
cash_out = calc.cash_out_date(results)
bm = calc.burn_multiple(results)
last = results[-1]
first = results[0]
print(f"\n{'='*60}")
print(f" SCENARIO: {name}")
print(f"{'='*60}")
print(f" Months modeled: {len(results)}")
print(f" Cash out: {cash_out or 'Does not run out in model period'}")
print(f" Ending cash: {fmt_k(last.cash_end)}")
print(f" Final runway: {last.runway_months:.1f} months")
print(f" Starting MRR: {fmt_k(first.mrr)}")
print(f" Ending MRR: {fmt_k(last.mrr)}")
print(f" Ending headcount: {last.headcount}")
print(f" Burn multiple: {bm:.2f}x")
print(f" Avg net burn: {fmt_k(sum(r.net_burn for r in results)/len(results))}/mo")
# Decision triggers
print(f"\n Decision Triggers:")
triggers = {9: "⚠️ START FUNDRAISE", 6: "🔴 COST REDUCTION PLAN", 4: "🚨 EXECUTE CUTS / BRIDGE"}
shown = set()
for r in results:
for threshold, label in triggers.items():
if r.runway_months <= threshold and threshold not in shown:
print(f" {r.label}: {label} (runway = {r.runway_months:.1f} mo)")
shown.add(threshold)
def print_monthly_table(results: list[MonthResult], max_rows: int = 24) -> None:
header = f"{'Month':<22} {'MRR':>10} {'Hdct':>6} {'Net Burn':>12} {'Cash':>12} {'Runway':>8}"
print(f"\n{header}")
print("-" * len(header))
for r in results[:max_rows]:
runway_str = f"{r.runway_months:.1f}mo" if r.runway_months != float("inf") else ""
print(
f"{r.label:<22} "
f"{fmt_k(r.mrr):>10} "
f"{r.headcount:>6} "
f"{fmt_k(r.net_burn):>12} "
f"{fmt_k(r.cash_end):>12} "
f"{runway_str:>8}"
)
def export_csv(scenarios: list[tuple[str, list[MonthResult]]]) -> str:
buf = io.StringIO()
writer = csv.writer(buf)
writer.writerow([
"Scenario", "Month", "Label", "MRR", "Gross Profit", "Headcount",
"Headcount Cost", "Other Opex", "Gross Burn", "Net Burn",
"Cash Start", "Cash End", "Runway Months"
])
for name, results in scenarios:
for r in results:
writer.writerow([
name, r.month, r.label,
round(r.mrr, 2), round(r.gross_profit, 2), r.headcount,
round(r.headcount_cost, 2), round(r.other_opex, 2),
round(r.gross_burn, 2), round(r.net_burn, 2),
round(r.cash_start, 2), round(r.cash_end, 2),
round(r.runway_months, 2),
])
return buf.getvalue()
# ---------------------------------------------------------------------------
# Sample data
# ---------------------------------------------------------------------------
def make_sample_configs() -> list[ModelConfig]:
"""
Sample company: Series A SaaS startup
- $3M cash on hand (post Series A)
- $125K MRR (~$1.5M ARR)
- 18 employees, $150K avg salary
- $80K/mo non-headcount opex (infra, tools, office)
- 72% gross margin
"""
common_kwargs = dict(
starting_cash=3_000_000,
starting_mrr=125_000,
starting_headcount=18,
avg_loaded_salary=150_000,
base_non_headcount_opex=80_000,
gross_margin_pct=0.72,
model_months=24,
start_date=date(2025, 1, 1),
)
# Base: 10% MoM growth, moderate hiring
base_hiring = [
HiringEntry(month=2, role="AE #1", department="sales", annual_salary=120_000, recruiting_cost=18_000),
HiringEntry(month=3, role="Senior SWE #1", department="engineering", annual_salary=160_000, recruiting_cost=24_000),
HiringEntry(month=5, role="SDR #1", department="sales", annual_salary=80_000, recruiting_cost=12_000),
HiringEntry(month=6, role="CSM #1", department="cs", annual_salary=90_000, recruiting_cost=13_500),
HiringEntry(month=8, role="AE #2", department="sales", annual_salary=120_000, recruiting_cost=18_000),
HiringEntry(month=9, role="Senior SWE #2", department="engineering", annual_salary=165_000, recruiting_cost=24_750),
HiringEntry(month=12, role="Controller", department="ga", annual_salary=130_000, recruiting_cost=19_500),
HiringEntry(month=14, role="AE #3", department="sales", annual_salary=125_000, recruiting_cost=18_750),
HiringEntry(month=15, role="ML Engineer", department="engineering", annual_salary=175_000, recruiting_cost=26_250),
HiringEntry(month=18, role="AE #4", department="sales", annual_salary=125_000, recruiting_cost=18_750),
]
# Bull: 15% MoM growth, full hiring plan
bull_hiring = base_hiring + [
HiringEntry(month=4, role="Marketing Manager", department="sales", annual_salary=110_000, recruiting_cost=16_500),
HiringEntry(month=7, role="Senior SWE #3", department="engineering", annual_salary=165_000, recruiting_cost=24_750),
HiringEntry(month=10, role="AE #5", department="sales", annual_salary=125_000, recruiting_cost=18_750),
HiringEntry(month=13, role="DevOps Engineer", department="engineering", annual_salary=150_000, recruiting_cost=22_500),
HiringEntry(month=16, role="AE #6", department="sales", annual_salary=125_000, recruiting_cost=18_750),
]
# Bear: 5% MoM growth, hiring freeze after month 3
bear_hiring = [
HiringEntry(month=2, role="AE #1", department="sales", annual_salary=120_000, recruiting_cost=18_000),
HiringEntry(month=3, role="Senior SWE #1", department="engineering", annual_salary=160_000, recruiting_cost=24_000),
]
return [
ModelConfig(name="BULL (15% MoM, full hiring)", mrr_growth_rate=0.15, hiring_plan=bull_hiring, **common_kwargs),
ModelConfig(name="BASE (10% MoM, planned hiring)", mrr_growth_rate=0.10, hiring_plan=base_hiring, **common_kwargs),
ModelConfig(name="BEAR ( 5% MoM, hiring freeze M3+)", mrr_growth_rate=0.05, hiring_plan=bear_hiring, **common_kwargs),
ModelConfig(name="DISTRESS (0% growth, freeze now)", mrr_growth_rate=0.00, hiring_plan=[], **common_kwargs),
]
# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------
def main() -> None:
parser = argparse.ArgumentParser(description="Startup Burn Rate & Runway Calculator")
parser.add_argument("--csv", action="store_true", help="Export full monthly data as CSV to stdout")
parser.add_argument("--scenario", choices=["bull", "base", "bear", "distress", "all"], default="all")
args = parser.parse_args()
configs = make_sample_configs()
if args.scenario != "all":
configs = [c for c in configs if args.scenario.upper() in c.name.upper()]
all_results: list[tuple[str, list[MonthResult]]] = []
print("\n" + "="*60)
print(" BURN RATE & RUNWAY CALCULATOR")
print(" Sample Company: Series A SaaS Startup")
print(" Starting cash: $3M | Starting MRR: $125K | 18 employees")
print("="*60)
for cfg in configs:
calc = RunwayCalculator(cfg)
results = calc.run()
all_results.append((cfg.name, results))
print_summary(cfg.name, results, calc)
print_monthly_table(results)
# Comparison summary
print("\n" + "="*60)
print(" SCENARIO COMPARISON")
print("="*60)
print(f" {'Scenario':<40} {'Runway':>8} {'Cash Out':<30} {'Burn Mult':>10}")
print(" " + "-"*88)
for cfg, (name, results) in zip(configs, all_results):
calc = RunwayCalculator(cfg)
cash_out = calc.cash_out_date(results) or "Survives model period"
bm = calc.burn_multiple(results)
final_runway = results[-1].runway_months
runway_str = f"{final_runway:.1f}mo" if final_runway != float("inf") else ""
bm_str = f"{bm:.2f}x" if bm != float("inf") else ""
print(f" {name:<40} {runway_str:>8} {cash_out:<30} {bm_str:>10}")
print("\n Decision Trigger Reference:")
print(" 9 months runway → Start fundraise process")
print(" 6 months runway → Begin cost reduction planning")
print(" 4 months runway → Execute cuts; explore bridge financing")
print(" 3 months runway → Emergency plan only")
if args.csv:
print("\n\n--- CSV EXPORT ---\n")
sys.stdout.write(export_csv(all_results))
if __name__ == "__main__":
main()