Creates aligned OKRs from company strategy down to team level.
- Generates company → product → team OKR cascade
- Configurable team structure and contribution percentages
- Alignment scoring across vertical and horizontal dimensions
- Multiple output formats (dashboard, JSON)
python okr_cascade_generator.py growth
python okr_cascade_generator.py retention --teams "Engineering,Design,Data"
python okr_cascade_generator.py revenue --contribution 0.4 --json
from typing import Dict, List
from datetime import datetime
"""Generate and cascade OKRs across the organization"""
def __init__(self, teams: List[str] = None, product_contribution: float = 0.3):
Initialize OKR generator.
teams: List of team names (default: Growth, Platform, Mobile, Data)
product_contribution: Fraction of company KRs that product owns (default: 0.3)
self.teams = teams or ['Growth', 'Platform', 'Mobile', 'Data']
self.product_contribution = product_contribution
'Accelerate user acquisition and market expansion',
'Achieve product-market fit in new segments',
'Build sustainable growth engine'
'Increase MAU from {current} to {target}',
'Achieve {target}% MoM growth rate',
'Expand to {target} new markets',
'Reduce CAC by {target}%',
'Improve activation rate to {target}%'
'Create lasting customer value and loyalty',
'Deliver a superior user experience',
'Maximize customer lifetime value'
'Improve retention from {current}% to {target}%',
'Increase NPS from {current} to {target}',
'Reduce churn to below {target}%',
'Achieve {target}% product stickiness',
'Increase LTV/CAC ratio to {target}'
'Drive sustainable revenue growth',
'Optimize monetization strategy',
'Expand revenue per customer'
'Grow ARR from ${current}M to ${target}M',
'Increase ARPU by {target}%',
'Launch {target} new revenue streams',
'Achieve {target}% gross margin',
'Reduce revenue churn to {target}%'
'Lead the market through product innovation',
'Establish leadership in key capability areas',
'Build sustainable competitive differentiation'
'Launch {target} breakthrough features',
'Achieve {target}% of revenue from new products',
'File {target} patents/IP',
'Reduce time-to-market by {target}%',
'Achieve {target} innovation score'
'Improve organizational efficiency',
'Achieve operational excellence',
'Scale operations sustainably'
'Improve velocity by {target}%',
'Reduce cycle time to {target} days',
'Achieve {target}% automation',
'Improve team satisfaction to {target}',
'Reduce incidents by {target}%'
# Team focus areas for objective relevance matching
'Growth': ['acquisition', 'growth', 'activation', 'viral', 'onboarding', 'conversion'],
'Platform': ['infrastructure', 'reliability', 'scale', 'performance', 'efficiency', 'automation'],
'Mobile': ['mobile', 'app', 'ios', 'android', 'native'],
'Data': ['analytics', 'metrics', 'insights', 'data', 'measurement', 'experimentation'],
'Engineering': ['delivery', 'velocity', 'quality', 'automation', 'infrastructure'],
'Design': ['experience', 'usability', 'interface', 'user', 'accessibility'],
'Product': ['features', 'roadmap', 'prioritization', 'strategy'],
def generate_company_okrs(self, strategy: str, metrics: Dict) -> Dict:
"""Generate company-level OKRs based on strategy"""
if strategy not in self.okr_templates:
template = self.okr_templates[strategy]
'quarter': self._get_current_quarter(),
for i in range(min(3, len(template['objectives']))):
'title': template['objectives'][i],
if j < len(template['key_results']):
kr_template = template['key_results'][j]
'id': f'CO-{i+1}-KR{j+1}',
'title': self._fill_metrics(kr_template, metrics),
'current': metrics.get('current', 0),
'target': metrics.get('target', 100),
'unit': self._extract_unit(kr_template),
obj['key_results'].append(kr)
company_okrs['objectives'].append(obj)
def cascade_to_product(self, company_okrs: Dict) -> Dict:
"""Cascade company OKRs to product organization"""
'quarter': company_okrs['quarter'],
'contribution': self.product_contribution,
for company_obj in company_okrs['objectives']:
'id': f'PO-{company_obj["id"].split("-")[1]}',
'title': self._translate_to_product(company_obj['title']),
'parent_objective': company_obj['id'],
'owner': 'Head of Product',
for kr in company_obj['key_results']:
'id': f'PO-{product_obj["id"].split("-")[1]}-KR{kr["id"].split("KR")[1]}',
'title': self._translate_kr_to_product(kr['title']),
'contributes_to': kr['id'],
'current': kr['current'],
'target': kr['target'] * self.product_contribution,
'contribution_pct': self.product_contribution * 100,
product_obj['key_results'].append(product_kr)
product_okrs['objectives'].append(product_obj)
def cascade_to_teams(self, product_okrs: Dict) -> List[Dict]:
"""Cascade product OKRs to individual teams"""
team_contribution = 1.0 / len(self.teams) if self.teams else 0.25
'quarter': product_okrs['quarter'],
'contribution': team_contribution,
for product_obj in product_okrs['objectives']:
if self._is_relevant_for_team(product_obj['title'], team):
'id': f'{team[:3].upper()}-{product_obj["id"].split("-")[1]}',
'title': self._translate_to_team(product_obj['title'], team),
'parent_objective': product_obj['id'],
for kr in product_obj['key_results'][:2]:
'id': f'{team[:3].upper()}-{team_obj["id"].split("-")[1]}-KR{kr["id"].split("KR")[1]}',
'title': self._translate_kr_to_team(kr['title'], team),
'contributes_to': kr['id'],
'current': kr['current'],
'target': kr['target'] * team_contribution,
team_obj['key_results'].append(team_kr)
team_okr['objectives'].append(team_obj)
if team_okr['objectives']:
team_okrs.append(team_okr)
def generate_okr_dashboard(self, all_okrs: Dict) -> str:
"""Generate OKR dashboard view"""
dashboard.append("OKR CASCADE DASHBOARD")
dashboard.append(f"Quarter: {all_okrs.get('quarter', 'Q1 2025')}")
dashboard.append(f"Strategy: {all_okrs.get('strategy', 'growth').upper()}")
dashboard.append(f"Teams: {', '.join(self.teams)}")
dashboard.append(f"Product Contribution: {self.product_contribution * 100:.0f}%")
dashboard.append("=" * 60)
if 'company' in all_okrs:
dashboard.append("\n🏢 COMPANY OKRS\n")
for obj in all_okrs['company']['objectives']:
dashboard.append(f"📌 {obj['id']}: {obj['title']}")
for kr in obj['key_results']:
dashboard.append(f" └─ {kr['id']}: {kr['title']}")
if 'product' in all_okrs:
dashboard.append("\n🚀 PRODUCT OKRS\n")
for obj in all_okrs['product']['objectives']:
dashboard.append(f"📌 {obj['id']}: {obj['title']}")
dashboard.append(f" ↳ Supports: {obj.get('parent_objective', 'N/A')}")
for kr in obj['key_results']:
dashboard.append(f" └─ {kr['id']}: {kr['title']}")
dashboard.append("\n👥 TEAM OKRS\n")
for team_okr in all_okrs['teams']:
dashboard.append(f"\n{team_okr['team']} Team:")
for obj in team_okr['objectives']:
dashboard.append(f" 📌 {obj['id']}: {obj['title']}")
for kr in obj['key_results']:
dashboard.append(f" └─ {kr['id']}: {kr['title']}")
dashboard.append("\n\n📊 ALIGNMENT MATRIX\n")
dashboard.append("Company → Product → Teams")
dashboard.append("-" * 40)
if 'company' in all_okrs and 'product' in all_okrs:
for c_obj in all_okrs['company']['objectives']:
dashboard.append(f"\n{c_obj['id']}")
for p_obj in all_okrs['product']['objectives']:
if p_obj.get('parent_objective') == c_obj['id']:
dashboard.append(f" ├─ {p_obj['id']}")
for team_okr in all_okrs['teams']:
for t_obj in team_okr['objectives']:
if t_obj.get('parent_objective') == p_obj['id']:
dashboard.append(f" └─ {t_obj['id']} ({team_okr['team']})")
return "\n".join(dashboard)
def calculate_alignment_score(self, all_okrs: Dict) -> Dict:
"""Calculate alignment score across OKR cascade"""
'horizontal_alignment': 0,
# Vertical alignment: How well each level supports the above
if 'product' in all_okrs:
for obj in all_okrs['product']['objectives']:
if 'parent_objective' in obj:
for team in all_okrs['teams']:
for obj in team['objectives']:
if 'parent_objective' in obj:
scores['vertical_alignment'] = round((aligned_objectives / total_objectives) * 100, 1)
# Horizontal alignment: How well teams coordinate
if 'teams' in all_okrs and len(all_okrs['teams']) > 1:
shared_objectives = set()
for team in all_okrs['teams']:
for obj in team['objectives']:
parent = obj.get('parent_objective')
shared_objectives.add(parent)
scores['horizontal_alignment'] = min(100, len(shared_objectives) * 25)
# Coverage: How much of company OKRs are covered
if 'company' in all_okrs and 'product' in all_okrs:
company_krs = sum(len(obj['key_results']) for obj in all_okrs['company']['objectives'])
covered_krs = sum(len(obj['key_results']) for obj in all_okrs['product']['objectives'])
scores['coverage'] = round((covered_krs / company_krs) * 100, 1)
# Balance: Distribution across teams
objectives_per_team = [len(team['objectives']) for team in all_okrs['teams']]
avg_objectives = sum(objectives_per_team) / len(objectives_per_team)
variance = sum((x - avg_objectives) ** 2 for x in objectives_per_team) / len(objectives_per_team)
scores['balance'] = round(max(0, 100 - variance * 10), 1)
scores['overall'] = round(sum([
scores['vertical_alignment'] * 0.4,
scores['horizontal_alignment'] * 0.2,
scores['coverage'] * 0.2,
def _get_current_quarter(self) -> str:
"""Get current quarter"""
quarter = (now.month - 1) // 3 + 1
return f"Q{quarter} {now.year}"
def _fill_metrics(self, template: str, metrics: Dict) -> str:
"""Fill template with actual metrics"""
for key, value in metrics.items():
result = result.replace(f'{{{key}}}', str(value))
def _extract_unit(self, kr_template: str) -> str:
"""Extract measurement unit from KR template"""
elif 'days' in kr_template.lower():
elif 'score' in kr_template.lower():
def _translate_to_product(self, company_objective: str) -> str:
"""Translate company objective to product objective"""
'Accelerate user acquisition': 'Build viral product features',
'Achieve product-market fit': 'Validate product hypotheses',
'Build sustainable growth': 'Create product-led growth loops',
'Create lasting customer value': 'Design sticky user experiences',
'Drive sustainable revenue': 'Optimize product monetization',
'Lead the market through': 'Ship innovative features to',
'Improve organizational': 'Improve product delivery'
for key, value in translations.items():
if key in company_objective:
return company_objective.replace(key, value)
return f"Product: {company_objective}"
def _translate_kr_to_product(self, kr: str) -> str:
"""Translate KR to product context"""
'growth rate': 'feature adoption rate',
'CAC': 'product onboarding efficiency',
'retention': 'product retention',
'ARR': 'product-driven revenue',
for term, replacement in product_terms.items():
result = result.replace(term, replacement)
def _translate_to_team(self, objective: str, team: str) -> str:
"""Translate objective to team context"""
'Growth': 'acquisition and activation',
'Platform': 'infrastructure and reliability',
'Mobile': 'mobile experience',
'Data': 'analytics and insights',
'Engineering': 'technical delivery',
'Design': 'user experience',
'Product': 'product strategy'
focus = team_focus.get(team, 'delivery')
return f"{objective} through {focus}"
def _translate_kr_to_team(self, kr: str, team: str) -> str:
"""Translate KR to team context"""
def _is_relevant_for_team(self, objective: str, team: str) -> bool:
"""Check if objective is relevant for team"""
keywords = self.team_relevance.get(team, [])
objective_lower = objective.lower()
# Platform is always relevant (infrastructure supports everything)
return any(keyword in objective_lower for keyword in keywords)
def parse_teams(teams_str: str) -> List[str]:
"""Parse comma-separated team string into list"""
return [t.strip() for t in teams_str.split(',') if t.strip()]
parser = argparse.ArgumentParser(
description='Generate OKR cascade from company strategy to team level',
formatter_class=argparse.RawDescriptionHelpFormatter,
# Generate growth strategy OKRs with default teams
python okr_cascade_generator.py growth
python okr_cascade_generator.py retention --teams "Engineering,Design,Data,Growth"
# Custom product contribution percentage
python okr_cascade_generator.py revenue --contribution 0.4
python okr_cascade_generator.py innovation --json
python okr_cascade_generator.py operational --teams "Core,Platform" --contribution 0.5 --json
choices=['growth', 'retention', 'revenue', 'innovation', 'operational'],
help='Strategy type (default: growth)'
help='Comma-separated list of team names (default: Growth,Platform,Mobile,Data)'
help='Product contribution to company OKRs as decimal (default: 0.3 = 30%%)'
help='Output as JSON instead of dashboard'
help='Metrics as JSON string (default: sample metrics)'
args = parser.parse_args()
teams = parse_teams(args.teams)
metrics = json.loads(args.metrics)
if not 0 < args.contribution <= 1:
print("Error: Contribution must be between 0 and 1")
generator = OKRGenerator(teams=teams, product_contribution=args.contribution)
company_okrs = generator.generate_company_okrs(args.strategy, metrics)
product_okrs = generator.cascade_to_product(company_okrs)
team_okrs = generator.cascade_to_teams(product_okrs)
'quarter': company_okrs['quarter'],
'strategy': args.strategy,
alignment = generator.calculate_alignment_score(all_okrs)
all_okrs['alignment_scores'] = alignment
'teams': generator.teams,
'product_contribution': generator.product_contribution
print(json.dumps(all_okrs, indent=2))
dashboard = generator.generate_okr_dashboard(all_okrs)
print("\n\n🎯 ALIGNMENT SCORES")
for metric, score in alignment.items():
status = "✓" if score >= 80 else "!" if score >= 60 else "✗"
print(f"{status} {metric.replace('_', ' ').title()}: {score}%")
if alignment['overall'] >= 80:
print("\n✅ Overall alignment is GOOD (≥80%)")
elif alignment['overall'] >= 60:
print("\n⚠️ Overall alignment NEEDS ATTENTION (60-80%)")
print("\n❌ Overall alignment is POOR (<60%)")
if __name__ == "__main__":