
Culture Architect
- 79 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
Culture Architect is a Claude skill that builds and measures company culture as operational behavior using values-to-behaviors translation, culture codes, health assessments, and rituals.
About
Culture Architect helps founders and leaders build company culture as an operational system of observable behaviors rather than aspirational slogans. It runs mission/vision/values workshops, translates each value into behavioral anchors, creates culture codes, assesses culture health, and manages culture debt. A leader uses it when defining values, diagnosing culture problems, scaling through rapid growth, or integrating teams after M&A.
- Translates company values into observable behavioral anchors with cost/trade-off tests
- Ships Python tools for culture survey analysis, engagement tracking, and values-alignment scoring
- Covers culture code creation, culture health assessment, and stage-based rituals from 5 to 500 people
Culture Architect by the numbers
- 79 all-time installs (skills.sh)
- Ranked #1,456 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
culture-architect capabilities & compatibility
- Capabilities
- decision logger
- Use cases
- planning · project management
- Pricing
- Free
What culture-architect says it does
Culture is what you DO, not what you SAY. This skill builds culture as an operational system -- observable behaviors, measurable health, and rituals that scale from 5 people to 500.
Culture = (What you reward) + (What you tolerate) + (What you celebrate)
3-5 values maximum | More than 5 and none are memorable
npx skills add https://github.com/borghei/claude-skills --skill culture-architectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 79 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Define, measure, and evolve company culture and values as concrete behaviors and rituals.
Who is it for?
Founders and executives operationalizing company values and diagnosing culture health as an organization scales.
Skip if: Writing or reviewing software; it produces org frameworks and surveys, not code.
When should I use this skill?
Building company values, assessing culture health, designing rituals, creating a culture code, or handling a culture clash or M&A integration.
What you get
Values expressed as observable behavioral anchors, a public culture code, and measurable culture-health signals.
- values-to-behaviors value cards
- culture code document
- culture health assessment
By the numbers
- 3-5 values maximum rule
- 90-minute values-to-behaviors translation workshop
- 3 Python culture-analysis scripts
Files
Culture Architect
Culture is what you DO, not what you SAY. This skill builds culture as an operational system -- observable behaviors, measurable health, and rituals that scale from 5 people to 500.
Keywords
culture, company culture, values, mission, vision, culture code, cultural rituals, culture health, values-to-behaviors, founder culture, culture debt, value-washing, culture assessment, culture survey, psychological safety, culture scaling, engagement, eNPS, remote culture, hybrid culture, culture clash, employer brand, onboarding culture, performance culture, recognition
---
Core Principle
Culture = (What you reward) + (What you tolerate) + (What you celebrate)
If your values say "transparency" but you punish bearers of bad news, your real value is "optics." Culture is not aspirational. It is descriptive. The work is closing the gap between stated and actual.
---
Culture Diagnostic Decision Tree
START: "How is our culture?"
|
v
[Run the Values Audit]
Ask: "What did the last person who got promoted demonstrate?"
|
+-- Answer matches stated values --> Values are real. Check transmission.
| |
| v
| [Can a 30-day employee describe the culture accurately?]
| +-- YES --> Culture is operational. Maintain and evolve.
| +-- NO --> Transmission gap. Fix onboarding and rituals.
|
+-- Answer differs from stated values --> Values are performative.
|
v
[Do leaders model the real (non-stated) values?]
+-- YES --> Rewrite values to match reality, then iterate.
+-- NO --> Deeper problem: no coherent culture exists. Build from scratch.---
Framework 1: Mission / Vision / Values Workshop
Mission (Why We Exist)
| Element | Test | Example |
|---|---|---|
| Present-tense | Is it about what we do now, not what we aspire to? | "We reduce preventable falls in elderly care" |
| Specific | Could a competitor claim the exact same thing? If yes, too generic. | Not "We make the world better" |
| Meaningful | Would something be lost if we disappeared? | Answer must be concrete |
Vision (What Winning Looks Like)
| Quality | Bad | Good |
|---|---|---|
| Specificity | "Be the market leader" | "Every care home in Europe uses our system by 2030" |
| Falsifiability | "Transform healthcare" | "Reduce fall-related injuries by 50% in partner facilities" |
| Timeline | No date | 5-10 year horizon with milestones |
Values (What We Actually Do)
| Rule | Explanation |
|---|---|
| 3-5 values maximum | More than 5 and none are memorable |
| Derived from observation | "What did our best hire do that nobody asked?" |
| Each has behavioral anchors | Specific enough to judge against |
| Include the tension | Good values have a cost ("Speed" means "we accept some risk") |
---
Framework 2: Values-to-Behaviors Translation
This is the work that makes values operational. Every value needs concrete behavioral anchors.
| Value | Vague Version | Behavioral Anchor | How You'd Observe It |
|---|---|---|---|
| Transparency | "We're open and honest" | "We share bad news within 24 hours, including to our manager" | Bad news travels fast, no surprises |
| Ownership | "We take responsibility" | "We don't hand off problems -- we own until resolved, even across team boundaries" | No orphaned issues |
| Speed | "We move fast" | "Decisions under $5K happen at team level, same day" | Low decision latency |
| Quality | "We don't cut corners" | "We stop the line before shipping something we're not proud of" | Teams delay launches for quality |
| Customer-first | "Customers are our priority" | "Any team member can escalate a customer issue to leadership, bypassing normal channels" | Escalation is celebrated, not punished |
Translation Workshop (90 minutes)
For each value:
Step 1: State the value in 2-3 words
Step 2: Ask "How would a new hire know we live this on day 30?"
Step 3: Write 3 observable behaviors that prove this value
Step 4: Write 3 behaviors that violate this value
Step 5: Ask "What does this value cost us? What's the trade-off?"
Step 6: If no trade-off exists, it's not a value -- it's a platitude
Output: Value card with behaviors, violations, and trade-offs---
Framework 3: Culture Code Creation
A culture code is a public document that describes how you operate. It should attract the right people and repel the wrong ones.
Culture Code Structure
| Section | Purpose | Key Question |
|---|---|---|
| 1. Who We Are | Mission, context, stage | "Why does this company exist?" |
| 2. Who Thrives Here | Specific behaviors, not adjectives | "What does success look like day-to-day?" |
| 3. Who Doesn't Thrive Here | Honest misfit description | "When have we made a bad hire? What was the pattern?" |
| 4. How We Make Decisions | Decision rights, speed expectations | "Who can decide what, and how fast?" |
| 5. How We Communicate | Channels, cadence, expectations | "What can I expect in response time and transparency?" |
| 6. How We Grow People | Career development, feedback | "What's my path here?" |
| 7. What We Expect of Leaders | Leadership behaviors | "How should managers behave?" |
Culture Code Anti-Patterns
| Anti-Pattern | Why It Fails | Better Alternative |
|---|---|---|
| "We're a family" | Families don't fire for performance | "We're a high-performing team that cares about each other" |
| Only positive traits | Not credible, doesn't help people self-select | Include "who doesn't thrive here" section |
| Aspirational, not descriptive | Creates cynicism when reality differs | Describe what IS, then iterate |
| Too long (> 15 pages) | Nobody reads it | Keep to 5-8 pages, link to details |
| Never updated | Becomes irrelevant as company scales | Review annually, update at each stage |
---
Framework 4: Culture Health Assessment
Run quarterly. Anonymous. 8-12 questions maximum.
Core Assessment Dimensions
| Dimension | Question Example | What It Measures |
|---|---|---|
| Psychological safety | "I can raise a concern without fear of negative consequences" | Trust in the system |
| Clarity | "I know how my work connects to company goals" | Strategic alignment |
| Fairness | "Decisions here are made consistently and transparently" | Trust in leadership |
| Growth | "I am learning and being challenged here" | Development opportunity |
| Trust in leadership | "I believe what leadership tells me" | Communication credibility |
| Recognition | "Good work is noticed and acknowledged" | Reward system health |
| Belonging | "I feel like I belong on this team" | Inclusion effectiveness |
| Autonomy | "I have enough freedom to do my best work" | Micromanagement detection |
Score Interpretation and Response
| Score Range | Status | Action Required | Timeline |
|---|---|---|---|
| 80-100% | Healthy | Document what works, celebrate, share practices | Maintain |
| 65-79% | Warning | Identify specific friction points, address top 2-3 | 30 days |
| 50-64% | Damaged | Leadership attention required, specific interventions | 14 days |
| < 50% | Crisis | All-hands intervention, external facilitation may be needed | Immediate |
eNPS Integration
eNPS Question: "On a scale of 0-10, how likely are you to recommend
this company as a place to work?"
Promoters (9-10) - Detractors (0-6) = eNPS
-----------------------------------------
> 50 = Exceptional
30-50 = Good
10-30 = Acceptable
0-10 = Concerning
< 0 = Crisis---
Framework 5: Cultural Rituals by Stage
Rituals are the delivery mechanism for culture. What works at 10 people breaks at 100.
Ritual Matrix
| Stage | Team Size | Key Rituals | Culture Risk |
|---|---|---|---|
| Seed | < 15 | Weekly all-hands (30 min), monthly retro, default transparency | Culture by osmosis -- works but won't scale |
| Early Growth | 15-50 | Quarterly culture survey, onboarding buddy, recognition program, leader office hours | First transmission failures appear |
| Scaling | 50-200 | Culture committee (peer-driven), values-based reviews, manager training, dept + company all-hands | Subcultures form, drift begins |
| Large | 200+ | Annual culture plan with KPIs, internal NPS, subculture management, culture integration for M&A | Culture becomes fragile without systems |
Ritual Design Template
| Element | Description |
|---|---|
| Name | Clear, memorable name for the ritual |
| Purpose | Which value does this reinforce? |
| Frequency | Weekly, monthly, quarterly, annual |
| Duration | Time commitment (shorter is better) |
| Participants | Who is involved, who leads |
| Format | In-person, remote, hybrid |
| Measurement | How do you know it's working? |
| Sunset criteria | When should this ritual be retired? |
---
Framework 6: Culture Debt
Culture debt accumulates like technical debt: small compromises that compound.
Culture Debt Inventory
| Debt Type | Example | Cost | Fix Difficulty |
|---|---|---|---|
| Tolerated bad behavior | Star performer who is toxic | Team morale, attrition | High (requires confrontation) |
| Stale values | Values from founding team, never updated | Cynicism, disengagement | Medium (requires workshop) |
| Missing rituals | No recognition system, no all-hands | Low cohesion, isolation | Low (design and implement) |
| Inconsistent enforcement | Some people held to standards, others not | Trust erosion, unfairness | High (requires consistency) |
| Osmosis-only transmission | No onboarding for culture, just happens | New hires don't get it | Medium (design onboarding) |
Culture Debt Decision Tree
START: Culture debt identified
|
v
[Is it actively causing harm?]
|
+-- YES --> [Is the cost of fixing it < cost of keeping it?]
| |
| +-- YES --> Fix immediately. This week.
| +-- NO --> Fix within 30 days. Plan the transition.
|
+-- NO --> [Will it compound if ignored for 6 months?]
|
+-- YES --> Schedule fix within 90 days
+-- NO --> Document and monitor quarterly---
Remote and Hybrid Culture
Remote Culture Operating Principles
| Principle | Implementation |
|---|---|
| Default to async | Write first, meet only when needed |
| Intentional social | Regular non-work social time (weekly) |
| Over-communicate decisions | Document reasoning, share broadly |
| Equal access | Remote participants get equal voice in hybrid meetings |
| Visible work | Regular updates so work is seen without surveillance |
Hybrid Meeting Rules
| Rule | Rationale |
|---|---|
| If one person is remote, everyone joins individually | Prevents room-vs-screen dynamic |
| Camera-optional for working sessions | Reduces fatigue |
| Shared document for all meetings | Creates equal participation |
| Record meetings with decisions | Timezone inclusion |
| No hallway decisions on hybrid days | Excludes remote team members |
---
Red Flags
- Values posted on wall, never referenced in reviews or decisions
- Star performers protected from cultural standards -- destroys credibility
- Leaders who "don't have time" for culture rituals -- signals culture isn't a priority
- New hires feel culture is "different than advertised" -- culture code is fiction
- No mechanism to raise cultural concerns safely -- problems go underground
- Culture survey results not shared with team -- breeds distrust
- Same values for 5+ years despite major scaling -- values are stale
- Founders exempt from cultural norms -- "do as I say, not as I do"
- No consequences for value violations -- values are suggestions, not standards
- Culture committee is all HR, no peers -- becomes compliance, not culture
---
Integration with C-Suite
| When... | Culture Architect Works With... | To... |
|---|---|---|
| Hiring surge | CHRO (chro-advisor) | Ensure culture fit is measured, not guessed |
| Org restructure | COO + CEO | Manage culture disruption from structure change |
| M&A or partnership | CEO + COO | Detect and resolve culture clashes early |
| Performance issues | CHRO | Separate culture misfit from skill deficit |
| Strategy pivot | CEO (ceo-advisor) | Update values that the pivot makes obsolete |
| Rapid growth | All C-suite | Scale rituals before culture dilutes |
| Change rollout | Change Management (change-management) | Cultural dimension of change |
| Operating system design | Company OS (company-os) | Culture rituals in the meeting pulse |
| Founder evolution | Founder Coach (founder-coach) | Leadership style impact on culture |
---
Proactive Triggers
- eNPS declining 2+ quarters -- investigate root cause before it becomes attrition
- Rapid hiring (> 30% headcount growth in a quarter) -- culture transmission at risk
- M&A announced -- culture integration plan needed immediately
- Star performer exhibiting toxic behavior -- address within 1 week or culture debt compounds
- Values haven't been reviewed in 2+ years -- schedule values refresh workshop
- Remote team growing without intentional culture design -- isolation and drift risk
- Exit interviews mention "culture" as departure reason -- pattern analysis needed
---
Output Artifacts
| Request | Deliverable |
|---|---|
| "Build our values" | Values workshop facilitation guide + values cards with behaviors |
| "Create a culture code" | Culture code document (5-8 pages) with all 7 sections |
| "Assess our culture health" | Survey design, score interpretation, action plan |
| "Design cultural rituals" | Ritual calendar by stage with design templates |
| "Audit culture debt" | Debt inventory with priority, cost, and fix plan |
| "Remote culture strategy" | Operating principles, tools, rituals for distributed teams |
| "M&A culture integration" | Culture comparison matrix, clash risk map, integration timeline |
---
Tool Reference
1. culture_survey_analyzer.py
Analyzes culture health survey results across 8 dimensions (psychological safety, clarity, fairness, growth, trust, recognition, belonging, autonomy). Calculates dimension scores, overall health rating, identifies strengths and risks, and generates action recommendations.
python scripts/culture_survey_analyzer.py --input survey_data.json --json
python scripts/culture_survey_analyzer.py --input survey_data.json| Flag | Type | Description |
|---|---|---|
--input | required | Path to JSON file with survey responses (dimension scores per respondent, optional department/tenure metadata) |
--json | optional | Output in JSON format instead of human-readable text |
2. values_alignment_scorer.py
Scores alignment between stated values and observed behaviors using the Competing Values Framework quadrants (Clan, Adhocracy, Market, Hierarchy). Detects gaps between current and desired culture, identifies value-washing risks, and recommends alignment actions.
python scripts/values_alignment_scorer.py --input values_data.json --json
python scripts/values_alignment_scorer.py --input values_data.json| Flag | Type | Description |
|---|---|---|
--input | required | Path to JSON file with stated values, behavioral evidence scores, and optional CVF quadrant assessments |
--json | optional | Output in JSON format instead of human-readable text |
3. engagement_tracker.py
Tracks employee engagement metrics over time including eNPS, survey scores, participation rates, and retention correlation. Detects trends, flags declining dimensions, and generates quarterly engagement reports.
python scripts/engagement_tracker.py --input engagement_data.json --json
python scripts/engagement_tracker.py --input engagement_data.json| Flag | Type | Description |
|---|---|---|
--input | required | Path to JSON file with periodic engagement data (eNPS scores, survey results, participation rates, optional attrition data) |
--json | optional | Output in JSON format instead of human-readable text |
---
Troubleshooting
| Problem | Likely Cause | Resolution |
|---|---|---|
| Values posted on wall but never referenced in decisions | Values created as aspirational exercise, not operational tool | Run values-to-behaviors workshop; tie values to performance reviews, hiring rubrics, and recognition |
| Culture survey scores declining quarter-over-quarter | Underlying issue not addressed after previous survey | Analyze by dimension to isolate the declining area; share results transparently; commit to specific actions with deadlines |
| Star performer protected from cultural standards | Leadership avoidance or fear of losing output | Address within 1 week; culture debt compounds daily; document impact on team morale and attrition |
| New hires say culture is "different than advertised" | Culture code describes aspiration, not reality | Rewrite culture code to describe what IS; include "who doesn't thrive here" section honestly |
| eNPS declining but leadership claims culture is strong | Leadership disconnected from frontline experience; survey results not shared | Share survey results with full team; conduct skip-level conversations; address top 2 detractor themes |
| Remote team members feel excluded from culture | Rituals designed for in-person only; hallway decisions on hybrid days | Apply Remote Culture Operating Principles; redesign rituals for hybrid; enforce "if one remote, all remote" meeting rule |
| Culture committee produces no measurable impact | Committee is all HR, no peers; no decision authority or budget | Reconstitute with peer representatives; grant budget and decision authority; set quarterly culture OKRs |
---
Success Criteria
- Culture health score above 70% across all 8 assessment dimensions
- eNPS above 30 (Good) sustained across 4 consecutive quarters
- Values-to-behaviors translation completed for all stated values with observable anchors
- 30-day employees can accurately describe the culture without prompting
- Culture debt inventory reviewed quarterly with no "Critical" items unaddressed for more than 30 days
- Survey participation rate above 80% indicating trust in the feedback process
- Zero cultural standard exceptions for high performers (no "brilliant jerk" tolerance)
---
Scope & Limitations
In scope: Mission/vision/values workshop facilitation, values-to-behaviors translation, culture code creation, culture health assessment (8-dimension survey, eNPS), cultural rituals design by company stage, culture debt identification and management, remote/hybrid culture operating principles, M&A culture integration planning, and Competing Values Framework assessment.
Out of scope: HR policy creation (use hr-operations/), compensation and benefits design (use chro-advisor), DEI program management, employee relations and conflict resolution, performance management system design, and organizational restructuring (use coo-advisor). Tools analyze survey and engagement data; continuous culture monitoring requires integration with HR platforms.
Limitations: Culture assessment depends on honest survey responses; low participation rates (<50%) or fear of retaliation invalidate results. The Competing Values Framework provides a useful map but oversimplifies the complexity of real organizational culture. Culture change is slow (12-24 months for meaningful shifts); tools measure progress but cannot accelerate the human change process. M&A culture integration assessments are predictive, not deterministic.
---
Integration Points
- chro-advisor -- Hiring for culture fit, performance reviews tied to values, attrition analysis linked to culture health
- ceo-advisor -- Culture strategy aligns with company vision; values refresh tied to strategic pivots
- coo-advisor -- Culture rituals embedded in operating rhythm; org restructures assessed for culture impact
- change-management -- Cultural dimension of any major change initiative; resistance patterns mapped to culture type
- founder-coach -- Leadership style impact on culture; founder behavior modeling assessed against stated values
- company-os -- Culture rituals integrated into the organizational operating system meeting cadence
#!/usr/bin/env python3
"""
Culture Survey Analyzer - Analyze culture health survey results across 8 dimensions.
Calculates dimension scores, overall health rating, identifies strengths and risks,
segments by department/tenure, and generates action recommendations.
Usage:
python culture_survey_analyzer.py --input survey_data.json
python culture_survey_analyzer.py --input survey_data.json --json
"""
import argparse
import json
import sys
from datetime import datetime
from statistics import mean, stdev
DIMENSIONS = [
"psychological_safety", "clarity", "fairness", "growth",
"trust_in_leadership", "recognition", "belonging", "autonomy"
]
DIMENSION_LABELS = {
"psychological_safety": "Psychological Safety",
"clarity": "Clarity",
"fairness": "Fairness",
"growth": "Growth",
"trust_in_leadership": "Trust in Leadership",
"recognition": "Recognition",
"belonging": "Belonging",
"autonomy": "Autonomy",
}
def load_data(path):
with open(path, "r") as f:
return json.load(f)
def get_health_label(score):
if score >= 80:
return "Healthy"
elif score >= 65:
return "Warning"
elif score >= 50:
return "Damaged"
else:
return "Crisis"
def get_action_timeline(label):
return {"Healthy": "Maintain", "Warning": "30 days", "Damaged": "14 days", "Crisis": "Immediate"}.get(label, "Review")
def analyze_dimension(responses, dimension):
"""Analyze a single dimension across all responses."""
scores = []
for r in responses:
val = r.get("scores", {}).get(dimension)
if val is not None:
scores.append(val)
if not scores:
return {"score": 0, "label": "No data", "responses": 0}
avg = round(mean(scores), 1)
label = get_health_label(avg)
result = {
"score": avg,
"label": label,
"action_timeline": get_action_timeline(label),
"responses": len(scores),
"min": min(scores),
"max": max(scores),
}
if len(scores) >= 3:
result["stdev"] = round(stdev(scores), 1)
return result
def segment_analysis(responses, segment_key):
"""Analyze scores segmented by a key (department, tenure, etc.)."""
segments = {}
for r in responses:
seg = r.get(segment_key, "unknown")
if seg not in segments:
segments[seg] = []
segments[seg].append(r)
results = {}
for seg_name, seg_responses in segments.items():
dim_scores = {}
for dim in DIMENSIONS:
scores = [r.get("scores", {}).get(dim, 0) for r in seg_responses if r.get("scores", {}).get(dim) is not None]
if scores:
dim_scores[dim] = round(mean(scores), 1)
overall = round(mean(dim_scores.values()), 1) if dim_scores else 0
results[seg_name] = {
"respondents": len(seg_responses),
"overall_score": overall,
"health": get_health_label(overall),
"dimension_scores": dim_scores,
}
return results
def calculate_enps(responses):
"""Calculate eNPS from responses."""
enps_scores = [r.get("enps_score") for r in responses if r.get("enps_score") is not None]
if not enps_scores:
return None
promoters = sum(1 for s in enps_scores if s >= 9) / len(enps_scores) * 100
detractors = sum(1 for s in enps_scores if s <= 6) / len(enps_scores) * 100
enps = round(promoters - detractors, 1)
if enps > 50:
label = "Exceptional"
elif enps > 30:
label = "Good"
elif enps > 10:
label = "Acceptable"
elif enps > 0:
label = "Concerning"
else:
label = "Crisis"
return {
"score": enps,
"label": label,
"promoters_pct": round(promoters, 1),
"detractors_pct": round(detractors, 1),
"passives_pct": round(100 - promoters - detractors, 1),
"total_responses": len(enps_scores),
}
def analyze_survey(data):
"""Run full survey analysis."""
responses = data.get("responses", [])
org_name = data.get("organization", "Organization")
survey_date = data.get("survey_date", datetime.now().strftime("%Y-%m-%d"))
results = {
"timestamp": datetime.now().isoformat(),
"organization": org_name,
"survey_date": survey_date,
"total_responses": len(responses),
"participation_rate_pct": data.get("participation_rate_pct", 0),
"overall_health_score": 0,
"overall_health_label": "",
"dimension_results": {},
"strengths": [],
"risks": [],
"enps": None,
"department_analysis": {},
"tenure_analysis": {},
"recommendations": [],
}
# Analyze each dimension
dim_scores = []
for dim in DIMENSIONS:
result = analyze_dimension(responses, dim)
results["dimension_results"][dim] = result
if result["score"] > 0:
dim_scores.append(result["score"])
# Overall score
if dim_scores:
results["overall_health_score"] = round(mean(dim_scores), 1)
results["overall_health_label"] = get_health_label(results["overall_health_score"])
# Identify strengths and risks
sorted_dims = sorted(results["dimension_results"].items(), key=lambda x: x[1]["score"], reverse=True)
results["strengths"] = [
{"dimension": DIMENSION_LABELS.get(d, d), "score": info["score"]}
for d, info in sorted_dims[:3] if info["score"] >= 65
]
results["risks"] = [
{"dimension": DIMENSION_LABELS.get(d, d), "score": info["score"], "action_timeline": info["action_timeline"]}
for d, info in sorted_dims if info["score"] < 65
]
# eNPS
results["enps"] = calculate_enps(responses)
# Segment analysis
if any(r.get("department") for r in responses):
results["department_analysis"] = segment_analysis(responses, "department")
if any(r.get("tenure") for r in responses):
results["tenure_analysis"] = segment_analysis(responses, "tenure")
# Recommendations
recs = results["recommendations"]
participation = results["participation_rate_pct"]
if participation > 0 and participation < 50:
recs.append(f"Low participation ({participation}%) -- results may not be representative; address trust in anonymity")
for risk in results["risks"][:3]:
recs.append(f"Address {risk['dimension']} (score: {risk['score']}) within {risk['action_timeline']}")
if results["enps"] and results["enps"]["score"] < 10:
recs.append(f"eNPS at {results['enps']['score']} ({results['enps']['label']}) -- investigate detractor feedback")
# Department-level risks
for dept, info in results.get("department_analysis", {}).items():
if info["overall_score"] < 50:
recs.append(f"Department '{dept}' in crisis (score: {info['overall_score']}) -- targeted intervention needed")
return results
def format_text(results):
lines = [
"=" * 60,
"CULTURE HEALTH SURVEY ANALYSIS",
"=" * 60,
f"Organization: {results['organization']}",
f"Survey Date: {results['survey_date']}",
f"Responses: {results['total_responses']} (participation: {results['participation_rate_pct']}%)",
"",
f"OVERALL HEALTH: {results['overall_health_score']}/100 ({results['overall_health_label']})",
]
if results["enps"]:
lines.append(f"eNPS: {results['enps']['score']} ({results['enps']['label']}) -- "
f"Promoters: {results['enps']['promoters_pct']}%, Detractors: {results['enps']['detractors_pct']}%")
lines.append("")
lines.append("DIMENSION SCORES")
for dim in DIMENSIONS:
info = results["dimension_results"].get(dim, {})
label = DIMENSION_LABELS.get(dim, dim)
lines.append(f" {label}: {info.get('score', 0)}/100 ({info.get('label', 'N/A')}) [{info.get('action_timeline', '')}]")
if results["strengths"]:
lines.append("")
lines.append("STRENGTHS")
for s in results["strengths"]:
lines.append(f" + {s['dimension']}: {s['score']}/100")
if results["risks"]:
lines.append("")
lines.append("RISKS")
for r in results["risks"]:
lines.append(f" ! {r['dimension']}: {r['score']}/100 (action: {r['action_timeline']})")
if results["department_analysis"]:
lines.append("")
lines.append("BY DEPARTMENT")
for dept, info in sorted(results["department_analysis"].items(), key=lambda x: x[1]["overall_score"]):
lines.append(f" {dept}: {info['overall_score']}/100 ({info['health']}) -- {info['respondents']} responses")
if results["recommendations"]:
lines.append("")
lines.append("RECOMMENDATIONS")
for rec in results["recommendations"]:
lines.append(f" * {rec}")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="Analyze culture health survey results across 8 dimensions")
parser.add_argument("--input", required=True, help="Path to JSON survey data file")
parser.add_argument("--json", action="store_true", help="Output in JSON format")
args = parser.parse_args()
try:
data = load_data(args.input)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading input file: {e}", file=sys.stderr)
sys.exit(1)
results = analyze_survey(data)
if args.json:
print(json.dumps(results, indent=2))
else:
print(format_text(results))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Engagement Tracker - Track employee engagement metrics over time.
Tracks eNPS, survey scores, participation rates, and retention correlation.
Detects trends, flags declining dimensions, and generates quarterly engagement reports.
Usage:
python engagement_tracker.py --input engagement_data.json
python engagement_tracker.py --input engagement_data.json --json
"""
import argparse
import json
import sys
from datetime import datetime
def load_data(path):
with open(path, "r") as f:
return json.load(f)
def classify_enps(score):
if score > 50:
return "Exceptional"
elif score > 30:
return "Good"
elif score > 10:
return "Acceptable"
elif score > 0:
return "Concerning"
else:
return "Crisis"
def detect_trend(values):
"""Detect trend from a list of values (oldest to newest)."""
if len(values) < 2:
return "insufficient_data"
recent = values[-1]
previous = values[-2]
if len(values) >= 3:
avg_earlier = sum(values[:-1]) / len(values[:-1])
if recent > avg_earlier * 1.05:
return "improving"
elif recent < avg_earlier * 0.95:
return "declining"
return "stable"
else:
if recent > previous * 1.05:
return "improving"
elif recent < previous * 0.95:
return "declining"
return "stable"
def calculate_correlation(engagement_scores, attrition_rates):
"""Simple correlation indicator between engagement and attrition."""
if len(engagement_scores) < 3 or len(attrition_rates) < 3:
return None
n = min(len(engagement_scores), len(attrition_rates))
eng = engagement_scores[:n]
att = attrition_rates[:n]
# Check if engagement drops precede attrition increases
lag_matches = 0
for i in range(1, n):
if eng[i] < eng[i - 1] and att[i] > att[i - 1]:
lag_matches += 1
elif eng[i] > eng[i - 1] and att[i] < att[i - 1]:
lag_matches += 1
correlation_strength = round(lag_matches / max(n - 1, 1), 2)
if correlation_strength >= 0.7:
return {"strength": "strong", "score": correlation_strength, "insight": "Engagement changes strongly predict attrition changes"}
elif correlation_strength >= 0.4:
return {"strength": "moderate", "score": correlation_strength, "insight": "Some relationship between engagement and attrition"}
else:
return {"strength": "weak", "score": correlation_strength, "insight": "Engagement and attrition may be driven by different factors"}
def analyze_engagement(data):
"""Run full engagement analysis."""
org_name = data.get("organization", "Organization")
periods = data.get("periods", [])
results = {
"timestamp": datetime.now().isoformat(),
"organization": org_name,
"periods_analyzed": len(periods),
"current_state": {},
"period_results": [],
"trends": {},
"alerts": [],
"attrition_correlation": None,
"recommendations": [],
}
enps_values = []
overall_scores = []
participation_values = []
attrition_values = []
for period in periods:
period_name = period.get("period", "Unknown")
enps = period.get("enps_score", 0)
overall = period.get("overall_engagement_score", 0)
participation = period.get("participation_rate_pct", 0)
attrition = period.get("attrition_rate_pct", 0)
dimension_scores = period.get("dimension_scores", {})
enps_values.append(enps)
overall_scores.append(overall)
participation_values.append(participation)
if attrition > 0:
attrition_values.append(attrition)
period_result = {
"period": period_name,
"enps": enps,
"enps_label": classify_enps(enps),
"overall_score": overall,
"participation_rate": participation,
"attrition_rate": attrition,
"dimension_scores": dimension_scores,
"respondents": period.get("respondents", 0),
}
results["period_results"].append(period_result)
# Current state (latest period)
if results["period_results"]:
latest = results["period_results"][-1]
results["current_state"] = {
"enps": latest["enps"],
"enps_label": latest["enps_label"],
"overall_score": latest["overall_score"],
"participation_rate": latest["participation_rate"],
"attrition_rate": latest["attrition_rate"],
}
# Trends
results["trends"] = {
"enps": detect_trend(enps_values),
"overall_score": detect_trend(overall_scores),
"participation": detect_trend(participation_values),
}
# Dimension trends (if available across periods)
all_dim_names = set()
for p in periods:
all_dim_names.update(p.get("dimension_scores", {}).keys())
dimension_trends = {}
for dim in all_dim_names:
dim_values = [p.get("dimension_scores", {}).get(dim) for p in periods]
dim_values = [v for v in dim_values if v is not None]
if dim_values:
trend = detect_trend(dim_values)
dimension_trends[dim] = {
"latest": dim_values[-1] if dim_values else 0,
"trend": trend,
}
if trend == "declining":
results["alerts"].append({
"dimension": dim,
"severity": "high" if dim_values[-1] < 50 else "medium",
"message": f"{dim} declining (latest: {dim_values[-1]})",
})
results["trends"]["dimensions"] = dimension_trends
# Attrition correlation
if overall_scores and attrition_values:
results["attrition_correlation"] = calculate_correlation(overall_scores, attrition_values)
# Alerts
if results["current_state"].get("enps", 0) < 10:
results["alerts"].append({
"dimension": "eNPS",
"severity": "high",
"message": f"eNPS at {results['current_state']['enps']} -- investigate detractor feedback",
})
if results["current_state"].get("participation_rate", 0) < 50:
results["alerts"].append({
"dimension": "Participation",
"severity": "high",
"message": f"Participation at {results['current_state']['participation_rate']}% -- trust in anonymity may be low",
})
if results["trends"]["enps"] == "declining":
results["alerts"].append({
"dimension": "eNPS Trend",
"severity": "high",
"message": "eNPS declining -- pattern requires root cause analysis",
})
# Recommendations
recs = results["recommendations"]
for alert in results["alerts"]:
if alert["severity"] == "high":
recs.append(f"URGENT: {alert['message']}")
if results["attrition_correlation"] and results["attrition_correlation"]["strength"] == "strong":
recs.append("Strong engagement-attrition correlation -- engagement improvements will likely reduce attrition")
if results["trends"]["overall_score"] == "declining":
recs.append("Overall engagement declining -- conduct focused listening sessions to identify root causes")
declining_dims = [d for d, info in dimension_trends.items() if info["trend"] == "declining"]
if declining_dims:
recs.append(f"Declining dimensions: {', '.join(declining_dims)} -- prioritize these in next action plan")
return results
def format_text(results):
lines = [
"=" * 60,
"ENGAGEMENT TRACKING REPORT",
"=" * 60,
f"Organization: {results['organization']}",
f"Periods Analyzed: {results['periods_analyzed']}",
f"Report Date: {results['timestamp'][:10]}",
]
cs = results["current_state"]
if cs:
lines.extend([
"",
"CURRENT STATE",
f" eNPS: {cs.get('enps', 0)} ({cs.get('enps_label', 'N/A')})",
f" Overall Score: {cs.get('overall_score', 0)}/100",
f" Participation: {cs.get('participation_rate', 0)}%",
f" Attrition: {cs.get('attrition_rate', 0)}%",
])
lines.append("")
lines.append("TRENDS")
for metric, trend in results["trends"].items():
if isinstance(trend, dict):
continue # Skip nested dimension trends
arrow = {"improving": "+", "declining": "-", "stable": "=", "insufficient_data": "?"}
lines.append(f" [{arrow.get(trend, '?')}] {metric}: {trend}")
dim_trends = results["trends"].get("dimensions", {})
if dim_trends:
lines.append("")
lines.append("DIMENSION TRENDS")
for dim, info in sorted(dim_trends.items(), key=lambda x: x[1]["latest"]):
arrow = {"improving": "+", "declining": "-", "stable": "=", "insufficient_data": "?"}
lines.append(f" [{arrow.get(info['trend'], '?')}] {dim}: {info['latest']}/100 ({info['trend']})")
lines.append("")
lines.append("PERIOD HISTORY")
for p in results["period_results"]:
lines.append(f" {p['period']}: eNPS={p['enps']} ({p['enps_label']}), score={p['overall_score']}, "
f"participation={p['participation_rate']}%, attrition={p['attrition_rate']}%")
if results["attrition_correlation"]:
ac = results["attrition_correlation"]
lines.extend([
"",
"ENGAGEMENT-ATTRITION CORRELATION",
f" Strength: {ac['strength']} (score: {ac['score']})",
f" Insight: {ac['insight']}",
])
if results["alerts"]:
lines.append("")
lines.append("ALERTS")
for a in results["alerts"]:
lines.append(f" [{a['severity'].upper()}] {a['message']}")
if results["recommendations"]:
lines.append("")
lines.append("RECOMMENDATIONS")
for rec in results["recommendations"]:
lines.append(f" * {rec}")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="Track employee engagement metrics over time with trend detection")
parser.add_argument("--input", required=True, help="Path to JSON engagement data file")
parser.add_argument("--json", action="store_true", help="Output in JSON format")
args = parser.parse_args()
try:
data = load_data(args.input)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading input file: {e}", file=sys.stderr)
sys.exit(1)
results = analyze_engagement(data)
if args.json:
print(json.dumps(results, indent=2))
else:
print(format_text(results))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Values Alignment Scorer - Score alignment between stated values and observed behaviors.
Uses Competing Values Framework (CVF) quadrants (Clan, Adhocracy, Market, Hierarchy).
Detects gaps between current and desired culture, identifies value-washing risks,
and recommends alignment actions.
Usage:
python values_alignment_scorer.py --input values_data.json
python values_alignment_scorer.py --input values_data.json --json
"""
import argparse
import json
import sys
from datetime import datetime
CVF_QUADRANTS = {
"clan": {
"label": "Clan (Collaborate)",
"focus": "Internal focus + Flexibility",
"traits": ["teamwork", "mentoring", "participation", "loyalty", "morale"],
},
"adhocracy": {
"label": "Adhocracy (Create)",
"focus": "External focus + Flexibility",
"traits": ["innovation", "risk-taking", "agility", "experimentation", "entrepreneurship"],
},
"market": {
"label": "Market (Compete)",
"focus": "External focus + Stability",
"traits": ["competition", "results", "achievement", "market_share", "goal_setting"],
},
"hierarchy": {
"label": "Hierarchy (Control)",
"focus": "Internal focus + Stability",
"traits": ["efficiency", "consistency", "process", "compliance", "predictability"],
},
}
def load_data(path):
with open(path, "r") as f:
return json.load(f)
def score_value_alignment(stated, observed):
"""Score alignment between stated and observed behavioral evidence."""
if observed >= stated * 0.9:
return {"score": round((observed / max(stated, 1)) * 100, 1), "status": "Aligned"}
elif observed >= stated * 0.6:
gap = round(stated - observed, 1)
return {"score": round((observed / max(stated, 1)) * 100, 1), "status": "Gap", "gap": gap}
else:
gap = round(stated - observed, 1)
return {"score": round((observed / max(stated, 1)) * 100, 1), "status": "Value-washing risk", "gap": gap}
def analyze_cvf(cvf_data):
"""Analyze Competing Values Framework quadrant distribution."""
if not cvf_data:
return None
current = cvf_data.get("current", {})
desired = cvf_data.get("desired", {})
# Validate totals should be ~100
current_total = sum(current.values())
desired_total = sum(desired.values())
quadrant_analysis = {}
for q_key, q_info in CVF_QUADRANTS.items():
curr = current.get(q_key, 0)
des = desired.get(q_key, 0)
shift = round(des - curr, 1)
quadrant_analysis[q_key] = {
"label": q_info["label"],
"current_pct": curr,
"desired_pct": des,
"shift_needed": shift,
"direction": "increase" if shift > 0 else ("decrease" if shift < 0 else "maintain"),
}
# Dominant culture
dominant_current = max(current, key=current.get) if current else None
dominant_desired = max(desired, key=desired.get) if desired else None
return {
"quadrants": quadrant_analysis,
"dominant_current": CVF_QUADRANTS.get(dominant_current, {}).get("label", "Unknown"),
"dominant_desired": CVF_QUADRANTS.get(dominant_desired, {}).get("label", "Unknown"),
"culture_shift_needed": dominant_current != dominant_desired,
}
def analyze_values(data):
"""Run full values alignment analysis."""
org_name = data.get("organization", "Organization")
values = data.get("values", [])
cvf_data = data.get("cvf_assessment", {})
results = {
"timestamp": datetime.now().isoformat(),
"organization": org_name,
"values_count": len(values),
"overall_alignment_score": 0,
"overall_alignment_label": "",
"value_assessments": [],
"aligned_values": [],
"gap_values": [],
"washing_risks": [],
"cvf_analysis": None,
"recommendations": [],
}
alignment_scores = []
for val in values:
name = val.get("name", "Unnamed")
stated_importance = val.get("stated_importance", 10) # 1-10
behavioral_evidence = val.get("behavioral_evidence_score", 0) # 1-10
behaviors = val.get("observable_behaviors", [])
violations = val.get("observed_violations", [])
trade_off = val.get("trade_off", "Not defined")
alignment = score_value_alignment(stated_importance, behavioral_evidence)
has_trade_off = trade_off != "Not defined" and trade_off != ""
assessment = {
"name": name,
"stated_importance": stated_importance,
"behavioral_evidence": behavioral_evidence,
"alignment_score": alignment["score"],
"alignment_status": alignment["status"],
"gap": alignment.get("gap", 0),
"observable_behaviors": behaviors,
"violations_observed": violations,
"trade_off_defined": has_trade_off,
"trade_off": trade_off,
}
# Flag platitudes (no trade-off defined)
if not has_trade_off:
assessment["warning"] = "No trade-off defined -- may be a platitude, not a real value"
results["value_assessments"].append(assessment)
alignment_scores.append(alignment["score"])
if alignment["status"] == "Aligned":
results["aligned_values"].append(name)
elif alignment["status"] == "Gap":
results["gap_values"].append({"name": name, "gap": alignment.get("gap", 0)})
elif alignment["status"] == "Value-washing risk":
results["washing_risks"].append({"name": name, "gap": alignment.get("gap", 0)})
# Overall alignment
if alignment_scores:
results["overall_alignment_score"] = round(sum(alignment_scores) / len(alignment_scores), 1)
score = results["overall_alignment_score"]
if score >= 80:
results["overall_alignment_label"] = "Strong alignment"
elif score >= 60:
results["overall_alignment_label"] = "Moderate alignment -- gaps to address"
elif score >= 40:
results["overall_alignment_label"] = "Weak alignment -- significant gaps"
else:
results["overall_alignment_label"] = "Values are performative -- rebuild from reality"
# CVF analysis
if cvf_data:
results["cvf_analysis"] = analyze_cvf(cvf_data)
# Recommendations
recs = results["recommendations"]
if results["washing_risks"]:
names = ", ".join(w["name"] for w in results["washing_risks"])
recs.append(f"VALUE-WASHING RISK: {names} -- stated importance far exceeds behavioral evidence")
recs.append("Either invest in making these values real or rewrite values to match actual culture")
platitudes = [a for a in results["value_assessments"] if not a["trade_off_defined"]]
if platitudes:
recs.append(f"{len(platitudes)} values have no defined trade-off -- run values-to-behaviors workshop")
if len(values) > 5:
recs.append(f"{len(values)} values defined -- reduce to 3-5 maximum for memorability")
if results["cvf_analysis"] and results["cvf_analysis"]["culture_shift_needed"]:
recs.append(
f"Culture shift needed: {results['cvf_analysis']['dominant_current']} -> "
f"{results['cvf_analysis']['dominant_desired']} -- plan for 12-24 month transition"
)
return results
def format_text(results):
lines = [
"=" * 60,
"VALUES ALIGNMENT SCORECARD",
"=" * 60,
f"Organization: {results['organization']}",
f"Values Assessed: {results['values_count']}",
f"Analysis Date: {results['timestamp'][:10]}",
"",
f"OVERALL ALIGNMENT: {results['overall_alignment_score']}% ({results['overall_alignment_label']})",
"",
"VALUE ASSESSMENTS",
]
for v in results["value_assessments"]:
status_icon = {"Aligned": "+", "Gap": "~", "Value-washing risk": "!!"}.get(v["alignment_status"], "?")
lines.append(f"\n [{status_icon}] {v['name']}")
lines.append(f" Stated: {v['stated_importance']}/10 | Evidence: {v['behavioral_evidence']}/10 | Alignment: {v['alignment_score']}%")
lines.append(f" Status: {v['alignment_status']}")
if v.get("trade_off_defined"):
lines.append(f" Trade-off: {v['trade_off']}")
else:
lines.append(f" Trade-off: NOT DEFINED (may be a platitude)")
if v.get("warning"):
lines.append(f" WARNING: {v['warning']}")
if results["aligned_values"]:
lines.append("")
lines.append(f"ALIGNED VALUES: {', '.join(results['aligned_values'])}")
if results["washing_risks"]:
lines.append("")
lines.append("VALUE-WASHING RISKS")
for w in results["washing_risks"]:
lines.append(f" !! {w['name']} (gap: {w['gap']})")
if results["cvf_analysis"]:
cvf = results["cvf_analysis"]
lines.append("")
lines.append("COMPETING VALUES FRAMEWORK")
lines.append(f" Dominant Culture: {cvf['dominant_current']}")
lines.append(f" Desired Culture: {cvf['dominant_desired']}")
lines.append(f" Shift Needed: {'Yes' if cvf['culture_shift_needed'] else 'No'}")
for q, info in cvf["quadrants"].items():
lines.append(f" {info['label']}: {info['current_pct']}% -> {info['desired_pct']}% ({info['direction']})")
if results["recommendations"]:
lines.append("")
lines.append("RECOMMENDATIONS")
for rec in results["recommendations"]:
lines.append(f" * {rec}")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="Score values alignment using CVF and behavioral evidence")
parser.add_argument("--input", required=True, help="Path to JSON values data file")
parser.add_argument("--json", action="store_true", help="Output in JSON format")
args = parser.parse_args()
try:
data = load_data(args.input)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading input file: {e}", file=sys.stderr)
sys.exit(1)
results = analyze_values(data)
if args.json:
print(json.dumps(results, indent=2))
else:
print(format_text(results))
if __name__ == "__main__":
main()
Related skills
FAQ
What does Culture Architect actually produce?
Value cards with behavioral anchors, violations and trade-offs, a public culture code, and culture-health assessments from survey and engagement data.
Does it work for M&A or rapid scaling?
Yes. Its description covers managing through rapid growth and M&A integration, and rituals designed to scale from 5 to 500 people.