Trình hướng dẫn tương tác để thiết kế và xác thực một thử nghiệm chaos engineering.
--- description: Interactive wizard to design and validate a chaos engineering experiment --- # /chaos-experiment Step through the design of a chaos engineering experiment using the `chaos-engineering` skill. Produces a plan, calculates blast radius, validates abort criteria, and outputs a markdown plan ready for peer review. ## Usage ``` /chaos-experiment /chaos-experiment --target checkout-svc --attack latency ``` ## Implementation ```bash SKILL=engineering/chaos-engineering/skills/chaos-engineering # Step 1: gather inputs interactively (target, hypothesis, attack, magnitude, ...) # Step 2: run experiment_designer.py to produce the plan python "$SKILL/scripts/experiment_designer.py" \ --target "$TARGET" --hypothesis "$HYPOTHESIS" \ --attack "$ATTACK" --magnitude "$MAGNITUDE" \ --duration-min "$DURATION" \ --abort-if "$ABORT" --owner "$OWNER" \ --format json > .chaos-plan.json # Step 3: calculate blast radius against the team's error budget python "$SKILL/scripts/blast_radius_calculator.py" \ --traffic-share "$TRAFFIC_SHARE" \ --user-pop "$USER_POP" \ --duration-min "$DURATION" \ --baseline-availability "$BASELINE_AVAIL" \ --expected-impact-availability "$IMPACT_AVAIL" # Step 4: render the markdown plan for peer review python "$SKILL/scripts/experiment_designer.py" \ --target "$TARGET" --hypothesis "$HYPOTHESIS" \ --attack "$ATTACK" --abort-if "$ABORT" --owner "$OWNER" ``` ## Output A markdown plan with: - Hypothesis, steady-state metric, attack, magnitude, duration - Blast radius (calculated) with risk score (GREEN/YELLOW/RED) - Abort criteria parsed from `--abort-if` - Rollback procedure - Monitoring dashboard link - Learning question ## Pre-conditions - `chaos-engineering` skill installed - Target identified - Steady-state metric and dashboard available - On-call team available - Error budget known (or use defaults) ## Post-conditions - `.chaos-plan.json` written for use with `experiment_postmortem.py` later - Markdown plan streamed for review - Recommendation printed: PROCEED / REDUCE / ABORT
Tạo đặc tả Use Case bằng Markdown theo mẫu 13 trường chuẩn của BA IT, dùng khi cần phân tích, soạn thảo hoặc rà soát Use Case.
---
name: use-case-writer
description: Generate Use Case specifications in English Markdown following the IT BA standard 13-field template (Karl Wiegers / IIBA). Use whenever a BA needs to scope, analyze, document, refine, or review a Use Case. Triggers include "write a use case", "draft UC", "use case specification", "analyze UC scope", "split feature into use cases", "review my UC", "write normal course / alternative course / exceptions", "define actors", and Vietnamese equivalents like "viết use case", "viết UC", "đặc tả use case", "phân tích use case", "review UC". Also trigger when user pastes a feature/BRD/PRD and asks to turn it into UCs. Skill enforces Cockburn's guidelines (coffee-break test, goal levels) and runs a 20-point quality checklist. Output is English Markdown with 13 fields (Actor, Description, Pre/Postconditions, Priority, Frequency, Normal/Alternative Courses, Exceptions, Includes, Special Req, Assumptions, Notes). DO NOT use for Agile User Stories, PRD/URD/SRS, or UML diagrams.
author: Phúc NT @ BA Zone
source: https://github.com/phucnt-bazone-vietnam/use-case-writer
---
# Use Case Writer — Skill for IT Business Analysts
> by **Phúc NT** · BA Zone · Digital School
This skill helps IT BAs **scope, analyze, and document Use Cases** in English Markdown following the standard 13-field template (Karl Wiegers / IIBA style), with best practices from Alistair Cockburn's "Writing Effective Use Cases" and the IIBA BABOK Guide.
Developed by **Phúc NT** as part of the **Digital School** training program by **BA Zone** — Vietnam's Business Analyst & Product Owner community.
## When to use this skill
Trigger this skill whenever the user needs to:
- Draft a new UC from a feature description, BRD, or PRD
- Refine or review an existing UC (completeness, correctness)
- Split a large feature into multiple smaller UCs (scope identification)
- Write a specific section: Normal Course, Alternative Course, Exceptions
- Validate a UC against the quality checklist
## Output rules (non-negotiable)
1. **Language**: English. Even if the user types in Vietnamese, generate the UC document in English. Use Vietnamese only when chatting with the user about the process.
2. **Format**: Markdown (`.md`). Use the 2-column table layout that mirrors the original template.
3. **Mode**: Sequential — generate section by section, **stop and wait for the user to confirm** before moving on. Never dump a full UC in one shot unless the user explicitly says "give me the full UC at once".
---
## Workflow: 4 Steps
```
Step 1: CLASSIFY INPUT → identify which mode the user is in
Step 2: SCOPE THE UC → apply 4 scoping rules + coffee-break test
Step 3: WRITE THE UC → fill the 13 fields ONE SECTION AT A TIME
Step 4: VALIDATE → run the 20-point checklist before handover
```
---
## Step 1: Classify input and pick a mode
Before writing anything, identify which mode the user is in:
| Mode | Signals | Action |
|------|---------|--------|
| **Mode A: Write new from feature** | User pastes a feature description, BRD, PRD, or says "write UC for feature X" | Go to Step 2 (scope) → Step 3 (write sequentially) |
| **Mode B: Split large feature into UC list** | User says "split into UC list", "how many UCs does this feature need", uploads a large PRD | Go deep on Step 2 (apply 3 identification techniques), output the **UC List first**, then ask the user which UC to write in detail |
| **Mode C: Refine / review existing UC** | User pastes an existing UC and asks "review this", "is it complete", "what's missing" | Skip Step 2, go directly to Step 4 (validate checklist) |
| **Mode D: Write a specific section** | User says "write the Normal Course for this UC", "add Exceptions" | Read the UC context, jump to the relevant part of Step 3 |
**Golden rule**: If input is vague (just one line), **ASK before writing** — never make things up. Ask at most 3 questions:
1. Who is the primary actor? (specific role / user class)
2. What is the actor's concrete goal in this UC?
3. Which system / module does this UC belong to?
Communicate with the user in their language (Vietnamese or English), but the UC artifact is always English.
---
## Step 2: Scope the Use Case
This is the **most important and most error-prone** part of UC writing. Read carefully.
### 2.1. Four scoping rules
**Rule 1 - Coffee-break test (Alistair Cockburn)**
After completing the UC, can the actor take a coffee break without feeling the task is unfinished? If NO → the UC is too low-level (sub-function), merge it. If YES → scope is right (user-goal level).
**Rule 2 - Goal Level (Cockburn's 3 levels)**
- **Summary level (cloud)**: UC spans multiple sessions. E.g. "Manage course enrollment lifecycle" → too high, DO NOT write as a single UC.
- **User-goal level (sea level)** ✅: 1 actor, 1 session, achieves 1 business goal. E.g. "Enroll in a Digital School course" → right level for a UC.
- **Sub-function level (fish)**: A small step inside another UC. E.g. "Verify OTP" → too low, treat as Includes inside another UC.
**Rule 3 - One Actor, One Goal, One Session**
Each UC should have EXACTLY: 1 primary actor + 1 business goal + completion in 1 continuous session. If you see 2 different goals → split into 2 UCs.
**Rule 4 - System Boundary**
A UC describes the **interaction** between actor and system, NOT the system's internals. Each step must be one of:
- Actor does something to the system (input)
- System responds to the actor (output)
If a step has neither actor nor UI → it's a design detail, not part of the UC.
### 2.2. Three techniques to identify UCs (for Mode B)
When splitting a large feature into a UC list:
**Technique 1: Goal-driven (top-down)**
List all goals for each actor → each goal = 1 candidate UC.
**Technique 2: Event-driven (external + internal triggers)**
- External events: user actions (click, submit, scheduled time)
- Internal events: system-triggered (cron job, batch process)
Each event produces a system response → candidate UC.
**Technique 3: CRUD-driven (data-centric)**
For each business entity (Learner, Course, Enrollment, Certificate…), check whether the system needs Create / Read / Update / Delete. Each = 1 candidate UC (you can merge R-U-D for the same entity if logic is similar).
### 2.3. Output of Step 2
**Mode A**: One sentence confirming scope, then ASK USER TO CONFIRM before moving to Step 3:
> "Scope confirmed: this UC is at user-goal level. Primary actor: [X]. Goal: [Y]. System boundary: [Z]. Confirm to proceed to Step 3?"
**Mode B**: A UC List table:
```
| UC ID | UC Name (verb + noun) | Primary Actor | Goal | Priority |
| UC-01 | Enroll in Digital School course | Learner | ... | High |
| UC-02 | Book 1-on-1 mentor session | Learner | ... | High |
| UC-03 | Approve learner KYC application | BO Approver | ... | Medium |
```
Then ask: "Which UC do you want me to write in detail first?"
---
## Step 3: Write the Use Case — section by section
**CRITICAL**: Generate ONE SECTION GROUP at a time, then **STOP and ask the user to confirm** before continuing. Do not dump the whole UC at once.
Read `references/template-guide.md` for detailed guidance on filling each field.
Read `references/writing-style.md` for writing conventions (active voice, numbering, anti-patterns).
### 3.1. The template (output structure)
```markdown
| **Use Case ID:** | UC-XX-YY |
| **Use Case Name:** | [Action verb + noun] |
| **Created By:** | | **Last Updated By:** | |
| **Date Created:** | | **Date Last Updated:** | |
| **Actor:** | [Primary actor] / [Secondary actors] |
| **Description:** | [2-3 sentences: why + what + outcome] |
| **Preconditions:** | 1. ... 2. ... |
| **Postconditions:** | 1. ... 2. ... |
| **Priority:** | High / Medium / Low |
| **Frequency of Use:** | [X times / unit time] |
| **Normal Course of Events:** | 1. Actor... 2. System... 3. ... |
| **Alternative Courses:**| UC-XX-YY.AC.1: [name] |
| **Exceptions:** | UC-XX-YY.EX.1: [name] |
| **Includes:** | UC-AA-BB |
| **Special Requirements:**| [Non-functional: perf, security…] |
| **Assumptions:** | 1. ... |
| **Notes and Issues:** | TBD-1: [open question] / Owner / Due |
```
Copy-ready template lives in `assets/uc-template.md`.
### 3.2. Sequential generation — the 5 section groups
Generate **in this exact order**, pause and ask confirmation after each group:
> **Group 1 — Identification + Actor + Description**
> Output: Use Case ID, Name, History (Created By / Date), Actor, Description.
> Then say: *"Group 1 done. Confirm to proceed to preconditions, postconditions, priority, frequency?"*
> **Group 2 — Conditions + Priority + Frequency**
> Output: Preconditions, Postconditions, Priority, Frequency of Use.
> Then say: *"Group 2 done. Confirm to proceed to the Normal Course?"*
> **Group 3 — Normal Course of Events**
> Output: numbered, step-by-step happy path.
> Then say: *"Normal Course done. Confirm to proceed to Alternative Courses and Exceptions?"*
> **Group 4 — Alternative Courses + Exceptions**
> Output: AC.1, AC.2…, EX.1, EX.2…
> Then say: *"Group 4 done. Confirm to proceed to the final group (Includes, Special Req, Assumptions, Notes)?"*
> **Group 5 — Includes + Special Requirements + Assumptions + Notes and Issues**
> Output: the remaining fields.
> Then say: *"All sections done. Shall I run the 20-point quality validation now?"*
**If the user requests changes** to a previous group, apply them and reconfirm before continuing.
**If the user says "skip ahead"** or "give me everything at once", honor that — but warn briefly that sequential mode catches more issues.
### 3.3. CRITICAL field-filling rules (the most common mistakes)
**Use Case ID**: Format `UC-<module>-<seq>`, e.g. `UC-LEARN-01`. Hierarchical X.Y if you have UC groups.
**Use Case Name**: MUST be "**Verb + Object**" (active voice).
- ✅ "Enroll in Digital School course", "Book mentor session", "Issue course completion certificate"
- ❌ "Enrollment" (no verb), "Learner enrolls" (actor included), "Manage courses" (vague verb)
**Actor**: Distinguish:
- *Primary actor*: initiates the UC, benefits from the outcome
- *Secondary actor*: supporting system/person (payment gateway, OTP service, LMS)
Never write "User" — be specific (Learner, Mentor, BO Admin, HR Manager, Enterprise Partner…).
**Preconditions**: Conditions that **MUST be true** before the UC starts. Distinguish from business rules!
- ✅ "Learner has logged in and has an active Digital School subscription"
- ❌ "Learner is motivated to study" (motivation — not verifiable)
**Postconditions**: System state **AFTER** successful UC completion. Must be verifiable.
- ✅ "Enrollment record saved with status='Active'; learner gains access to all course materials"
- ❌ "Learner feels satisfied" (not verifiable)
**Normal Course of Events** (most important):
- Numbered list, one action per step
- Alternate Actor / System steps (subject must be explicit)
- Each step starts with a clear subject + active verb
- **NO embedded if/else, loops, or exceptions** — those go in Alternative/Exception sections
- Storytelling style: from trigger to goal achieved
- ✅ "1. Learner selects the course on the Digital School catalog. 2. System displays course details and enrollment options. 3. Learner clicks 'Enroll Now'."
- ❌ "1. If learner has voucher, enter code; otherwise proceed to payment…" (branching embedded)
**Alternative Courses**: Different paths that **still lead to success**. E.g. paying with enterprise voucher instead of personal wallet. Format `UC-XX.AC.N` + "At step Y of Normal Course, if [condition], execute the alternative: …"
**Exceptions**: Cases where **the goal fails** (errors, validation fails, timeouts). Format `UC-XX.EX.N`. Each exception needs: trigger condition + system response + final state.
**Includes**: List of sub-UCs "called" by this UC (common functionality). E.g. UC "Enroll in course" includes UC "Process payment".
**Special Requirements**: Non-functional requirements specific to this UC:
- Performance: "Course catalog page loads ≤ 2s for 5,000 concurrent learners"
- Security: "Payment data must be encrypted in transit (TLS 1.3)"
- Usability, Reliability, Compliance…
**Assumptions**: Things assumed during analysis. Different from Preconditions — a precondition is a hard requirement; an assumption is a belief that hasn't been verified.
**Notes and Issues**: List of TBDs with format `[TBD-N] | Owner | Due date | Resolution`.
---
## Step 4: Validate against the 20-point checklist
**ALWAYS run this checklist BEFORE handing over the UC.** If any item fails, fix it or flag it to the user.
Read `references/quality-checklist.md` for the full checklist with examples. The 20 items, grouped:
### Scope & Identification (5 items)
- [ ] **C1**: UC Name follows "verb + object", active voice
- [ ] **C2**: UC is at user-goal level (passes coffee-break test)
- [ ] **C3**: UC ID is unique and follows naming convention
- [ ] **C4**: Exactly 1 primary actor + 1 clear business goal
- [ ] **C5**: System boundary is clear (not mixed with other UCs)
### Actor & Context (3 items)
- [ ] **C6**: Actor is a specific role/class, not "User"
- [ ] **C7**: Description answers WHY (reason) + WHAT (action) + OUTCOME (result)
- [ ] **C8**: Frequency of Use is quantified (not "sometimes")
### Pre/Post Conditions (3 items)
- [ ] **C9**: Preconditions are verifiable (not disguised business rules)
- [ ] **C10**: Postconditions cover the success state and all system changes
- [ ] **C11**: Preconditions are not confused with Assumptions
### Normal Course (4 items)
- [ ] **C12**: Numbered list, one action per step
- [ ] **C13**: Alternates Actor / System with clear subjects
- [ ] **C14**: NO embedded if/else/loop in the Normal Course
- [ ] **C15**: Flow runs from trigger to postcondition (no dangling step)
### Alternative & Exception (3 items)
- [ ] **C16**: Each AC specifies "at step N" + condition
- [ ] **C17**: Each Exception has trigger + system response + final state
- [ ] **C18**: Common failure modes are covered (timeout, invalid input, network, permission denied, concurrency conflict)
### Completeness (2 items)
- [ ] **C19**: Includes (if any) point to existing UCs
- [ ] **C20**: Special Requirements don't duplicate functional requirements
**Validation output**: A `Item | Status | Note` table with ✅ ❌ ⚠️ markers.
---
## Output format details
- Always produce English Markdown
- Use the 2-column table layout that matches the original template
- Save final output as a `.md` file if the user wants a downloadable file; otherwise show inline in chat
- File naming convention: `<UC-ID>_<UC-Name-kebab>.md`, e.g. `UC-LEARN-01_enroll-digital-school-course.md`
---
## References
- `references/template-guide.md` - Detailed guidance for each field (with EdTech & Digital School examples)
- `references/writing-style.md` - Writing conventions (active voice, numbering, anti-patterns)
- `references/quality-checklist.md` - 20-point checklist with pass/fail examples
- `references/examples-edtech.md` - 2 complete EdTech UC examples (Course Enrollment, Mentor Session Approval)
- `assets/uc-template.md` - Copy-ready Markdown template
- `scripts/uc_quality_checker.py` - stdlib Python tool that runs the 20-point checklist (Step 4) as deterministic heuristic checks against a finished UC Markdown file. Repo-convention addition, not part of the upstream skill; use it as a mechanical first pass before the LLM-driven review.
---
## Anti-patterns (ABSOLUTELY avoid)
1. **UC = UI flow**: Describing every button click and popup → that's a wireframe spec, not a UC
2. **UC = User Story**: A UC describes detailed interactions; a US is a one-liner "As a… I want… So that…"
3. **UC = Business Process**: A BP covers an entire business process (many people, many systems); a UC covers 1 actor + 1 system
4. **Vague verbs in UC Name**: "Manage", "Handle", "Process" — too generic. Use specific action verbs
5. **Mixing concerns**: Cramming enrollment, payment, notification into one giant UC → split using Includes
6. **Forgetting exceptions**: Writing only the happy path with no failure modes → insufficient for dev/QA
7. **Vague preconditions**: "System is ready" → meaningless. Must be verifiable
---
*Skill developed by **Phúc NT** · BA Zone · Digital School*
*Please keep attribution intact when sharing or forking this repo.*
FILE:assets/uc-template.md
# Use Case Template — Copy-Ready Markdown
Copy the template below and replace the `<...>` placeholders with actual content.
> Template by **Phúc NT** · BA Zone · Digital School
---
## UC-XX-YY: \<Use Case Name\>
| **Use Case ID:** | UC-XX-YY |
| ---: | :--- |
| **Use Case Name:** | \<Action verb + Object\> |
| **Created By:** | \<Name - Role\> | **Last Updated By:** | \<Name - Role\> |
| **Date Created:** | YYYY-MM-DD | **Date Last Updated:** | YYYY-MM-DD |
| **Actor:** | **Primary:** \<specific role, e.g. Learner / Mentor / HR Manager\>. **Secondary:** \<supporting actors, e.g. Payment Gateway, LMS, Notification Service\>. |
| ---: | :--- |
| **Description:** | \<2-3 sentences: WHY + WHAT + OUTCOME\> |
| **Preconditions:** | 1. \<condition 1, verifiable\><br>2. \<condition 2\><br>3. \<...\> |
| **Postconditions:** | 1. \<state 1 after UC completes\><br>2. \<state 2\><br>3. \<...\> |
| **Priority:** | High / Medium / Low - \<brief justification\> |
| **Frequency of Use:** | \<count / unit time\>, peak: \<...\> |
| **Normal Course of Events:** | 1. \<Actor action\><br>2. \<System response\><br>3. \<...\><br>... |
| **Alternative Courses:** | **UC-XX-YY.AC.1: \<AC name\>**<br>At step \<N\>, if \<condition\>:<br>Na. \<step\><br>Nb. \<step\><br>... → continue from step \<M\> of the Normal Course. |
| **Exceptions:** | **UC-XX-YY.EX.1: \<exception name\>**<br>Trigger: \<when it happens\><br>Response: \<what the system does\><br>Final state: \<the end state\> |
| **Includes:** | UC-AA-BB: \<sub-UC name\> (invoked at step \<N\>) |
| **Special Requirements:** | **Performance**: \<...\><br>**Security**: \<...\><br>**Reliability**: \<...\><br>**Compliance**: \<...\> |
| **Assumptions:** | 1. \<assumption 1\><br>2. \<assumption 2\> |
| **Notes and Issues:** | [TBD-1] \<question\> \| Owner: \<...\> \| Due: \<...\> \| Resolution: \<...\> |
---
*Template by **Phúc NT** · BA Zone · Digital School*
*Please keep attribution intact when distributing this template.*
FILE:references/examples-edtech.md
# Examples — 2 Complete EdTech Use Cases
Use these as reference when writing UCs. Both examples have passed the full 20-point checklist.
Compiled by **Phúc NT** for the **Digital School** program · **BA Zone**
---
## Example 1: UC-LEARN-01 — Enroll in a Digital School course
| **Use Case ID:** | UC-LEARN-01 |
| ---: | :--- |
| **Use Case Name:** | Enroll in a Digital School course |
| **Created By:** | Phúc NT - BA Zone | **Last Updated By:** | Phúc NT - BA Zone |
| **Date Created:** | 2026-05-14 | **Date Last Updated:** | 2026-05-14 |
| **Actor:** | **Primary:** Learner (registered BA Zone account, email verified). **Secondary:** Payment Gateway, Notification Service, LMS (Learning Management System). |
| ---: | :--- |
| **Description:** | When a learner discovers a course on the Digital School catalog and decides to purchase it, the learner navigates to the course page and completes enrollment via the BA Zone platform. The UC ends when the payment is confirmed, the learner's account is granted access to all course materials, and a welcome notification is sent. |
| **Preconditions:** | 1. Learner has logged in to BA Zone with a verified email address.<br>2. The selected course status is 'Published' and still has available capacity.<br>3. Learner has not previously enrolled in this course (no duplicate enrollment).<br>4. Payment Gateway is available and responsive. |
| **Postconditions:** | 1. Enrollment record is created in the Enrollments table with status='Active' and the enrollment timestamp.<br>2. Learner's account is granted read access to all published lessons of the course.<br>3. Payment transaction is recorded with status='Completed' and a unique transaction reference.<br>4. Welcome email + in-app notification is sent to the learner within 60 seconds.<br>5. Course enrollment count is incremented by 1. |
| **Priority:** | High — Core revenue-generating feature; blocks Digital School MVP go-live. |
| **Frequency of Use:** | Estimated ~500 enrollments/day platform-wide; peak ~100/hour during promotional campaigns and new course launches. |
| **Normal Course of Events:** | 1. Learner browses the Digital School course catalog and clicks on a course card.<br>2. System displays the **Course Detail** page: syllabus, instructor profile, price, and an **Enroll Now** button.<br>3. Learner clicks **Enroll Now**.<br>4. System displays the **Order Summary** screen: course name, original price, applicable discount (if any), and total amount due.<br>5. Learner selects a payment method (wallet, card, or enterprise voucher) and clicks **Proceed to Payment**.<br>6. System invokes UC-PAY-01 to process the payment.<br>7. Upon successful payment, system creates the enrollment record in the LMS and grants course access.<br>8. System displays the **Enrollment Confirmed** screen with a **Go to Course** button and a download link for the receipt.<br>9. System invokes UC-NOTI-01 to send the welcome email and push notification to the learner. |
| **Alternative Courses:** | **UC-LEARN-01.AC.1: Enroll using an enterprise voucher code**<br>At step 5 of the Normal Course, if the learner selects **Enterprise Voucher** as the payment method:<br>5a. System displays a voucher code input field.<br>5b. Learner enters the voucher code and clicks **Apply**.<br>5c. System validates the voucher against the Enterprise_Vouchers table: checks expiry date, course applicability, and remaining usage count.<br>5d. System updates the total amount to 0 VND and displays "Voucher applied — fully covered".<br>5e. Learner clicks **Confirm Enrollment** → continue from step 7 of the Normal Course (no payment gateway call needed).<br><br>**UC-LEARN-01.AC.2: Re-enroll after course expiry**<br>At step 3 of the Normal Course, if the learner had a previous expired enrollment (status='Expired') in this course:<br>3a. System detects the expired enrollment and displays a banner: "You previously enrolled in this course. Your access expired on [date]. Re-enroll to regain access?"<br>3b. Learner clicks **Re-enroll** → continue from step 4 of the Normal Course. The original enrollment record is archived; a new enrollment record is created. |
| **Exceptions:** | **UC-LEARN-01.EX.1: Payment fails at gateway**<br>Trigger: At step 6, UC-PAY-01 returns a payment failure (insufficient funds, card declined, gateway timeout).<br>Response: System displays "Payment unsuccessful. Please check your payment details and try again." with a **Try Again** button and a **Choose Different Method** link.<br>Final state: No enrollment record is created. Learner's course access remains unchanged. The failed payment attempt is logged in Payment_Logs with reason code from the gateway.<br><br>**UC-LEARN-01.EX.2: Course reaches full capacity between page load and enrollment confirmation**<br>Trigger: At step 7, LMS returns a CAPACITY_EXCEEDED error because another learner filled the last slot milliseconds earlier.<br>Response: System displays "Sorry, this course just reached full capacity. Join the waitlist to be notified when a slot opens."<br>Final state: Payment is refunded automatically within 1 business day. No enrollment record is created. Learner is offered the option to join the waitlist.<br><br>**UC-LEARN-01.EX.3: Voucher code invalid or expired**<br>Trigger: At step 5c (AC.1), the voucher code does not exist, has expired, or has been fully redeemed.<br>Response: System displays an inline error: "Voucher code is invalid or has expired. Please check with your enterprise administrator."<br>Final state: No enrollment is created. Learner can retry with a different code or choose another payment method.<br><br>**UC-LEARN-01.EX.4: LMS unavailable during enrollment**<br>Trigger: At step 7, the LMS does not respond within 10 seconds when the system attempts to create the enrollment record.<br>Response: System displays "Your payment was successful. We are setting up your course access — this may take a few minutes. Check your email for confirmation."<br>Final state: Payment is recorded as 'Completed'. A background retry job attempts to create the LMS enrollment every 2 minutes for up to 30 minutes. Learner receives email once access is confirmed. If the retry fails after 30 minutes, the support team is alerted via an automated ticket. |
| **Includes:** | UC-PAY-01: Process payment (invoked at step 6 of the Normal Course)<br>UC-NOTI-01: Send enrollment notification (invoked at step 9 of the Normal Course) |
| **Special Requirements:** | **Performance**: Course Detail page loads ≤ 2s; Order Summary and Enrollment Confirmed screens load ≤ 1s. System supports 500 concurrent enrollments without degradation.<br>**Security**: Payment card data must never be stored on BA Zone servers; all card processing is delegated to the PCI-DSS certified Payment Gateway. Voucher codes must be validated server-side only — never expose remaining usage counts to the client.<br>**Reliability**: If the LMS is unavailable at step 7, payment must NOT be rolled back — the enrollment must be retried asynchronously. No learner should pay and receive no access without a support escalation path.<br>**Usability**: The enrollment flow must be completable in ≤ 3 taps on mobile (post-payment-method selection).<br>**Compliance**: Issue a VAT invoice for all transactions ≥ 200,000 VND per Vietnamese tax regulations. |
| **Assumptions:** | 1. Payment Gateway SLA is ≥ 99.5% uptime during business hours.<br>2. Enterprise vouchers are pre-loaded into the system by BA Zone's ops team before being distributed to partners.<br>3. Learner's email is verified — welcome emails will not bounce.<br>4. LMS access provisioning is synchronous under normal conditions (< 3s). |
| **Notes and Issues:** | [TBD-1] Should learners be able to gift a course enrollment to another BA Zone user? \| Owner: Product Team \| Due: 2026-06-01 \| Resolution: TBD — deferred to phase 2.<br>[TBD-2] What is the refund policy if a learner requests a refund within 7 days of enrollment? \| Owner: Phúc NT - BA Zone \| Due: 2026-05-25 \| Resolution: TBD.<br>[NOTE] Coordinate with the Marketing team on the welcome email template — must align with the current Digital School brand guidelines. |
---
## Example 2: UC-MENTOR-03 — Approve learner 1-on-1 mentor session request
| **Use Case ID:** | UC-MENTOR-03 |
| ---: | :--- |
| **Use Case Name:** | Approve learner 1-on-1 mentor session request |
| **Created By:** | Phúc NT - BA Zone | **Last Updated By:** | Phúc NT - BA Zone |
| **Date Created:** | 2026-05-14 | **Date Last Updated:** | 2026-05-14 |
| **Actor:** | **Primary:** Mentor (BA Zone certified mentor, active mentor account). **Secondary:** Notification Service, Calendar Integration Service. |
| ---: | :--- |
| **Description:** | When a learner submits a 1-on-1 session request through the Digital School platform, the request enters the assigned mentor's queue. The mentor accesses their Mentor Portal, reviews the request details, and makes a decision: Approve, Decline, or Propose an Alternative Slot. The UC ends when the request has a final status and the learner is notified of the outcome. |
| **Preconditions:** | 1. Mentor has logged in to the BA Zone Mentor Portal with an active mentor account.<br>2. At least one session request is in the mentor's queue with status='Pending_Mentor_Review'.<br>3. The requested time slot is within the mentor's published availability window.<br>4. Learner still has at least 1 unused session quota in their current subscription. |
| **Postconditions:** | 1. Session request has a final status: 'Confirmed' / 'Declined' / 'Rescheduled'.<br>2. A decision record is saved in the Session_Decisions table with: mentor_id, timestamp, decision, reason.<br>3. If Approved: a calendar invite (Google Calendar / Outlook) is sent to both parties; session slot is blocked in the mentor's availability calendar.<br>4. Learner's session quota is decremented by 1 if the decision is 'Confirmed'.<br>5. Push notification + email is sent to the learner with the outcome within 2 minutes of the mentor's decision. |
| **Priority:** | High — Core differentiator of the Digital School Premium subscription. Directly affects learner retention. |
| **Frequency of Use:** | ~15 session requests/day per mentor. Platform-wide ~300 requests/day across 20 active mentors. Peak on Sunday evenings (learners planning their week). |
| **Normal Course of Events:** | 1. Mentor selects the **Session Requests** tab in the BA Zone Mentor Portal.<br>2. System displays the pending request queue, sorted by request submission time (oldest first), showing: learner name, requested topic, preferred date/time, and subscription tier.<br>3. Mentor clicks a request to open the **Request Detail** view.<br>4. System displays full details: learner profile, course progress summary, submitted topic/question, preferred slot, and the learner's session history with this mentor (if any).<br>5. Mentor reviews the details and clicks one of three action buttons: **Approve** / **Decline** / **Propose Alternative Slot**.<br>6. System displays a confirmation popup requesting an optional note to the learner.<br>7. Mentor enters an optional note and clicks **Confirm Decision**.<br>8. System saves the decision to Session_Decisions, updates the request status, and performs the corresponding action (book slot / release slot / send alternative options).<br>9. System invokes UC-NOTI-02 to send the decision notification to the learner.<br>10. System displays a toast "Session request #[ID] processed" and returns the mentor to the queue. |
| **Alternative Courses:** | **UC-MENTOR-03.AC.1: Propose an alternative time slot**<br>At step 5 of the Normal Course, if the mentor is unavailable at the learner's preferred time but is willing to meet:<br>5a. Mentor clicks **Propose Alternative Slot**.<br>5b. System displays the mentor's availability calendar for the next 14 days.<br>5c. Mentor selects 1-3 alternative slots and clicks **Send Proposal**.<br>5d. System updates the request status to 'Awaiting_Learner_Confirmation' and sends the alternative slots to the learner.<br>5e. UC ends here for the mentor. Learner will confirm or decline the alternatives in a separate UC (UC-MENTOR-04).<br><br>**UC-MENTOR-03.AC.2: Approve with a pre-session resource attachment**<br>At step 7 of the Normal Course, if the mentor wants to share a preparation resource before the session:<br>7a. Mentor clicks **Attach Resource** and uploads a PDF or pastes a URL (max 10MB / 500 chars).<br>7b. System validates the attachment format and size.<br>7c. Mentor clicks **Confirm Decision** → continue from step 8 of the Normal Course.<br>7d. The attached resource is included in the learner's notification email. |
| **Exceptions:** | **UC-MENTOR-03.EX.1: Duplicate decision — concurrency conflict**<br>Trigger: At step 8, system detects that the request has already been processed (status changed) since the mentor opened the detail view — e.g. a system auto-cancellation or an admin override occurred concurrently.<br>Response: System displays "This session request was already processed or cancelled. Please refresh the queue."<br>Final state: The mentor's current decision attempt is discarded. The request retains its already-updated status. The concurrency event is logged in the audit trail.<br><br>**UC-MENTOR-03.EX.2: Session expired before mentor reviews**<br>Trigger: At step 3, the system detects that the learner's preferred slot is now in the past (request sat in the queue too long due to mentor inactivity).<br>Response: System displays a warning banner: "The learner's preferred slot has passed. You may still Decline or Propose a new slot — the Approve option is disabled."<br>Final state: Approve button is disabled. Mentor can only Decline or Propose Alternative Slot.<br><br>**UC-MENTOR-03.EX.3: Calendar Integration Service unavailable**<br>Trigger: At step 8, when the system attempts to create the calendar invite, the Calendar Integration Service times out or returns an error.<br>Response: System saves the decision as 'Confirmed' and displays a warning: "Session confirmed, but calendar invite could not be sent automatically. Please share the meeting link manually with the learner."<br>Final state: Session status is 'Confirmed'. Learner is notified of approval but without a calendar invite. A retry job attempts to send the calendar invite every 5 minutes for 30 minutes; if it fails, a support ticket is created.<br><br>**UC-MENTOR-03.EX.4: Learner's session quota already exhausted**<br>Trigger: At step 8, system checks and finds the learner's session quota = 0 (quota was consumed by another session between the request submission and the mentor's approval).<br>Response: System prevents the approval and displays: "This learner's session quota has been exhausted. Approve action is blocked. Please Decline and inform the learner to upgrade their subscription."<br>Final state: Request is auto-updated to status='Blocked_Quota_Exceeded'. Learner receives a notification explaining the situation and a link to upgrade. |
| **Includes:** | UC-NOTI-02: Send session decision notification (invoked at step 9 of the Normal Course) |
| **Special Requirements:** | **Performance**: Session request queue loads ≤ 2s with up to 50 pending requests. Request Detail view loads ≤ 1.5s.<br>**Security**: Mentor can only view and process requests assigned to their own queue (RBAC). Learner's personal data displayed in the mentor portal must comply with BA Zone's privacy policy.<br>**Audit**: Every mentor action (view, approve, decline, propose) must be logged with a second-level timestamp. Audit log is retained for 3 years.<br>**SLA**: 80% of session requests must receive a mentor decision within 24 hours of submission. Requests exceeding 48 hours without a decision trigger an automated escalation to the Mentor Success team. |
| **Assumptions:** | 1. Mentors have been onboarded and trained on using the BA Zone Mentor Portal.<br>2. Calendar Integration supports both Google Calendar and Microsoft Outlook (OAuth 2.0).<br>3. Session quota management is real-time — no batch reconciliation. |
| **Notes and Issues:** | [TBD-1] Should mentors be penalized (e.g. ranking score deduction) for declining more than 30% of session requests in a month? \| Owner: Phúc NT - BA Zone \| Due: 2026-06-10 \| Resolution: TBD.<br>[NOTE] Consider adding a mobile-optimized view for the Mentor Portal — several mentors have requested it for on-the-go approvals. Targeted for phase 2. |
---
## Lessons learned from the two examples
1. **UC-LEARN-01** illustrates a learner-facing enrollment UC with payment integration and async fallback handling when the LMS is unavailable.
2. **UC-MENTOR-03** illustrates a mentor-facing admin UC with concurrency, quota enforcement, and calendar integration edge cases.
3. **Both UCs share**:
- 1 primary actor + clear secondary actors
- Description covering WHY + WHAT + OUTCOME
- Verifiable preconditions (not motivations)
- Postconditions expressed as system state changes
- 9-10 step Normal Course alternating Actor/System
- 2 ACs + 3-4 Exceptions covering key failure modes
- Special Requirements that are non-functional only
- Notes with TBDs including owner + due date
4. **Patterns worth learning from these EdTech examples**:
- Async fallback pattern (EX.4 in UC-LEARN-01): payment succeeds but downstream system fails — never roll back payment, retry asynchronously
- Quota enforcement at decision time, not request time (EX.4 in UC-MENTOR-03)
- Concurrency conflict handling for multi-actor queues (EX.1 in UC-MENTOR-03)
- Voucher validation always server-side (security note in Special Requirements)
- Reference Business Rules by ID rather than inlining them in Normal Course steps
---
*Compiled by **Phúc NT** · BA Zone · Digital School*
*Please credit the source when sharing or adapting these examples.*
FILE:references/quality-checklist.md
# Quality Checklist — 20 Points to Validate a Use Case
Run this checklist BEFORE handing over a UC. Each item has: definition, how to check, pass/fail examples.
> Compiled by **Phúc NT** · BA Zone · Digital School
## How to use
1. After writing the UC, walk through items C1-C20
2. Mark Status: ✅ Pass / ❌ Fail / ⚠️ Needs review
3. If Fail → fix it or flag it to the user
4. Output a summary table at the end
```
| Item | Status | Note |
| C1 | ✅ | UC Name "Enroll in Digital School course" follows the format |
| C2 | ⚠️ | UC could be split further — confirm with PO |
| ... | ... | ... |
```
---
## GROUP A: Scope & Identification (C1-C5)
### C1. UC Name follows "verb + object", active voice
**Definition**: UC Name starts with an active verb + an object noun, with no actor name embedded.
**How to check**: Parse the UC Name → identify the leading verb → verify it's an action verb.
**Pass**: "Enroll in Digital School course", "Approve mentor session request", "Issue completion certificate"
**Fail**: "Enrollment" (no verb), "Learner books session" (actor included), "Manage courses" (vague verb)
---
### C2. UC is at user-goal level (passes the coffee-break test)
**Definition**: After completing the UC, the actor can stop and take a break — the goal is achieved.
**How to check**: Read the Postconditions → ask yourself "Is this a business-meaningful result?"
- If the result is just a sub-step (e.g. "OTP is verified") → UC is too small
- If the result spans multiple sessions → UC is too large
**Pass**:
- "Enroll in Digital School course" → postcondition: enrollment active, learner has course access
- "Book mentor session" → postcondition: session request submitted, mentor notified
**Fail**:
- "Verify OTP" (too small — just a sub-step of another UC) → should be an Includes
- "Manage entire learner lifecycle" (too large — spans many sessions) → split into many UCs
---
### C3. UC ID is unique and follows naming convention
**Definition**: ID is unique in the project and matches the standard format.
**How to check**:
- Check the master UC list — is the ID unique?
- Does the format match `UC-<module>-<seq>`?
**Pass**: "UC-LEARN-01" (unique, correct format), "UC-MENTOR-03"
**Fail**: "UC1" (no module), "UseCase_CourseEnroll" (name embedded)
---
### C4. Exactly 1 primary actor + clear business goal
**Definition**: One UC has 1 primary actor (the initiator) and 1 specific goal.
**How to check**:
- Actor field → is there "Primary: [X]"?
- Description → does it state the goal clearly?
- If you see 2 primary actors → flag for splitting
**Pass**: Primary: Learner. Goal: enroll in a Digital School course and gain immediate access to materials.
**Fail**: Primary: Learner + HR Manager (2 actors). → Split: "Learner self-enrolls" and "HR Manager assigns course to employee" as 2 UCs.
---
### C5. System boundary is clear
**Definition**: The UC describes interaction with one specific system, not multiple systems mixed together.
**How to check**: Read the Normal Course → do the "System..." steps consistently refer to one system?
**Pass**: All steps refer to "BA Zone Platform". LMS and Payment Gateway are secondary actors.
**Fail**: Mixing BA Zone web platform + mobile app + third-party LMS API as if they were one system. → Split by system boundary or clarify primary system.
---
## GROUP B: Actor & Context (C6-C8)
### C6. Actor is a specific role/class
**How to check**: Is the actor a specific role/class rather than "User"?
**Pass**: "Learner (Digital School Premium subscriber)", "Mentor (BA Zone certified, active account)"
**Fail**: "User", "Person", "Actor 1"
---
### C7. Description answers WHY + WHAT + OUTCOME
**How to check**: Read the Description → check that all 3 elements are present.
**Pass**:
"When a learner completes all lessons and passes the final assessment [WHY], the learner navigates to the Certificate section to request a completion certificate [WHAT]. The UC ends when a personalized certificate PDF is generated with a unique verification code and emailed to the learner [OUTCOME]."
**Fail**: "This UC is about issuing certificates." (missing WHY and OUTCOME)
---
### C8. Frequency of Use is quantified
**How to check**: Does the Frequency field contain a NUMBER?
**Pass**: "~500 enrollments/day platform-wide; peak ~100/hour during promotional campaigns"
**Fail**: "Frequent", "Often during course launches" (no volume)
⚠️ Acceptable: "TBD — awaiting analytics data from ops team" + logged in Notes as [TBD-N]
---
## GROUP C: Pre/Post Conditions (C9-C11)
### C9. Preconditions are verifiable
**How to check**: Can each precondition be verified by a query / boolean test?
**Pass**: "Learner has completed 100% of course lessons (progress = 100%)" (DB query), "Payment Gateway is available" (health check)
**Fail**: "Learner is motivated to learn" (motivation — not verifiable), "System is ready" (too vague)
---
### C10. Postconditions cover the success state + all changes
**How to check**: Do the postconditions describe all changes after the UC runs?
- Data changes (which records, which fields)
- External state (notification sent, calendar blocked, file generated)
- User-visible state (new screen, badge unlocked)
**Pass**:
```
1. Enrollment record created with status='Active'
2. Learner granted access to all published lessons
3. Payment transaction saved with status='Completed'
4. Welcome email + in-app notification sent within 60s
5. Course enrollment count incremented by 1
```
**Fail**: Only "Enrollment succeeded" → missing all state detail.
---
### C11. Preconditions are not confused with Assumptions
**How to check**: Distinguish:
- Precondition: MUST BE TRUE, system can check
- Assumption: BELIEVED to be true, not verified
**Common Digital School mistake**: Putting "Learner has basic computer literacy" in Precondition → WRONG, this is an Assumption. The system cannot check it.
---
## GROUP D: Normal Course (C12-C15)
### C12. Numbered list, one action per step
**How to check**: Does each step:
- Start with a number (1., 2., 3...)
- Contain only one main action
- Avoid "and" connecting two different-kind actions
**Pass**: "3. Learner enters the session topic, preferred date, and time slot." (same kind — input fields)
**Fail**: "3. Learner enters the topic and clicks Send and waits for confirmation." (3 actions in one step)
---
### C13. Alternates Actor / System with clear subjects
**How to check**: Read the steps — is there an alternating Actor/System pattern?
**Pass**:
```
1. Learner clicks Enroll Now ← Actor
2. System displays the Order Summary ← System
3. Learner selects a payment method ← Actor
4. Learner clicks Proceed to Payment ← Actor
5. System invokes the Payment Gateway ← System
```
(OK to have 2 consecutive Actor steps when both are input — still clear)
**Fail**: Only "Learner does X, then Y, then Z" with no system response anywhere.
---
### C14. NO embedded if/else/loop in the Normal Course
**How to check**: Search the Normal Course for "if", "in case", "otherwise" → flag.
**Pass**:
```
5. System validates the learner's remaining session quota.
6. System creates the session request with status='Pending_Mentor_Review'.
```
**Fail**:
```
5. If the learner has a Premium subscription, system shows all mentors; if Free, system shows only free-tier mentors; if quota is 0, system blocks the action.
```
→ Split into: Normal Course (default Premium flow) + AC (Free tier) + Exception (quota exhausted).
---
### C15. Flow runs from trigger to postcondition
**How to check**:
- Does step 1 match the trigger in the Description?
- Does the final step achieve the postcondition?
- Are there any "dangling" steps?
**Pass**: Step 1 "Learner clicks Enroll Now" (trigger) → step 9 "System sends welcome notification" (postcondition achieved).
**Fail**: Final step is "System saves enrollment" but postcondition says "Welcome notification is sent" → flow is incomplete.
---
## GROUP E: Alternative & Exception (C16-C18)
### C16. Each AC specifies "at step N" + condition
**How to check**: Does each Alternative Course have:
- ID format `UC-XX.AC.N`
- Opening sentence: "At step Y of the Normal Course, if [condition]..."
- Sub-steps numbered 5a, 5b...
- Closing sentence: "continue from step Z of the Normal Course"
**Pass**:
```
UC-LEARN-01.AC.1: Enroll using enterprise voucher
At step 5 of the Normal Course, if the learner selects Enterprise Voucher:
5a. System displays a voucher code field.
5b. Learner enters the code and clicks Apply.
5c. System validates the voucher → continue from step 7 of the Normal Course.
```
**Fail**:
```
AC1: If learner has a voucher, they can use it instead of paying.
```
(Too vague, no step reference, no sub-steps, no rejoining instruction)
---
### C17. Each Exception has trigger + response + final state
**How to check**: Does each exception have all 3 parts?
**Pass**:
```
UC-LEARN-01.EX.2: Course reaches full capacity mid-flow
Trigger: At step 7, LMS returns CAPACITY_EXCEEDED.
Response: System displays "This course just reached full capacity. Join the waitlist."
Final state: Payment refunded within 1 business day. No enrollment created. Waitlist offer shown.
```
**Fail**:
```
EX1: If an error occurs, system shows an error message.
```
(Vague — no trigger, no response detail, no final state)
---
### C18. Common failure modes are covered
**How to check**: Does the UC cover at least the common failure types relevant to Digital School?
| Failure type | Required for Digital School UC? |
|---|---|
| Validation error (invalid input) | ✅ |
| Business rule violation (quota exceeded, course at capacity) | ✅ |
| External service failure (payment gateway, LMS, calendar timeout) | ✅ |
| Authentication/Authorization failure | ✅ if UC has auth |
| Network/connectivity issue | ✅ for mobile flows |
| Concurrency conflict (two learners grabbing last slot) | ✅ for enrollment/booking UCs |
| Session timeout (mentor idle on detail view) | ✅ for UCs with long review flows |
**Tip**: If the UC has only 1-2 Exceptions → suspicious. Enrollment and booking UCs typically need 3-5.
---
## GROUP F: Completeness (C19-C20)
### C19. Includes (if any) point to existing UCs
**How to check**: Does each UC in the Includes field have a valid ID + does that UC actually exist?
**Pass**: "Includes: UC-PAY-01 (Process payment)" → UC-PAY-01 has been written and is in the UC register.
**Fail**: "Includes: Payment UC" → ID not specific, or referenced UC doesn't exist yet.
---
### C20. Special Requirements don't duplicate functional requirements
**How to check**: Is each item in Special Requirements a non-functional requirement?
**Pass** (non-functional):
- "Course catalog loads ≤ 2s under 5,000 concurrent users"
- "Audit log retained for 3 years"
- "Comply with Vietnamese VAT invoicing regulations"
**Fail** (functional — belongs in Normal Course / Business Rule):
- "Validate that the voucher code is 16 characters" → validation logic, belongs in a Normal Course step or BR
- "Learner can only enroll in 10 courses per month" → business rule, not a Special Requirement
---
## Validation Report
After checking all 20 items, output the report in this format:
```markdown
## Validation Result for UC-LEARN-01
| # | Item | Status | Note |
|---|------|--------|------|
| C1 | UC Name format | ✅ | "Enroll in Digital School course" — active verb + object |
| C2 | User-goal level | ✅ | Passes coffee-break test |
| C3 | UC ID unique | ✅ | Follows convention |
| C4 | 1 primary actor | ✅ | Learner |
| C5 | System boundary | ✅ | BA Zone Platform |
| C6 | Specific actor | ✅ | |
| C7 | Description WHY+WHAT+OUTCOME | ✅ | |
| C8 | Frequency quantified | ⚠️ | TBD — awaiting analytics from ops team |
| C9 | Preconditions verifiable | ✅ | 4/4 verifiable |
| C10 | Postconditions cover state | ✅ | 5 postconditions |
| C11 | No Pre/Assumption mix | ✅ | |
| C12 | Numbered, 1 action/step | ✅ | 9 steps |
| C13 | Actor/System alternating | ✅ | |
| C14 | No nested if/else | ✅ | |
| C15 | Flow complete | ✅ | |
| C16 | AC has "at step N" | ✅ | 2 ACs, all properly anchored |
| C17 | Exception has 3 parts | ✅ | 4 exceptions, all complete |
| C18 | Common failure modes covered | ✅ | Payment fail, capacity, LMS unavailable — all covered |
| C19 | Includes valid | ✅ | UC-PAY-01, UC-NOTI-01 |
| C20 | Special Req non-functional | ✅ | |
**Summary**: 19/20 ✅ + 1 ⚠️. UC is ready for stakeholder review.
**Follow-up**: C8 — Frequency of Use awaiting analytics data from the ops team [TBD-3].
```
---
*Compiled by **Phúc NT** · BA Zone · Digital School*
*Please credit the source when sharing or adapting this checklist.*
FILE:references/template-guide.md
# Template Guide — How to Fill Each Field
Detailed guidance for filling each of the 13 fields, with pass/fail examples in the EdTech & Digital School domain.
Compiled by **Phúc NT** · BA Zone · Digital School
## Table of Contents
1. [Use Case ID](#1-use-case-id)
2. [Use Case Name](#2-use-case-name)
3. [Use Case History](#3-use-case-history)
4. [Actor](#4-actor)
5. [Description](#5-description)
6. [Preconditions](#6-preconditions)
7. [Postconditions](#7-postconditions)
8. [Priority](#8-priority)
9. [Frequency of Use](#9-frequency-of-use)
10. [Normal Course of Events](#10-normal-course-of-events)
11. [Alternative Courses](#11-alternative-courses)
12. [Exceptions](#12-exceptions)
13. [Includes](#13-includes)
14. [Special Requirements](#14-special-requirements)
15. [Assumptions](#15-assumptions)
16. [Notes and Issues](#16-notes-and-issues)
---
## 1. Use Case ID
**Purpose**: Unique identifier so requirements can be traced back to the UC.
**Rules**:
- Format: `UC-<module>-<sequence>` or `UC-X.Y` (hierarchical)
- Use a consistent naming convention across the project
- For related UC groups, use X.Y (e.g. UC-3.1, UC-3.2 belong to the "Enrollment" group)
- Pad the sequence to 2-3 digits: `UC-LEARN-01`, `UC-MENTOR-003`
**Good examples**:
- `UC-LEARN-01` (Enrollment module, UC #1)
- `UC-MENTOR-03` (Mentoring module, UC #3)
- `UC-3.2` (hierarchical, 2nd sub-UC of group 3)
**Bad examples**:
- `UC1` (no scheme)
- `UseCase_CourseEnrollment` (mixes name into ID — hard to maintain when name changes)
---
## 2. Use Case Name
**Purpose**: Short label describing the UC's goal.
**CRITICAL rules**:
- MUST follow **"Action verb + Object"** form
- 3-7 words, not too long
- DO NOT start with the actor name
- DO NOT use vague verbs ("manage", "handle", "process", "do")
- Reflects the actor's goal, not the implementation
**Pattern**: `<Verb> <Direct Object> [<modifier>]`
**Good examples** (Digital School / BA Zone):
- ✅ "Enroll in Digital School course"
- ✅ "Book 1-on-1 mentor session"
- ✅ "Issue course completion certificate"
- ✅ "Approve learner KYC application"
- ✅ "Assign enterprise license to employee"
**Bad examples → how to fix**:
- ❌ "Enrollment" → ✅ "Enroll in course"
- ❌ "Learner books session" (actor included) → ✅ "Book mentor session"
- ❌ "Manage learning path" (vague verb) → split into "Create learning path", "Update learning path", "Archive learning path"
- ❌ "Certificate is issued" (passive voice) → ✅ "Issue completion certificate"
---
## 3. Use Case History
**Purpose**: Audit trail (Created By, Date Created, Last Updated By, Date Last Updated).
**Rules**:
- Created By: full name + role (e.g. "Phúc NT - BA Zone")
- Date Created: YYYY-MM-DD format
- Last Updated By + Date Last Updated: update on every edit
- If unknown, use the placeholder `<TBD>` instead of leaving blank
---
## 4. Actor
**Purpose**: Identify who/what interacts with the system.
**Actor types**:
- **Primary actor**: Initiates the UC, benefits from the outcome
- **Secondary actor**: Supporting system/person (payment gateway, LMS, calendar service)
- **Off-stage stakeholder**: Has interest but doesn't interact directly (regulators, auditors) — usually NOT listed in the Actor field
**Rules**:
- The primary actor MUST be a specific role/class — never write "User" generically
- A UC should have 1 primary actor (rarely 2+)
- If there's a secondary actor, label it clearly
**Good examples** (Digital School / BA Zone):
- ✅ "Primary: Learner (Digital School Premium subscriber, email verified)"
- ✅ "Primary: Mentor (BA Zone certified, active account)"
- ✅ "Primary: HR Manager (Enterprise Partner with license admin rights)"
- ✅ "Primary: BO Admin; Secondary: AML Service, Notification Service"
**Bad examples**:
- ❌ "User" (too generic)
- ❌ "Student" (ambiguous — is it the same as Learner?)
- ❌ "System" (the system is the target of the UC, not an actor)
---
## 5. Description
**Purpose**: Summarize the UC in 2-3 sentences so readers grasp what it's about quickly.
**Rules — must answer 3 questions**:
1. **WHY**: The reason/trigger that leads to this UC
2. **WHAT**: What the actor does with the system
3. **OUTCOME**: The final result (new system state / value for the actor)
**Pattern**: `[When/To] <trigger/reason>, <actor> <action> in order to <outcome>.`
**Good example** (Digital School):
> "When a learner completes all lessons and passes the final assessment of a Digital School course, the learner navigates to the Certificate section to download their completion certificate. The UC ends when a personalized certificate PDF is generated with a unique verification code, downloaded by the learner, and recorded in the Certificates table."
**Bad examples**:
> ❌ "This UC is about certificates." (too short, missing WHY and OUTCOME)
> ❌ "The certificate module has these steps: request, generate, download…" (describes flow, not a description)
---
## 6. Preconditions
**Purpose**: List conditions that MUST be true before the UC can start.
**CRITICAL rules**:
- Every precondition must be **verifiable** (boolean check)
- Number them: 1, 2, 3…
- Distinguish from Business Rules:
- Precondition: checked BEFORE the UC starts
- Business Rule: applied DURING the UC's flow
- Distinguish from Assumptions:
- Precondition: REQUIRED for the UC to run
- Assumption: BELIEVED to be true but not verified
**Good examples** (Digital School):
```
1. Learner has logged in to BA Zone with a verified email address
2. Learner has completed 100% of the course lessons (progress = 100%)
3. Learner has passed the final assessment with a score ≥ 70%
4. Certificate generation service is available
```
**Bad examples**:
- ❌ "System is operating" (too generic, not verifiable)
- ❌ "Learner wants a certificate" (motivation, not a condition)
- ❌ "Learner must have a valid payment method" (belongs in a payment UC, not a certificate UC)
---
## 7. Postconditions
**Purpose**: Describe the system state AFTER successful UC completion.
**Rules**:
- Verifiable (can be checked via DB query / API response)
- Cover all kinds of changes:
- Data state (new record, status change)
- User-facing state (notification sent, file available for download)
- External system state (API call succeeded, calendar blocked)
- Number them
**Important**: A postcondition is a **state**, not an **action**.
- ✅ State: "Certificate record is saved with a unique verification code"
- ❌ Action: "System saves the certificate record" (this is a step in the Normal Course)
**Good example** (Digital School):
```
1. Certificate record is created in the Certificates table with a unique verification code (format: CERT-BAZONE-YYYY-NNNNN)
2. Certificate PDF is generated and stored in cloud storage, accessible via a permanent URL
3. Learner's profile displays the certificate badge for the completed course
4. Certificate verification page is publicly accessible at verify.bazone.vn using the unique code
5. Achievement notification is sent to the learner's email and in-app notification center
```
---
## 8. Priority
**Purpose**: Define the implementation priority of the UC.
**Common schemes**:
- **MoSCoW**: Must / Should / Could / Won't
- **3-level**: High / Medium / Low
**Rules**:
- Use the SAME scheme as the project's SRS / PRD
- Justify (one sentence explaining why priority X)
**Good examples** (Digital School):
- "High — Core feature; directly tied to learner retention and completion rate metrics"
- "Medium — Enhances enterprise partner experience; planned for phase 2"
---
## 9. Frequency of Use
**Purpose**: Estimate how often the UC will be executed → input for performance/capacity planning.
**Rules**:
- Use SPECIFIC NUMBERS (not "occasionally", "frequently")
- Suitable time units: per second, per hour, per day, per month
- If there are peak times, state them explicitly
**Good examples** (Digital School):
- "~500 enrollments/day; peak ~100/hour during campaign launches and new course releases"
- "~15 session requests/day per mentor; system-wide ~300/day across 20 active mentors; peak Sunday evenings"
**Bad examples**:
- ❌ "Frequent"
- ❌ "Daily" (no volume)
---
## 10. Normal Course of Events
**Purpose**: Describe the happy path — steps from trigger to goal achieved.
**CRITICAL rules** (this is the most error-prone field):
### 10.1. Format
- Numbered list (1, 2, 3…)
- Each step: one single action
- Start with a clear subject (Actor / System)
- Active voice + present tense
- Short steps, 1-2 sentences each
### 10.2. Alternate Actor / System
Typical pattern: Actor → System → Actor → System…
- Odd steps: actor input
- Even steps: system response
### 10.3. DO NOT embed:
- ❌ If/else → move to Alternative Course
- ❌ Loops → use "Steps X-Y repeat until Z"
- ❌ Exceptions → move to Exceptions
- ❌ Internal system logic → that's design, not a UC
### 10.4. Start and end
- Step 1: Trigger (the event that activates the UC)
- Final step: Goal achieved (postcondition met)
**Good example** (Digital School — book a mentor session):
```
1. Learner navigates to the "My Mentors" section and selects a mentor profile.
2. System displays the mentor's profile: bio, expertise, average rating, and available time slots for the next 14 days.
3. Learner selects a preferred date and time slot.
4. Learner enters a topic or question for the session (max 500 characters) and clicks "Send Request".
5. System validates that the learner has at least 1 unused session quota in their current subscription.
6. System creates a session request with status='Pending_Mentor_Review' and sends a notification to the mentor.
7. System displays a confirmation screen: "Request sent! Your mentor will respond within 24 hours."
8. System invokes UC-NOTI-03 to send a confirmation email to the learner.
```
**Bad examples → how to fix**:
- ❌ "1. If the learner has a Premium subscription, they can select any mentor; otherwise they can only select from the free tier…" → Move the branching to an Alternative Course
- ❌ "3. System validates. If invalid, show error. If valid, continue." → Validation-pass continues in flow; validation-fail goes into an Exception
- ❌ "5. System calls POST /api/v1/sessions with body {learner_id, mentor_id, slot_id}" → Too technical. Say: "System creates the session request in the booking system"
---
## 11. Alternative Courses
**Purpose**: A DIFFERENT path that still leads to the goal (still success), just a different route.
**Rules**:
- ID format: `UC-XX.AC.N` (AC = Alternative Course)
- Each AC starts with: "At step Y of the Normal Course, if [condition], execute the alternative: …"
- After the AC, state explicitly which step of the Normal Course to continue from
**Good example** (Digital School):
```
UC-LEARN-01.AC.1: Enroll using an enterprise voucher
At step 5 of the Normal Course, if the learner selects "Enterprise Voucher" as the payment method:
5a. System displays a voucher code input field.
5b. Learner enters the code and clicks "Apply".
5c. System validates the voucher (expiry, applicability, remaining uses).
5d. System updates the total amount to 0 VND → continue from step 7 of the Normal Course (no payment gateway call).
```
---
## 12. Exceptions
**Purpose**: Cases where the UC FAILS (goal is not achieved).
**Rules**:
- ID format: `UC-XX.EX.N` (EX = Exception)
- Each exception needs 3 parts:
1. **Trigger condition**: When the exception occurs
2. **System response**: What the system does
3. **Final state**: The end state (rollback? partial? log?)
**Common failure modes to check** (don't forget):
- Validation errors (wrong format, missing field)
- Business rule violations (quota exceeded, course at capacity)
- External service failures (payment gateway timeout, LMS unavailable)
- Network/connectivity issues
- Permission denied / authorization failure
- Concurrency conflict (slot booked by another learner at the same time)
- Session timeout (mentor idle too long on the detail view)
**Good example** (Digital School):
```
UC-LEARN-01.EX.2: Course reaches full capacity between page load and enrollment
Trigger: At step 7, LMS returns CAPACITY_EXCEEDED because another learner filled the last slot milliseconds earlier.
Response: System displays "Sorry, this course just reached full capacity. Join the waitlist to be notified when a slot opens."
Final state: Payment is refunded automatically within 1 business day. No enrollment record is created. Learner is offered the waitlist option.
```
---
## 13. Includes
**Purpose**: Reuse common functionality across UCs.
**Rules**:
- List sub-UCs "called" by this UC (UML «include» semantics)
- The sub-UC must exist (have its own spec)
- DO NOT use Includes just to group minor steps — only for logic reused in other UCs
**Good example** (Digital School):
```
- UC-PAY-01: Process payment (called at step 6 of the Normal Course)
- UC-NOTI-01: Send enrollment notification (called at step 9)
```
---
## 14. Special Requirements
**Purpose**: Non-functional requirements specific to this UC.
**Categories to cover**:
- **Performance**: Response time, throughput, concurrent users
- **Security**: Authentication, encryption, data privacy
- **Usability**: Accessibility, mobile-first requirements
- **Reliability**: Uptime, async fallback strategy
- **Compliance**: Regulatory requirements (VAT invoicing, data retention)
**Rule**: DO NOT duplicate functional requirements — only list non-functional.
**Good example** (Digital School):
```
- Performance: Course catalog page loads ≤ 2s under 5,000 concurrent learners
- Security: Payment card data never stored on BA Zone servers; all card processing via PCI-DSS certified gateway
- Reliability: If LMS is unavailable during enrollment, payment must not be rolled back — retry asynchronously up to 30 min
- Compliance: Issue VAT invoice for all transactions ≥ 200,000 VND (Vietnamese tax law)
```
---
## 15. Assumptions
**Purpose**: Things assumed during analysis that haven't been verified.
**Difference vs Precondition**:
- Precondition: MUST BE TRUE, system can verify
- Assumption: BELIEVED TO BE TRUE, not required to verify
**Good example** (Digital School):
```
1. Learner's email address is verified and active — welcome emails will not bounce
2. Payment Gateway SLA is ≥ 99.5% uptime during business hours
3. Enterprise vouchers are pre-loaded by BA Zone's ops team before distribution to partners
4. LMS access provisioning completes synchronously in < 3s under normal load
```
---
## 16. Notes and Issues
**Purpose**: Open questions, TBDs, follow-up items.
**Format**:
```
[TBD-N] | Owner | Due Date | Resolution
```
**Good example** (Digital School):
```
- [TBD-1] Should learners be able to gift a course enrollment to another BA Zone user? | Owner: Product Team | Due: 2026-06-01 | Resolution: TBD — deferred to phase 2
- [TBD-2] What is the refund policy if a learner requests a refund within 7 days? | Owner: Phúc NT - BA Zone | Due: 2026-05-25 | Resolution: TBD
- [NOTE] Welcome email template must align with current Digital School brand guidelines — coordinate with Marketing team
```
---
*Compiled by **Phúc NT** · BA Zone · Digital School*
*Please credit the source when sharing or adapting this guide.*
FILE:references/writing-style.md
# Writing Style Guide
Compiled from Alistair Cockburn ("Writing Effective Use Cases") + IIBA BABOK + BA Zone practice in EdTech and enterprise software domains.
> Compiled by **Phúc NT** · BA Zone · Digital School
## Supreme principle: READABILITY FIRST
Cockburn's famous quote: "Write clearly. Readability is the most important thing."
A good UC is one where:
- Non-technical stakeholders can grasp the meaning
- Developers have enough to code from
- QA has enough to write test cases
- A new BA (or future Digital School grad) can update it when things change
---
## Rule 1: Active Voice + Present Tense
### Active voice
Use active sentences where the subject performs the action.
- ✅ "Learner clicks the **Enroll Now** button"
- ❌ "The **Enroll Now** button is clicked by the learner"
- ✅ "System saves the enrollment record to the database"
- ❌ "The enrollment record is saved to the database by the system"
### Present tense
Use simple present tense, avoid future/past.
- ✅ "System displays the course confirmation screen"
- ❌ "System will display the course confirmation screen"
- ❌ "System displayed the course confirmation screen"
---
## Rule 2: Clear subject — Subject + Verb + Object
Every step must start with a **specific subject**: an actor name or "System".
- ✅ "Learner selects a preferred mentor session slot"
- ❌ "Selects a preferred session slot" (no subject)
- ✅ "System validates the learner's remaining session quota"
- ❌ "Validates the remaining quota" (passive, unclear who's doing it)
---
## Rule 3: One step = one action
Each step in the Normal Course does exactly one thing. If you see "and" connecting different kinds of action → split the step.
- ✅ "3. Learner enters the destination account, preferred slot, and session topic." (same kind — filling a form)
- ❌ "3. Learner fills in the session topic and clicks Confirm." → split into 2 steps:
- "3. Learner enters the session topic (max 500 characters)."
- "4. Learner clicks the **Send Request** button."
**Why**: "Clicking Send Request" usually triggers system validation → it needs to be a separate step so an Exception "quota exceeded" can be attached to it.
---
## Rule 4: Avoid vague verbs
Vague verbs = verbs that don't convey a specific action.
| ❌ Vague | ✅ Specific |
|---------|------------|
| Manage | Create / Update / Archive / View |
| Handle | Validate / Process / Reject / Escalate |
| Do | Submit / Approve / Assign / Generate |
| Make | Issue / Build / Render / Compute |
| Get | Retrieve / Fetch / Query / Download |
| Use | Apply / Invoke / Execute / Redeem |
| Take care of | Specific verb |
**Apply this to both the UC Name and the step text.**
---
## Rule 5: Avoid implementation details
A UC describes **WHAT** (the action), not **HOW** (the mechanism). Leave HOW for the design phase.
- ❌ "System calls POST /api/v1/enrollments with header Authorization Bearer {token}, body {course_id, learner_id}…"
- ✅ "System creates the enrollment record in the LMS"
- ❌ "System inserts a row into the tbl_enrollments table with fields: enroll_id, course_id, learner_id, created_at…"
- ✅ "System saves the enrollment to the database"
- ❌ "System renders the <EnrollmentSuccessModal> React component with prop courseTitle='BA Fundamentals'…"
- ✅ "System displays the Enrollment Confirmed screen with the course name and access link"
**Exception**: If the UC is specifically an integration spec, it can be more detailed — but still use business language.
---
## Rule 6: Consistent numbering
### Normal Course
Numbered list starting at 1.
### Alternative Course
Sub-numbering by original step + letter:
- AC at step 5 → step 5a, 5b, 5c
- After the AC, state "continue from step N of the Normal Course"
### Exception ID
Format: `UC-XX.EX.N` (numbered independently, not tied to a step)
### Pre/Postconditions
Numbered list starting at 1.
---
## Rule 7: Naming UI elements
When mentioning a UI element in a step, use bold and the actual on-screen label:
- ✅ "Learner clicks the **Enroll Now** button"
- ✅ "System displays the **Order Summary** screen"
- ✅ "Learner selects **Enterprise Voucher** from the payment method dropdown"
Reason: Easy to trace back to wireframes/mockups during design handoff.
---
## Rule 8: Avoid vague words
| ❌ Vague | ✅ Specific |
|---------|------------|
| In some cases | When condition X occurs |
| May / can | When [condition], system [action] |
| Sometimes | X% of the time / Y times per Z |
| If needed | When [specific trigger] |
| Valid | Meets the criteria: … (list them) |
| Appropriate | Per BA Zone policy [reference] |
| Quickly | Within X seconds |
| User | Learner / Mentor / BO Admin / HR Manager |
---
## Rule 9: Don't embed business rules in steps
A Normal Course step describes **flow**. Business rules (validation rules, limits, business logic) should:
- Reference Special Requirements by rule ID
- Or live in a separate Business Rule document (BR-XX-YY)
- ❌ "5. System validates: session topic must be ≤ 500 chars, learner must have ≥ 1 unused quota, slot must be ≥ 2 hours in the future, mentor must not be on leave…"
- ✅ "5. System validates the session request according to business rule BR-MENTOR-001."
- (Then list BR-MENTOR-001 in Special Requirements or a separate BR document)
---
## Rule 10: Length guidelines
- **UC Name**: 3-7 words
- **Description**: 2-4 sentences, ~50-100 words
- **Normal Course**: 5-15 steps (usually 7-10 for Digital School UCs)
- **Each step**: 1 sentence, max 2 sentences, < 30 words
- **Alternative Courses**: 1-5 ACs per UC (more → consider splitting the UC)
- **Exceptions**: 3-7 for a typical UC
- **Total UC document**: 2-5 A4 pages
If you exceed the guideline:
- UC too long → split via Includes
- Too many ACs/EXs → review the scope, the UC might be carrying too much
---
## Rule 11: Consistency across the project
Be consistent across the whole document set:
- Actor names (don't switch between "Learner", "Student", "User", "Participant")
- System component names (LMS, Learning Management System, Moodle → pick one)
- Screen/menu names (must match the wireframe or product spec)
- Naming convention for UC IDs
Tip: Maintain a **Glossary** at the front of the document set. For Digital School, agree upfront: is it "Learner" or "Student"? "Mentor" or "Instructor"?
---
## Rule 12: Internationalization
If the Digital School platform has i18n requirements:
- Screen/button names in the UC can use keys instead of hard-coded text
- E.g. replace "clicks the **Enroll Now** button" with "clicks the {btn.enroll_now} button"
- For most BA Zone UC specs, plain English labels are fine
---
## Anti-patterns — the 10 most common mistakes
### 1. UC is a pixel-by-pixel UI spec
❌ "System displays a modal with a blue #1E88E5 header 'Enrollment Confirmed', a checkmark icon, and course thumbnail image on the left..."
→ That's a wireframe annotation. A UC says: "System displays the Enrollment Confirmed screen with the course name and a Go to Course button."
### 2. Mixing actor and system in one step
❌ "3. Learner selects the slot and system validates quota."
→ Split into 2 steps.
### 3. Skipping system response
❌ "1. Learner clicks Enroll Now. 2. Learner enters payment info. 3. Learner confirms."
→ System responses between steps are missing. A UC must show DIALOG actor ↔ system.
### 4. Embedded conditional logic
❌ "5. If the learner has a Premium subscription, system allows mentor selection; otherwise only free-tier mentors are shown."
→ Split into Normal Course (default case) + AC (Premium path) or Exception (unauthorized access).
### 5. Vague trigger
❌ "When the learner wants to get a certificate, they..."
→ Be specific: "When the learner navigates to the **Certificates** tab after completing the course..."
### 6. Postcondition is an action instead of a state
❌ "System sends a certificate to the learner" (action)
→ "A certificate email has been delivered to the learner's registered email address" (state) ← verifiable
### 7. UC with 2 primary actors
❌ Primary: Learner + HR Manager (both initiating the UC)
→ Split into 2 UCs: one for self-enrollment, one for HR-assigned enrollment.
### 8. Vague "System processes"
❌ "5. System processes the enrollment."
→ Be specific: "System creates the enrollment record in the LMS and grants the learner access to all published lessons."
### 9. Repeating the Description in the Normal Course
If the Description already states the full flow, don't copy it into the Normal Course. The Description is a 2-3 sentence summary; the Normal Course is the detailed step-by-step.
### 10. Forgetting failure modes
A UC with only a Normal Course + 1 generic "error" Exception → not enough.
For Digital School UCs, always cover: payment failures, quota exhaustion, external service timeouts, concurrency conflicts (two learners grabbing the last slot), and permission/role mismatches.
---
*Compiled by **Phúc NT** · BA Zone · Digital School*
*Please credit the source when sharing or adapting this guide.*
FILE:scripts/uc_quality_checker.py
#!/usr/bin/env python3
"""Deterministic first-pass checker for the use-case-writer 20-point quality checklist.
Parses a Use Case Markdown file written in the `assets/uc-template.md` table format
and runs heuristic checks for items C1-C20 from `references/quality-checklist.md`.
This is a mechanical pre-check, not a substitute for the LLM-driven Step 4 review in
SKILL.md -- several items (C2, C5, C11, C13, C15, C19) require judgment or an external
UC registry and are reported as MANUAL rather than PASS/FAIL.
Stdlib only. No network calls.
"""
import argparse
import json
import re
import sys
VAGUE_VERBS = {"manage", "handle", "process", "do", "make", "get", "use", "take"}
GENERIC_ACTORS = {"user", "users", "person", "actor", "system", "student", "customer"}
VAGUE_PRECONDITION_WORDS = ("motivated", "literacy", "wants", "ready", "interested", "willing")
FAILURE_MODE_KEYWORDS = (
"timeout", "invalid", "network", "permission", "quota", "capacity",
"concurrency", "unavailable", "denied", "expire", "conflict",
)
FIELD_ALIASES = {
"use case id": "uc_id",
"use case name": "uc_name",
"actor": "actor",
"description": "description",
"preconditions": "preconditions",
"postconditions": "postconditions",
"priority": "priority",
"frequency of use": "frequency",
"normal course of events": "normal_course",
"alternative courses": "alternative_courses",
"exceptions": "exceptions",
"includes": "includes",
"special requirements": "special_requirements",
"assumptions": "assumptions",
"notes and issues": "notes",
}
SAMPLE_UC = """## UC-LEARN-01: Enroll in Digital School course
| **Use Case ID:** | UC-LEARN-01 |
| ---: | :--- |
| **Use Case Name:** | Enroll in Digital School course |
| **Actor:** | **Primary:** Learner (Digital School Premium subscriber). **Secondary:** Payment Gateway, LMS. |
| **Description:** | When a learner selects a course from the catalog, the learner enrolls in order to gain access to all published lessons. The UC ends when the enrollment record is active and materials are accessible. |
| **Preconditions:** | 1. Learner has logged in with a verified email address.<br>2. Payment Gateway is available. |
| **Postconditions:** | 1. Enrollment record created with status='Active'.<br>2. Learner granted access to all published lessons. |
| **Priority:** | High - core retention feature |
| **Frequency of Use:** | ~500 enrollments/day; peak ~100/hour during campaign launches |
| **Normal Course of Events:** | 1. Learner selects the course on the catalog.<br>2. System displays course details and the Enroll Now button.<br>3. Learner clicks Enroll Now.<br>4. System creates the enrollment record.<br>5. System displays the confirmation screen. |
| **Alternative Courses:** | **UC-LEARN-01.AC.1: Enroll using enterprise voucher**<br>At step 3, if the learner selects Enterprise Voucher: 3a. System displays a voucher field. 3b. Learner enters the code. -> continue from step 4 of the Normal Course. |
| **Exceptions:** | **UC-LEARN-01.EX.1: Course reaches full capacity**<br>Trigger: At step 4, LMS returns CAPACITY_EXCEEDED.<br>Response: System displays a waitlist offer.<br>Final state: No enrollment record created; payment refunded. |
| **Includes:** | UC-PAY-01: Process payment (invoked at step 4) |
| **Special Requirements:** | **Performance**: Catalog page loads <= 2s under 5,000 concurrent learners. |
| **Assumptions:** | 1. Learner's email address is verified and active. |
| **Notes and Issues:** | [TBD-1] Should learners be able to gift enrollment? \\| Owner: Product \\| Due: 2026-06-01 \\| Resolution: TBD |
"""
def parse_uc(text):
fields = {}
for line in text.splitlines():
stripped = line.strip()
if not stripped.startswith("|"):
continue
m = re.match(r"\|\s*\*\*([^*:]+):?\*\*\s*\|\s*(.*)", stripped)
if not m:
continue
label = m.group(1).strip().lower()
key = FIELD_ALIASES.get(label)
if not key:
continue
value = m.group(2)
value = re.sub(r"\|\s*$", "", value).strip()
value = value.replace("<br>", "\n")
if key in fields:
fields[key] += "\n" + value
else:
fields[key] = value
return fields
def check(item, status, note):
return {"item": item, "status": status, "note": note}
def run_checks(fields, registry):
results = []
# C1: UC Name follows verb + object
name = fields.get("uc_name", "")
if not name:
results.append(check("C1", "FAIL", "Use Case Name is missing"))
else:
first_word = re.split(r"\s+", name.strip())[0].lower().rstrip(".,")
if first_word in VAGUE_VERBS:
results.append(check("C1", "FAIL", f"Vague leading verb '{first_word}' -- use a specific action verb"))
elif len(name.split()) < 2:
results.append(check("C1", "FAIL", "Name is a single word -- needs verb + object"))
elif re.match(r"^(the|a|an)\b", name.strip(), re.I):
results.append(check("C1", "WARN", "Name may embed an actor/article rather than starting with a verb"))
else:
results.append(check("C1", "PASS", f"'{name}' reads as verb + object"))
# C2: coffee-break test / goal level -- judgment call
results.append(check("C2", "MANUAL", "Goal-level scoping (coffee-break test) requires human/LLM judgment"))
# C3: UC ID format
uc_id = fields.get("uc_id", "")
if re.match(r"^UC-[A-Za-z0-9]+-\d+$", uc_id) or re.match(r"^UC-\d+(\.\d+)+$", uc_id):
results.append(check("C3", "PASS", f"ID '{uc_id}' matches UC-<module>-<seq> or UC-X.Y"))
else:
results.append(check("C3", "FAIL", f"ID '{uc_id}' does not match naming convention"))
# C4: exactly one primary actor
actor = fields.get("actor", "")
primary_count = len(re.findall(r"primary\s*:", actor, re.I))
if primary_count == 1:
results.append(check("C4", "PASS", "Exactly one Primary actor declared"))
elif primary_count == 0:
results.append(check("C4", "FAIL", "No 'Primary:' actor found"))
else:
results.append(check("C4", "FAIL", f"{primary_count} 'Primary:' actors found -- consider splitting the UC"))
# C5: system boundary -- judgment call
results.append(check("C5", "MANUAL", "System boundary consistency requires reading the full Normal Course"))
# C6: actor is specific, not generic
primary_match = re.search(r"primary\s*:\s*\**\s*([^.\n]+)", actor, re.I)
primary_role = primary_match.group(1).strip().strip("*").strip() if primary_match else ""
primary_first_word = re.split(r"\s+", primary_role)[0].lower().rstrip(".,()") if primary_role else ""
if primary_first_word and primary_first_word in GENERIC_ACTORS:
results.append(check("C6", "FAIL", f"Primary actor '{primary_role}' is a generic role"))
elif primary_role:
results.append(check("C6", "PASS", f"Primary actor '{primary_role}' is specific"))
else:
results.append(check("C6", "FAIL", "No Primary actor role found"))
# C7: description covers WHY + WHAT + OUTCOME (heuristic keyword presence + length)
description = fields.get("description", "")
words = len(description.split())
why_cue = re.search(r"\b(when|after|because|since)\b", description, re.I)
outcome_cue = re.search(r"\b(so that|in order to|ends when|until|outcome)\b", description, re.I)
if words < 12:
results.append(check("C7", "WARN", f"Description is short ({words} words) -- verify WHY/WHAT/OUTCOME are all present"))
elif why_cue and outcome_cue:
results.append(check("C7", "PASS", "Description contains WHY and OUTCOME cues"))
else:
missing = [n for n, c in (("WHY", why_cue), ("OUTCOME", outcome_cue)) if not c]
results.append(check("C7", "WARN", f"Description may be missing: {', '.join(missing)}"))
# C8: frequency quantified
frequency = fields.get("frequency", "")
if re.search(r"\d", frequency):
results.append(check("C8", "PASS", "Frequency of Use contains a number"))
elif re.search(r"tbd", frequency, re.I):
results.append(check("C8", "WARN", "Frequency marked TBD -- ensure it is logged in Notes and Issues"))
else:
results.append(check("C8", "FAIL", "Frequency of Use has no quantity"))
# C9: preconditions verifiable (heuristic banned-word scan)
preconditions = fields.get("preconditions", "")
if not preconditions:
results.append(check("C9", "FAIL", "Preconditions field is empty"))
else:
hits = [w for w in VAGUE_PRECONDITION_WORDS if w in preconditions.lower()]
if hits:
results.append(check("C9", "WARN", f"Possible unverifiable precondition language: {', '.join(hits)}"))
else:
results.append(check("C9", "PASS", "No obviously unverifiable language detected"))
# C10: postconditions present and non-trivial
postconditions = fields.get("postconditions", "")
items = [l for l in postconditions.split("\n") if re.match(r"^\s*\d+[.)]", l)]
if not items:
results.append(check("C10", "FAIL", "No numbered Postconditions found"))
else:
results.append(check("C10", "PASS", f"{len(items)} postcondition(s) listed"))
# C11: precondition/assumption confusion -- judgment call
results.append(check("C11", "MANUAL", "Precondition-vs-Assumption confusion needs semantic review"))
# C12: Normal Course numbered, one action per step
normal_course = fields.get("normal_course", "")
steps = [l for l in normal_course.split("\n") if re.match(r"^\s*\d+[.)]", l)]
if not steps:
results.append(check("C12", "FAIL", "Normal Course has no numbered steps"))
else:
multi_and = [s for s in steps if s.lower().count(" and ") >= 2]
if multi_and:
results.append(check("C12", "WARN", f"{len(multi_and)} step(s) chain multiple actions with 'and'"))
else:
results.append(check("C12", "PASS", f"{len(steps)} numbered step(s), no obvious multi-action steps"))
# C13: actor/system alternation -- weak heuristic
if re.search(r"\bsystem\b", normal_course, re.I) and re.search(r"\b(learner|actor|user|mentor|admin|manager)\b", normal_course, re.I):
results.append(check("C13", "PASS", "Both actor- and system-attributed steps appear"))
else:
results.append(check("C13", "WARN", "Could not confirm actor/system alternation -- review manually"))
# C14: no embedded conditionals in Normal Course
conditional_hits = re.findall(r"\b(if|in case|otherwise|unless)\b", normal_course, re.I)
if conditional_hits:
results.append(check("C14", "FAIL", f"Conditional language found in Normal Course: {', '.join(sorted(set(w.lower() for w in conditional_hits)))} -- move to Alternative/Exception"))
else:
results.append(check("C14", "PASS", "No embedded if/otherwise/unless in Normal Course"))
# C15: flow completeness -- judgment call
results.append(check("C15", "MANUAL", "Trigger-to-postcondition completeness needs semantic review"))
# C16: Alternative Courses format
ac = fields.get("alternative_courses", "")
if not ac.strip():
results.append(check("C16", "WARN", "No Alternative Courses provided (acceptable if none apply)"))
else:
ac_ids = re.findall(r"UC-[\w.\-]+\.AC\.\d+", ac)
has_at_step = "at step" in ac.lower()
has_continue = "continue from step" in ac.lower()
if ac_ids and has_at_step and has_continue:
results.append(check("C16", "PASS", f"{len(ac_ids)} AC(s) with 'at step' + 'continue from step'"))
else:
missing = []
if not ac_ids:
missing.append("UC-XX.AC.N id")
if not has_at_step:
missing.append("'at step N' anchor")
if not has_continue:
missing.append("'continue from step' rejoin")
results.append(check("C16", "WARN", f"Alternative Course missing: {', '.join(missing)}"))
# C17: Exceptions have trigger/response/final state
exceptions = fields.get("exceptions", "")
if not exceptions.strip():
results.append(check("C17", "FAIL", "No Exceptions found -- happy-path-only UCs are insufficient (see C18)"))
else:
ex_ids = re.findall(r"UC-[\w.\-]+\.EX\.\d+", exceptions)
has_trigger = "trigger" in exceptions.lower()
has_response = "response" in exceptions.lower()
has_final = "final state" in exceptions.lower()
if ex_ids and has_trigger and has_response and has_final:
results.append(check("C17", "PASS", f"{len(ex_ids)} exception(s) with trigger/response/final state"))
else:
missing = [n for n, c in (("id", ex_ids), ("Trigger:", has_trigger), ("Response:", has_response), ("Final state:", has_final)) if not c]
results.append(check("C17", "WARN", f"Exception(s) missing: {', '.join(missing)}"))
# C18: common failure modes covered
hits = [w for w in FAILURE_MODE_KEYWORDS if w in exceptions.lower()]
if len(hits) >= 2:
results.append(check("C18", "PASS", f"Failure-mode keywords present: {', '.join(hits)}"))
elif hits:
results.append(check("C18", "WARN", f"Only one failure-mode keyword present ({hits[0]}) -- consider more coverage"))
else:
results.append(check("C18", "FAIL", "No common failure-mode keywords found in Exceptions"))
# C19: Includes point to existing UCs
includes = fields.get("includes", "")
if not includes.strip():
results.append(check("C19", "WARN", "No Includes -- acceptable if this UC has no shared sub-flows"))
else:
inc_ids = re.findall(r"UC-[\w.\-]+", includes)
if not inc_ids:
results.append(check("C19", "FAIL", "Includes field has no recognizable UC-ID"))
elif registry:
unknown = [i for i in inc_ids if i not in registry]
if unknown:
results.append(check("C19", "FAIL", f"Included UC(s) not found in registry: {', '.join(unknown)}"))
else:
results.append(check("C19", "PASS", f"All {len(inc_ids)} included UC(s) found in registry"))
else:
results.append(check("C19", "MANUAL", f"Includes reference {', '.join(inc_ids)} -- pass --registry to verify existence"))
# C20: Special Requirements are non-functional
special = fields.get("special_requirements", "")
functional_leak = re.search(r"\b(validate|must be exactly|characters|business rule)\b", special, re.I)
if not special.strip():
results.append(check("C20", "WARN", "Special Requirements is empty"))
elif functional_leak:
results.append(check("C20", "WARN", f"Possible functional requirement leaking in: '{functional_leak.group(0)}'"))
else:
results.append(check("C20", "PASS", "No obvious functional-requirement language detected"))
return results
def format_table(uc_id, results):
lines = [f"## Validation Result for {uc_id or '(unknown UC ID)'}", "", "| # | Status | Note |", "|---|--------|------|"]
icon = {"PASS": "PASS", "FAIL": "FAIL", "WARN": "WARN", "MANUAL": "MANUAL"}
for r in results:
lines.append(f"| {r['item']} | {icon[r['status']]} | {r['note']} |")
passed = sum(1 for r in results if r["status"] == "PASS")
failed = sum(1 for r in results if r["status"] == "FAIL")
warned = sum(1 for r in results if r["status"] == "WARN")
manual = sum(1 for r in results if r["status"] == "MANUAL")
lines += ["", f"**Summary**: {passed} PASS / {warned} WARN / {failed} FAIL / {manual} MANUAL out of {len(results)}."]
if failed:
lines.append("**Verdict**: FIX FAILING ITEMS before handover.")
elif warned:
lines.append("**Verdict**: Review WARN items, then run the LLM-driven Step 4 checklist before handover.")
else:
lines.append("**Verdict**: Mechanical checks clean. Still run MANUAL items and the LLM-driven Step 4 checklist before handover.")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="Mechanical first pass over the use-case-writer 20-point checklist.")
parser.add_argument("input", nargs="?", help="Path to a UC Markdown file (assets/uc-template.md format)")
parser.add_argument("--registry", help="Path to a text file listing known UC IDs (one per line), used to verify C19 Includes")
parser.add_argument("--json", action="store_true", help="Output JSON instead of a Markdown table")
parser.add_argument("--sample", action="store_true", help="Run against the bundled sample UC instead of a file")
args = parser.parse_args()
if args.sample:
text = SAMPLE_UC
elif args.input:
with open(args.input, "r", encoding="utf-8") as f:
text = f.read()
else:
parser.error("provide an input file or --sample")
return
registry = None
if args.registry:
with open(args.registry, "r", encoding="utf-8") as f:
registry = {line.strip() for line in f if line.strip()}
fields = parse_uc(text)
results = run_checks(fields, registry)
if args.json:
print(json.dumps({"uc_id": fields.get("uc_id", ""), "results": results}, indent=2))
else:
print(format_table(fields.get("uc_id", ""), results))
sys.exit(1 if any(r["status"] == "FAIL" for r in results) else 0)
if __name__ == "__main__":
main()
Tư vấn Chief AI Officer: chọn API, tinh chỉnh hay tự xây, phân loại rủi ro AI, kinh tế chi phí AI và tổ chức nhóm AI.
---
name: "chief-ai-officer-advisor"
description: "Chief AI Officer advisory for startups: model build-vs-buy decisions (API vs fine-tune vs in-house), AI risk classification under EU AI Act + US state patchwork, AI cost economics (API-to-self-hosted breakeven), and AI team org evolution. Use when deciding whether to call an API or fine-tune, classifying AI use cases for regulatory risk, calculating when self-hosting pays off, sequencing AI hires, or when user mentions CAIO, AI strategy, model selection, foundation model, fine-tuning, EU AI Act, NIST AI RMF, AI governance, model risk, or AI economics. Strategic only — does not duplicate engineering AI/ML skills."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: chief-ai-officer-leadership
updated: 2026-05-12
python-tools: model_buildvsbuy_calculator.py, ai_risk_classifier.py, ai_cost_economics.py
frameworks: model-buildvsbuy, ai-risk-governance, ai-economics, ai-team-org
---
# Chief AI Officer Advisor
Strategic AI leadership for startup CAIOs and founders without one. **Four decisions, no AI hype:**
1. **Should we use an API, fine-tune, or build our own?** — model build-vs-buy with 3-year TCO
2. **Is this AI use case high-risk under regulation, and how do we govern it?** — EU AI Act + NIST AI RMF + US state patchwork
3. **When do we switch from API to self-hosted, and at what cost?** — token economics with breakeven analysis
4. **What AI role do we hire next?** — stage-to-role map (AI engineer ≠ ML engineer ≠ research scientist)
This skill does **not** cover tactical AI/ML engineering. For RAG implementation, agent design, prompt engineering, eval infrastructure, model deployment, or cost optimization, see `engineering/rag-architect/`, `engineering/agent-designer/`, `engineering/prompt-governance/`, `engineering/self-eval/`, `engineering/llm-cost-optimizer/`.
## Keywords
CAIO, chief AI officer, AI strategy, model selection, foundation model, fine-tuning, RLHF, DPO, LoRA, QLoRA, build vs buy, AI build-vs-buy, model risk tier, EU AI Act, AI Act Article 6, Article 9, Article 10, Annex III, prohibited AI, high-risk AI, NIST AI RMF, AI risk management framework, NYC Local Law 144, Colorado SB 21-169, Illinois HB 53, model card, eval set, eval harness, hallucination rate, jailbreak risk, prompt injection, AI red team, AI safety, alignment, model lifecycle, model registry, API-to-self-hosted breakeven, GPU economics, A100, H100, inference cost, fine-tuning cost, AI team, AI engineer, ML engineer, research scientist, MLOps, AI platform
## Quick Start
```bash
# Decision A: API vs fine-tune vs build
python scripts/model_buildvsbuy_calculator.py # embedded customer-support sample
python scripts/model_buildvsbuy_calculator.py path/to/use_case.json
# Decision B: Risk classification under EU AI Act + US state laws
python scripts/ai_risk_classifier.py # embedded hiring-AI sample
python scripts/ai_risk_classifier.py path/to/use_case.json
# Decision C: API vs self-hosted economics
python scripts/ai_cost_economics.py # embedded 5M tokens/day sample
python scripts/ai_cost_economics.py path/to/workload.json
```
## Key Questions (ask these first)
- **What does this AI need to be good at, and how would you measure it?** (If no eval set, no ship.)
- **What's the SLO on hallucination / error rate?** (Without one, "AI quality" is a vibe.)
- **What happens when the model is wrong?** (Fallback behavior, human-in-the-loop, blast radius.)
- **What's the risk tier under EU AI Act, and is conformity assessment required?** (Determines product launch timeline.)
- **At what monthly token volume does self-hosting beat API?** (Almost never below 100M tokens/month at frontier quality.)
- **Are we hiring an AI engineer or an ML research scientist?** (Different jobs; founders confuse them.)
## Core Responsibilities
### 1. Model Build-vs-Buy
The decision is not "use AI or not" — it's **API vs fine-tune vs in-house** for each use case. Each path has a different TCO curve, latency profile, and capability ceiling.
**Default path: API (frontier model)**
- Use when: well-served by frontier (Claude, GPT, Gemini), QPS < 100, latency budget > 1s, cost < $50K/month
- Why: frontier APIs are 10-100x more capable than what most teams can fine-tune in-house
- Failure mode: API rate limits at scale, vendor lock-in, capability drift between model versions
**Fine-tune a smaller model**
- Use when: domain-specific behavior the API can't be prompted into (medical coding, legal redlining), high volume reducing API cost, latency budget < 500ms, specific style/format consistency required
- Approaches: full fine-tune (rare), LoRA/QLoRA (common), RLHF/DPO (when alignment matters)
- Failure mode: fine-tuned model lags frontier capability within 6-12 months; ongoing retraining cost
**Build from scratch / pre-train**
- Use when: almost never. You're a foundation-model company, OR you have a unique data corpus, $50M+ funding, and 18+ month patience.
- Failure mode: by the time you ship, frontier models have caught up and your sunk cost is unrecoverable
**Run** `model_buildvsbuy_calculator.py` for a use-case-specific recommendation with 3-year TCO. See `references/model_buildvsbuy_strategy.md` for full decision tree.
### 2. AI Risk Classification & Governance
The 2026 question every founder is facing: **does this AI use case trigger high-risk regulatory obligations?**
**EU AI Act (in force 2026) tiers:**
| Tier | Examples | Obligations |
|---|---|---|
| **Prohibited** | Social scoring, real-time biometric surveillance, manipulative AI | Cannot deploy in EU |
| **High-risk** | Employment screening, credit scoring, education access, critical infrastructure, law enforcement, biometric ID | Conformity assessment, registration, post-market monitoring, transparency, human oversight |
| **Limited-risk** | Chatbots, deepfakes, emotion recognition | Transparency: user must know they're interacting with AI |
| **Minimal-risk** | Recommendation systems, spam filters, most B2B SaaS internals | No specific obligations |
**Run** `ai_risk_classifier.py` to classify a use case and get the required-controls list.
**US state patchwork (non-exhaustive):**
- NYC LL 144 — Automated Employment Decision Tools (AEDTs) require annual bias audit + candidate notice
- Colorado AI Act / SB 21-169 — AI in consumer decisions (credit, insurance, employment, housing)
- Illinois HB 53 — AI in interview/hiring
- California SB 1001 — Bot disclosure
- Texas TCPA — Biometric identifier capture
- Federal NIST AI RMF — voluntary; increasingly referenced in contracts
**Industry-specific overlays:**
- Healthcare: FDA AI/ML guidance (2023), MDR (EU) for medical-device AI, 510(k) pathway for AI/ML-enabled medical devices
- Financial: NYDFS Reg 23, FTC Section 5, ECOA for credit decisions
- Insurance: NAIC model bulletin, state insurance commissioner rules
See `references/ai_risk_governance.md` for the full regulatory landscape + governance program checklist.
### 3. AI Cost Economics
**The breakeven question:** at what monthly token volume does self-hosted inference beat API costs?
**Key components:**
- **API cost** — variable, per-token. Frontier models 2026: Claude Sonnet 4.6 ~$3/$15 per M tokens (input/output), GPT-4o ~$2.50/$10, Gemini 2.5 ~$1.25/$5
- **Self-hosted cost** — fixed (GPU commitment) + variable (electricity). H100 spot ~$2-5/hour, A100 spot ~$1-3/hour. Llama 3.1 70B / Qwen 2.5 72B: ~$0.50-2.00 per million output tokens at 70% utilization
- **Hidden costs of self-hosting** — ops on-call, monitoring, model updates, scaling overhead, idle time penalty
- **Hidden costs of API** — rate limits requiring multi-vendor failover, vendor lock-in, capability drift between versions, data residency
**Typical breakeven (frontier-quality):** 100M–500M tokens/month, depending on model size and acceptable quality tradeoff. Below this, API wins. Above this, run the calculator.
**Run** `ai_cost_economics.py` with workload characteristics for a breakeven point + sensitivity to GPU rates and model size.
See `references/ai_cost_economics.md` for the full economics model and operational considerations.
### 4. AI Team Org Evolution
**The wrong question:** "Should we hire an ML engineer or a research scientist?"
**The right question:** "What's the next AI capability we need to ship, and what role unblocks that?"
Stage-to-role map:
| Stage | First AI hire | Then | Then |
|---|---|---|---|
| Pre-PMF | Founder + 1 ML-curious engineer playing with prompts | — | — |
| Series A | **AI engineer** (applied, full-stack; owns prompts/evals/deployment) | Second AI engineer for evals/quality | — |
| Series B | AI/ML platform engineer (inference, evals, observability) | Third AI engineer for production reliability | Data scientist if model is core IP |
| Series C | Manager of AI | ML research scientist (only if model IS the product) | AI safety / red team (if customer-facing AI) |
| Late-stage | Head of AI → CAIO | Multiple research scientists, platform team, safety/red team | Federated AI leads per business unit |
**Critical distinctions:**
- **AI engineer** ≠ **ML engineer** ≠ **research scientist**
- AI engineer: full-stack + prompts + evals + deployment. Most startups need this, not the others.
- ML engineer: production deployment, monitoring, retraining infrastructure. Hire after data engineer.
- Research scientist: model invention, novel architectures. Only at Series C+ if model is core IP.
**Centralize-vs-embed for AI:** AI starts centralized (one team) and stays there longer than data team, because the surface area is smaller. Embed only when AI is being deployed in 4+ product surfaces.
See `references/ai_team_org_evolution.md`.
## Workflows
### Workflow 1: Model Selection Decision (1 hour)
**Goal:** Decide whether a specific use case should use API, fine-tune, or build.
```bash
# 1. Define use_case.json (volume, latency, accuracy, team size, budget)
python scripts/model_buildvsbuy_calculator.py use_case.json
# 2. Review 3-year TCO + breakeven
# 3. Cross-check with cs-cfo-advisor on budget commitment
# 4. Cross-check with cs-cto-advisor on engineering capacity (esp. for fine-tune)
# 5. Log via /cs:decide; consider /cs:freeze 60 on multi-year vendor commitment
```
### Workflow 2: AI Risk Classification (2-4 hours)
**Goal:** Classify a use case under EU AI Act + US state laws, identify required controls.
```bash
# 1. Define use_case.json (decisions affected, users, geography, sector)
python scripts/ai_risk_classifier.py use_case.json
# 2. For HIGH-RISK: budget conformity assessment + registration
# 3. For LIMITED-RISK: implement transparency requirements
# 4. Cross-check with cs-general-counsel-advisor on contractual implications
# 5. Cross-check with cs-ciso-advisor on technical safeguards
# 6. Log via /cs:decide
```
### Workflow 3: API-to-Self-Hosted Breakeven (1 day)
**Goal:** Decide when (and whether) to migrate from API to self-hosted inference.
```bash
# 1. Build workload.json (tokens/day, model size, latency, quality tolerance)
python scripts/ai_cost_economics.py workload.json
# 2. Run sensitivity scenarios (low/mid/high GPU rates)
# 3. Estimate migration cost (engineering time + risk)
# 4. Cross-check with cs-cfo-advisor on capex commitment
# 5. Cross-check with cs-cto-advisor on platform readiness
# 6. Log via /cs:decide; pair with /cs:freeze if signing GPU commitment
```
### Workflow 4: AI Team Roadmap (1 week)
**Goal:** Sequence next 18 months of AI hires aligned to capabilities to ship.
1. List top 5 AI capabilities the product needs in 12 months
2. Map each capability to the role that ships it (see `ai_team_org_evolution.md`)
3. Sequence hires (one role at a time, ramp before next)
4. Cross-check with cs-chro-advisor on comp + leveling
5. Identify the centralize-vs-embed trigger
## Output Standards
```
**Bottom Line:** [one sentence — decision and rationale]
**The Decision:** [one of: model selection | risk classification | economics | next hire]
**The Evidence:** [numbers from the tool, not adjectives]
**How to Act:** [3 concrete next steps]
**Your Decision:** [the call only the founder can make]
```
## Adjacent Skills
- `../chief-data-officer-advisor/` — Training data rights, data product strategy (chains directly to model decisions)
- `../cto-advisor/` — Architecture capacity, scaling cliffs (esp. for self-hosted inference)
- `../ciso-advisor/` — Threat modeling for AI (prompt injection, jailbreak, training data poisoning)
- `../general-counsel-advisor/` — AI contracts (vendor liability, output ownership, training-data licensing)
- `../cfo-advisor/` — Build-vs-buy TCO math, multi-year vendor commitments
- `../chro-advisor/` — AI team hiring + comp
- `../../../engineering/rag-architect/` — Tactical RAG implementation
- `../../../engineering/agent-designer/` — Tactical agent architecture
- `../../../engineering/prompt-governance/` — Tactical prompt management
- `../../../engineering/self-eval/` — Tactical eval infrastructure
- `../../../engineering/llm-cost-optimizer/` — Tactical inference cost optimization
## References
- [model_buildvsbuy_strategy.md](references/model_buildvsbuy_strategy.md) — Full decision tree + 3-year TCO components + when each path fails
- [ai_risk_governance.md](references/ai_risk_governance.md) — EU AI Act + NIST AI RMF + US state patchwork + industry overlays + governance program
- [ai_cost_economics.md](references/ai_cost_economics.md) — API pricing 2026 + GPU rental economics + utilization realities + migration cost
- [ai_team_org_evolution.md](references/ai_team_org_evolution.md) — Stage-to-role map + role definitions (AI engineer ≠ ML engineer ≠ scientist) + anti-patterns
---
**Version:** 1.0.0
**Status:** Production Ready
**Disclaimer:** AI regulation is evolving rapidly. This skill surfaces decisions and tradeoffs as of 2026 but cannot replace qualified AI counsel for binding compliance decisions, especially under EU AI Act conformity assessments.
FILE:references/ai_cost_economics.md
# AI Cost Economics — The Decision: "When does self-hosted beat API, and at what hidden cost?"
This reference answers exactly one decision: **at what monthly token volume does self-hosting beat API, and what hidden costs determine whether the migration is worth it?**
Pair with `scripts/ai_cost_economics.py` for automation.
## The Mental Model
API cost is **fully variable**: linear in token volume, zero fixed cost.
Self-hosted cost is **mostly fixed**: warm GPUs cost the same whether you process 1M or 1B tokens. The marginal cost of additional tokens approaches the marginal electricity + amortization cost, which is small.
The crossover happens where API variable cost exceeds the self-hosted fixed floor. **For 70B-class models on rented A100s, this is typically 1–10 billion tokens per month** depending on which API tier you're comparing against and what GPU pricing you can negotiate.
## 2026 API Pricing (illustrative; verify quarterly)
Per million tokens, USD:
| Tier | Example models | Input | Output |
|---|---|---|---|
| Frontier-premium | Claude Sonnet 4.6, GPT-4o-tier | $3.00 | $15.00 |
| Frontier-economy | Gemini 2.5 Flash, Claude Haiku 4.5-tier | $1.25 | $5.00 |
| Open-hosted | Llama 3.1 70B / Qwen 2.5 72B via Together, Fireworks, OpenRouter | $0.50 | $1.50 |
| Open-economy | 8B-13B-class hosted | $0.10 | $0.30 |
**Caveats:**
- Frontier pricing dropped ~10x from 2023 to 2026 and continues to drop. Pin your TCO to current pricing only.
- Provider rate limits matter: Tier 1 customers get throttled at QPS spikes; Tier 4+ (~$10K+/mo commitment) get burst capacity.
- Long-context surcharge: requests >100K tokens often charged differently.
- Caching: most providers offer prompt caching at 50-90% discount on cached tokens. Significantly changes economics for repeated system prompts.
## Self-Hosted Inference Economics
### GPU Rental Pricing (2026 spot, $/hour)
| GPU | Low | Mid | High |
|---|---|---|---|
| A100 (40/80GB) | $1.50 | $2.50 | $3.50 |
| H100 (80GB) | $3.50 | $5.00 | $8.00 |
| H200 (141GB) | $5.00 | $7.50 | $12.00 |
| B200 (192GB, limited availability) | $8.00 | $14.00 | $22.00 |
Pricing varies by provider (AWS, GCP, Azure, Lambda, RunPod, Coreweave, Crusoe, etc.), commitment (spot, on-demand, reserved 1-yr, reserved 3-yr), and geographic region.
### How Many GPUs Do You Need?
Per model size, minimum to serve at frontier-equivalent quality:
| Model class | A100-80GB | H100 | Why |
|---|---|---|---|
| 7B-13B | 1 | 1 | Fits in single GPU memory |
| 70B-class (fp16) | 4 | 2 | ~140GB weights + KV cache |
| 405B-class | 8 | 4 | Multi-GPU tensor parallelism |
| Mixture-of-Experts (e.g., Mixtral 8x22B active) | 4 | 2 | Sparse routing reduces active params |
### Throughput (tokens/sec/GPU at 70% utilization)
| Model class | A100 | H100 |
|---|---|---|
| 7B-13B | ~1,500 | ~3,500 |
| 70B-class | ~200 | ~600 |
### Cost Per Million Tokens (rough)
70B-class on rented A100s at $2.50/hr × 4 GPUs at 70% utilization = $10/hr for 4 × 200 × 0.7 × 3600 tokens/hr = ~2M tokens/hr → **$5/M tokens.**
70B-class on rented H100s at $5/hr × 2 GPUs at 70% utilization = $10/hr for 2 × 600 × 0.7 × 3600 tokens/hr = ~3M tokens/hr → **$3.30/M tokens.**
Compare to API frontier-economy at $1.25/$5 input/output → blended ~$2.50/M tokens for typical 4:1 input:output ratio.
**Bottom line:** self-hosted 70B-class is roughly equivalent to or slightly more expensive than frontier-economy API at the per-token level. The "savings" only appear when self-hosted is highly utilized AND the alternative is frontier-premium API.
## Utilization Reality Check
The 70% utilization assumption above is **optimistic**. Realistic utilization patterns:
- **Continuous batch workload** (e.g., async classification): 60-80% achievable with proper batching
- **User-facing interactive (chat):** 20-40% typical — bursty demand, idle time between user turns
- **Mixed workload:** 30-50%
If your utilization is 30% instead of 70%, your effective cost per token roughly doubles. Plan for utilization explicitly.
## Hidden Costs of Self-Hosted
### 1. Ops On-Call
- 24/7 on-call rotation requires ≥3 engineers
- Pager duty for inference outages
- Realistic attribution: 30% of one engineer (~$75K/yr fully-loaded)
- At scale: dedicated MLOps team
### 2. Monitoring & Observability
- Token throughput, latency p50/p95/p99
- Quality monitoring (drift, hallucination rate vs eval set)
- GPU health, memory pressure, OOM events
- Cost monitoring (idle GPU detection)
- **Budget:** $5-20K/mo in tooling (Datadog, Honeycomb, custom)
### 3. Model Updates
- Open-weights models release new versions every 3-6 months
- Each update requires re-evaluation against your eval set
- Quality regressions are common; rollback path required
- **Budget:** 1-2 engineer-weeks per quarter
### 4. Capacity Planning
- Warm GPUs must serve peak QPS, not average
- 2-3x over-provisioning typical for user-facing workloads
- Auto-scaling exists but has 5-10 minute lag for GPU warm-up
### 5. Failover & Redundancy
- Single-region self-hosting is a single point of failure
- Multi-region adds 2x capex
- Or: hybrid with API failover (best of both, but requires routing logic)
### 6. Security & Compliance
- Self-hosted = you own the security boundary
- SOC 2 / ISO 27001 scope expands to inference infrastructure
- Model weights protection (worth $$ if fine-tuned proprietary)
## Hidden Costs of API
### 1. Vendor Lock-In
- Migration to another provider: 2-8 weeks of engineering work
- Output format differences, prompt sensitivity differences
- Mitigation: abstraction layer (LiteLLM, OpenRouter, Portkey) — $100-500/mo + engineering time
### 2. Capability Drift
- Provider updates models silently or with brief notice
- Your prompts may produce different outputs after upgrade
- Mitigation: pin model IDs (e.g., `claude-sonnet-4-6` vs `claude-sonnet-latest`)
- Cost: regression eval runs on every model swap
### 3. Rate Limits
- Default tiers throttle aggressively
- Burst capacity requires Tier 4+ commitment ($10K+/mo)
- Mitigation: multi-vendor load balancing (failure path: degraded quality)
### 4. Long-Context Pricing
- Many providers charge differently above 100K-200K context
- 1M-token context (Gemini, Claude) priced higher per token
### 5. Data Residency
- EU customers may require EU-only inference (Claude EU, Azure OpenAI EU regions, Vertex EU)
- Limits provider options
### 6. Privacy / Training Data Use
- Default provider TOS often allows training on your inputs
- Enterprise / business contracts disable this (zero retention available from major providers)
- Mitigation: enterprise contract; verify zero-retention clause
## Migration Cost: API → Self-Hosted
Realistic engineering effort for a production migration:
| Phase | Effort |
|---|---|
| Inference platform setup (vLLM, TGI, TensorRT-LLM) | 4-6 weeks |
| Model deployment + benchmarking | 2-3 weeks |
| Eval harness rebuild (different model = different eval) | 2-4 weeks |
| Production rollout with shadow traffic | 4-8 weeks |
| Monitoring + on-call setup | 2-4 weeks |
| **Total** | **3-6 months, 2-3 engineers** |
At fully-loaded $250K/engineer/yr, migration cost is ~$150-300K in engineering time alone, plus migration risk (regressions, latency spikes during rollout).
**Implication:** migration should pay back in 12-18 months of cost savings, OR provide a strategic capability (data residency, capability not in API).
## Decision Heuristics
### Stay with API when:
- Monthly cost < $50K
- Volume < 500M tokens/month
- Latency p95 acceptable at API levels
- No compliance forcing self-host
- ML team < 3 engineers
### Consider hybrid when:
- $50K-$500K/mo API spend
- Some workloads have predictable high volume (good for self-host)
- Some workloads have bursty / low-volume (good for API)
- Have ML platform engineer in seat
### Migrate to self-hosted when:
- > 500M tokens/month on stable workload
- $250K+/mo API spend
- Data residency / sovereignty requires it
- Have 2+ ML engineers and 1 platform engineer
- 3-6 month migration capacity available
- Multi-year stable workload (don't migrate if you're pivoting)
### Hybrid is often the right answer.
## Prompt Caching: The Underrated Lever
Most major providers (Anthropic, OpenAI, Google) offer prompt caching: cached input tokens cost 10-50% of normal.
**When it dominates economics:**
- Repeated system prompt across queries (typical for agents, RAG)
- Large context with small variable suffix
- Multi-turn conversations
**Realistic savings:** 30-70% reduction in input token costs for cache-friendly workloads. Often makes self-host migration unnecessary by closing the cost gap.
## Failure Modes
### API failure modes
- **Vendor outage during peak hours** — multi-vendor failover required for B2B SaaS SLAs
- **Capability degradation between versions** — pin model IDs and run regressions
- **Rate limit surprise** — Tier 1 customers get throttled; commit to higher tier
### Self-hosted failure modes
- **Quality regression on model update** — invisible without eval set
- **GPU spot price spike** — convert to reserved capacity for predictability above $20K/mo
- **Idle GPU bleeding cash** — auto-shutdown / dynamic scaling required
- **Out-of-memory at peak** — KV cache pressure during long-context burst
## When This Reference Doesn't Help
- **Tactical inference optimization (quantization, speculative decoding, vLLM tuning).** See `engineering/llm-cost-optimizer/`.
- **Prompt caching implementation.** See `engineering/prompt-governance/`.
- **Multi-vendor abstraction implementation.** See `engineering/agent-designer/` and LiteLLM/OpenRouter docs.
This reference is about strategic economics and the migration decision, not tactical implementation.
---
**Source authorities (non-exhaustive):**
- Kwon et al., "Efficient Memory Management for Large Language Model Serving with PagedAttention" (vLLM, 2023)
- "DistServe: Disaggregating Prefill and Decoding for Goodput-optimized LLM Serving" (NSDI 2024)
- Stanford HELM benchmark — public LLM cost / quality / latency tracking
- Artificial Analysis (artificialanalysis.ai) — independent LLM pricing and performance tracking
- Anthropic, OpenAI, Google Cloud, AWS Bedrock pricing pages (verify current)
- Together AI, Fireworks, OpenRouter, Replicate pricing pages (verify current)
- "Llama 3.1: Open Foundation and Instruction Models" — model performance vs frontier benchmarks
- Lambda Labs, Coreweave, Runpod GPU pricing pages (verify current; spot pricing is volatile)
FILE:references/ai_risk_governance.md
# AI Risk & Governance — The Decision: "Is this AI use case high-risk, and how do we govern it?"
This reference answers exactly one decision: **for a specific AI use case, which regulations apply, what risk tier does it fall into, and what governance program is required?**
Pair with `scripts/ai_risk_classifier.py` for automation. **Not legal advice.**
## EU AI Act — The Centerpiece (in force 2026)
The EU AI Act (Regulation (EU) 2024/1689) is the most comprehensive AI regulation globally. It applies to any AI system **placed on the EU market or whose output is used in the EU**, regardless of where the provider is established.
### Risk Tiers (Article 5–7, Annex III)
#### 🔴 Tier 1: Prohibited (Article 5)
Cannot be deployed in EU at any safeguard level:
- **Social scoring** by public authorities causing detrimental treatment (Art. 5(1)(c))
- **Real-time remote biometric identification** by law enforcement in publicly accessible spaces (narrow exceptions for specific serious crimes only) (Art. 5(1)(h))
- **Subliminal manipulation** beyond a person's consciousness to materially distort behavior (Art. 5(1)(a))
- **Exploitation of vulnerabilities** (age, disability, social/economic situation) to materially distort behavior (Art. 5(1)(b))
- **Predictive policing** based solely on profiling (Art. 5(1)(d))
- **Untargeted facial recognition** scraping from internet or CCTV (Art. 5(1)(e))
- **Emotion recognition** in workplace or educational institutions (Art. 5(1)(f))
- **Biometric categorization** to infer race, political opinions, religion, etc. (Art. 5(1)(g))
#### 🟠 Tier 2: High-Risk (Article 6 + Annex III)
Permitted, but heavy obligations:
**Annex III domains:**
1. Biometric identification and categorization
2. Critical infrastructure (water, gas, electricity, traffic management)
3. Education and vocational training (access, assessment, monitoring during exams)
4. Employment, workers management (recruitment selection, promotion, task allocation)
5. Access to essential services (credit scoring, insurance pricing, public benefits, emergency dispatch)
6. Law enforcement (risk assessment, lie detection, evidence reliability, profiling)
7. Migration, asylum, border control (visa/asylum decisions, risk assessment)
8. Administration of justice and democratic processes
**Obligations for high-risk AI (Articles 8–15, 43, 49, 72):**
| Obligation | Article |
|---|---|
| Risk management system throughout lifecycle | Art. 9 |
| Data governance: representative, accurate, complete training data; bias mitigation | Art. 10 |
| Technical documentation per Annex IV | Art. 11 |
| Record-keeping / logging for traceability | Art. 12 |
| Transparency and instructions for use | Art. 13 |
| Human oversight design (override, stop button, monitoring) | Art. 14 |
| Accuracy, robustness, cybersecurity | Art. 15 |
| Quality management system | Art. 17 |
| Conformity assessment (self-assessment for most; Notified Body for biometric) | Art. 43 |
| Registration in EU database before deployment | Art. 49 |
| Post-market monitoring | Art. 72 |
| Serious incident reporting (within 15 days) | Art. 73 |
**Timeline cost:** Conformity assessment typically 3-6 months for self-assessment, 6-12 months when Notified Body involvement required.
#### 🟡 Tier 3: Limited-Risk (Article 50, 52)
Transparency obligations:
- **Chatbots:** users must be informed they are interacting with AI (Art. 50(1))
- **Deepfakes / AI-generated content:** must be marked as AI-generated (Art. 50(2))
- **Emotion recognition / biometric categorization** (outside Annex III): user notice required
- **General-purpose AI models:** model cards documenting capabilities, limitations, training-data summary (Art. 53)
#### 🟢 Tier 4: Minimal-Risk
No specific obligations. Voluntary codes of conduct recommended (e.g., transparency, model cards). Most B2B SaaS internal AI falls here (recommendation systems, spam filters, productivity assistants).
### General-Purpose AI Models (Article 51–55)
If you build a general-purpose AI model (foundation model), additional obligations apply:
- Technical documentation
- Information to downstream providers
- Training-data summary
- Compliance with EU copyright (especially text-and-data-mining opt-outs)
If your model is "systemic risk" (training compute > 10^25 FLOP, currently includes GPT-4, Claude, Gemini, Llama 3.1 405B+):
- Model evaluation
- Systemic risk assessment + mitigation
- Cybersecurity protections
- Serious incident reporting
## NIST AI Risk Management Framework (AI RMF 1.0)
US voluntary framework, increasingly referenced in B2B contracts and federal procurement.
**Four functions:**
1. **GOVERN** — Policy, roles, accountability, oversight
2. **MAP** — Context, impact assessment, stakeholders
3. **MEASURE** — Quantify, monitor, evaluate trustworthiness
4. **MANAGE** — Treat, prioritize, monitor risks
**Trustworthy characteristics:**
- Valid and reliable
- Safe
- Secure and resilient
- Accountable and transparent
- Explainable and interpretable
- Privacy-enhanced
- Fair with harmful bias managed
**Why it matters:** even outside government contracts, NIST AI RMF compliance is increasingly demanded by enterprise customers in security questionnaires (2025–2026 trend).
## US State Patchwork
### NYC Local Law 144 (Automated Employment Decision Tools)
- **Trigger:** AI/algorithmic decision-making in hiring or promotion for NYC-based employees
- **Obligations:** Annual independent bias audit (with EEO-1 categories); candidate notice 10+ business days before use; publication of audit summary on company website
- **Penalty:** $375-$1,500 per violation per day
- **Citation:** NYC Local Law 144 of 2021; 6 RCNY § 5-300
### Colorado AI Act (SB 21-169 and 2024 amendments)
- **Trigger:** High-risk AI in consumer-impacting decisions (employment, credit, insurance, healthcare, housing, government services, legal services)
- **Obligations:** Reasonable care to protect from algorithmic discrimination; annual impact assessment; consumer notice when used; right to appeal; comprehensive risk management policy
- **Effective:** February 2026
- **Citation:** Colorado SB 21-169; CRS § 6-1-1701 et seq.
### Illinois (multiple laws)
- **HB 53 (AI Video Interview Act):** Candidate notice + consent before AI analyzes video interview; explanation of how AI is used; deletion within 30 days of request. (820 ILCS 42/)
- **HB 3773 (AI hiring 2024):** Bans AI use in employment decisions that "tends to" discriminate based on protected class
- **BIPA (740 ILCS 14/):** Written informed consent for biometric capture; statutory damages $1K-$5K per violation; private right of action (massive class action exposure)
### California
- **SB 1001 (B.O.T. Act):** Bot disclosure in commercial transactions and CA elections
- **AB 2013 (2024):** Training-data transparency for generative AI providers
- **AB 1008 (2024):** AI-generated content disclosure in elections
- **CCPA / CPRA:** Right to know about automated decision-making; opt-out rights (CCPA § 1798.140 et seq.)
### Texas (BIPA-equivalent)
- Capture-of-biometric-identifier rules (Texas Business & Commerce Code § 503.001)
### Washington
- My Health My Data Act: consumer health data including AI-inferred health attributes (RCW 19.373)
## Industry-Specific Overlays
### Healthcare
- **FDA AI/ML guidance (2023, updated 2024):** Software as Medical Device (SaMD) classification; Predetermined Change Control Plan for adaptive models; Good Machine Learning Practices (GMLP)
- **Regulatory pathways:** 510(k), De Novo, or PMA depending on risk class
- **EU MDR + IVDR:** Medical-device AI deployed in EU requires CE marking + Notified Body (most cases)
- **HIPAA:** Patient data + AI → BAA + Limited Data Set rules
### Financial Services
- **CFPB Circular 2023-03:** Adverse action notices for AI-driven credit decisions must give specific reasons, not "the algorithm said no"
- **Fed SR 11-7 (model risk management):** Applies if you're a bank; influences vendor expectations
- **NYDFS Reg 23 (cybersecurity):** AI systems in financial services require risk assessment + governance
- **SEC AI rule proposal (2023, ongoing):** Investment adviser conflicts-of-interest disclosure for AI predictive analytics
- **ECOA (15 USC §1691):** Anti-discrimination in credit; applies to AI-driven underwriting
### Insurance
- **NAIC Model Bulletin on AI (2023):** AI governance, risk management, third-party AI oversight; state insurance commissioners are adopting variants
- **NY Insurance Reg 187:** Consumer-facing AI in insurance must not discriminate
### Critical Infrastructure / Defense
- **CISA AI Roadmap (2024):** Guidance for AI in critical infrastructure
- **DoD AI Ethical Principles (2020):** Responsible, equitable, traceable, reliable, governable
- **ITAR / EAR:** Some AI capabilities are export-controlled
## Governance Program Checklist
For any organization with > 1 production AI use case, build a governance program with:
1. **AI inventory** — every model in production, owner, use case, risk tier
2. **Risk classification** — every use case classified under EU AI Act + applicable US laws
3. **Eval sets** — every model has documented success criteria
4. **Monitoring** — drift, bias, performance, incident detection
5. **Incident response** — runbook for AI failures (e.g., hallucination in customer-facing output)
6. **Documentation** — model cards, training-data provenance, decision logs
7. **Human oversight** — escalation paths, override mechanisms
8. **Vendor / third-party AI oversight** — DPAs, model cards from providers, contract clauses for AI use
9. **Bias audits** — annual for high-risk; on-demand otherwise
10. **Compliance updates** — quarterly regulatory horizon scan
## When to Hire an AI Counsel
| Stage | AI legal need |
|---|---|
| Pre-seed / seed | None (general counsel covers basics) |
| Series A | Outside AI counsel ad-hoc for high-risk use cases or EU launch |
| Series B | Fractional AI counsel ($10-20K/mo) if regulated industry or EU customers |
| Series C+ | Full-time AI counsel if regulated industry, government customers, or multi-jurisdiction AI |
**Signs you need AI counsel:**
- About to launch in EU with a high-risk use case
- Enterprise customer is asking for AI governance documentation
- Regulator inquiry received
- Building general-purpose AI model (foundation model)
- AI failure caused customer harm
## When This Reference Doesn't Help
- **Specific contract language for AI vendor agreements.** See `general-counsel-advisor/references/contracts_playbook.md`.
- **GDPR data subject rights for AI.** Overlaps; see GDPR Art. 22 specifically.
- **Tactical bias audit implementation.** See `engineering/self-eval/`.
- **Tactical AI safety techniques (red teaming, adversarial testing).** See `engineering/agent-designer/`.
This reference is about strategic risk classification and governance program design, not tactical implementation.
---
**Source authorities (non-exhaustive):**
- EU AI Act: Regulation (EU) 2024/1689 of the European Parliament and of the Council (12 July 2024)
- NIST AI RMF 1.0: "Artificial Intelligence Risk Management Framework" (January 2023) + AI RMF Playbook
- NYC Local Law 144 of 2021; 6 RCNY § 5-300
- Colorado AI Act, SB 21-169 and 2024 amendments; CRS § 6-1-1701
- Illinois HB 53 (820 ILCS 42/); BIPA (740 ILCS 14/); HB 3773 (2024)
- California SB 1001 (Business & Professions Code § 17940); AB 2013 (2024); CCPA/CPRA
- CFPB Circular 2023-03 (adverse action notices)
- Federal Reserve SR 11-7 (model risk management)
- FDA "Marketing Submission Recommendations for a Predetermined Change Control Plan for AI/ML-Enabled Device Software Functions" (2024)
- NAIC Model Bulletin on the Use of AI by Insurers (2023)
- EDPB Opinion 28/2024 on processing personal data in AI models
- White House Executive Order on Safe, Secure, and Trustworthy AI (EO 14110, 2023) — rescinded 2025; subsequent EOs vary
- "On the Dangers of Stochastic Parrots: Can Language Models Be Too Big? 🦜" Bender, Gebru, et al. (2021)
- "Constitutional AI: Harmlessness from AI Feedback" Bai et al., Anthropic (2022)
FILE:references/ai_team_org_evolution.md
# AI Team Org Evolution — The Decision: "What AI role do we hire next, and how is the AI team different from the data team?"
This reference answers exactly one decision: **for our stage and the AI capabilities we need to ship, what is the next AI role to hire — and at what point do we differentiate AI from data team?**
## The Wrong Question
> "Should we hire an ML engineer or a research scientist?"
This is the wrong question. Most ML engineers and research scientists hired by Series A startups are unable to deliver value because:
- The product hasn't validated which model behaviors matter
- There's no eval infrastructure to know if a change is good
- The "model" the founder imagines is actually an API call with better prompts
## The Right Question
> "What's the next AI capability the product needs to ship, and what role unblocks that?"
This shifts hiring from role-taxonomy to capability-shipping. AI org grows in response to specific capability gaps.
## The Five Stages
### Stage 1: Pre-PMF / Pre-seed / Seed
**Team size:** 1-15 people. **AI team:** 0 specialists.
**Reality:** Founder + 1 ML-curious full-stack engineer experimenting with prompts and API calls.
**Don't hire:** AI engineer, ML engineer, research scientist. They will have nothing to do because the capabilities aren't validated.
**Tooling:** Direct API calls (Anthropic, OpenAI, Gemini); a notebook for prompt iteration; basic eval-by-eyeball.
**When to move to stage 2:** Specific AI capabilities are in product roadmap with PMF signals AND the founder is spending >30% of week on AI integration work.
### Stage 2: Series A
**Team size:** 15-50 people. **AI team:** 1-2.
**First hire: AI engineer (NOT ML engineer, NOT research scientist).**
Profile:
- 3-5 years software engineering experience
- Strong applied AI/LLM skills (prompts, RAG, agents, evals)
- Comfortable with Python + TypeScript + APIs
- Has shipped at least one production AI feature
- NOT a researcher; NOT PhD-required
Why this hire first:
- Most early AI value is in **prompt engineering + RAG + eval discipline**, not novel models
- AI engineer owns the full stack: prompts, vector store, eval set, deployment, monitoring
- A pure ML engineer wants to deploy models that don't exist yet; a research scientist wants to invent models for problems that aren't validated
**Second hire: Second AI engineer focused on evals + quality.**
Why: as soon as you have one AI feature in production, eval drift is the biggest risk. Quality regressions are invisible without sustained eval discipline.
**Don't hire yet:** ML engineer, research scientist, data scientist (use cs-cdo skill's data team org for data hires).
**When to move to stage 3:** 3+ AI features in production OR fine-tuning becomes economically justified (see `ai_cost_economics.md`).
### Stage 3: Series B
**Team size:** 50-200. **AI team:** 3-7.
**Third hire: AI/ML platform engineer.**
Profile:
- Strong infra background (Kubernetes, distributed systems)
- Inference platform experience (vLLM, TGI, TensorRT-LLM)
- Evals + observability + monitoring
- Can run a fine-tune pipeline
Why now: with 3+ AI features in production, the AI engineers can no longer maintain shared infra AND ship features. Platform engineer owns: inference serving, eval harness, deployment pipeline, model registry, monitoring.
**Fourth hire: Third AI engineer (production reliability).**
Why: AI features in production accumulate maintenance burden. Bug fixes, edge cases, customer escalations. Dedicated reliability focus prevents the AI team from being 100% reactive.
**Conditional fifth hire: ML engineer (if fine-tuning is real).**
Hire only when:
- Decision A from `model_buildvsbuy_strategy.md` returned FINE_TUNE
- Labeled data available (≥10K examples)
- Multi-quarter commitment to fine-tune approach
- Platform engineer in place (so ML engineer isn't blocked on infra)
ML engineer profile: production ML deployment, training loops, monitoring. Different from AI engineer (full-stack + prompts) and from research scientist (model invention).
**Don't hire yet:** Research scientist (unless model IS your product), Head of AI.
**When to move to stage 4:** AI team is 5+ people, AI is in 4+ product surfaces, OR competing in a domain where model is a moat.
### Stage 4: Growth (Series C / pre-IPO)
**Team size:** 200-1000. **AI team:** 7-30.
**Sixth hire: Manager of AI Engineering.**
Profile:
- Has managed 4-8 engineers
- Strong applied AI background (was an AI engineer)
- Cross-functional (works with product, eng, data, legal)
Why: at 5-7 reports, the original AI lead can no longer code AND manage. Promote internally if possible.
**Seventh hire: ML research scientist (IF model is core IP).**
Triggers:
- You're competing in a model-quality lane (e.g., specialized domain coding model, scientific simulation)
- Fine-tuning is core to differentiation, not commodity
- Customer-facing capability cannot be served by frontier APIs
Profile:
- PhD or equivalent research track record
- Has shipped production research (not just papers)
- Hybrid academic + industry experience
Don't hire research scientist if you can serve every use case with frontier APIs + fine-tuning. Research is expensive ($400K+ TC at Series C+).
**Eighth hire: AI safety / red team engineer (IF customer-facing AI).**
Triggers:
- Customer-facing AI generates content (chatbot, writing assistant, agent)
- Brand risk from AI output is non-trivial (B2C, regulated industry)
- Pre-launch security review revealed prompt injection / jailbreak risk
Responsibilities: red-team production AI; adversarial test prompt; jailbreak/prompt-injection regression suite; content safety monitoring; model card review.
**Ninth hire: Head of AI / VP AI.**
Triggers:
- AI team is 10+ people
- AI strategy needs an executive who isn't the CTO
- Compliance / governance becomes board-level concern (EU AI Act, NIST AI RMF)
Profile: has run AI org at $50M+ ARR; technical depth + strategic clarity; business judgment; comfortable with board reporting.
**Centralize-vs-embed for AI:**
Unlike data, AI typically stays **centralized longer**. Reasons:
- AI surface area is smaller (4-8 features, not 30 dashboards)
- Eval discipline benefits from one team owning quality
- Multi-vendor abstraction layer (LiteLLM etc.) benefits from one owner
**When to embed AI engineers in product teams:** when AI is deployed in 5+ distinct product surfaces AND product teams complain that central AI team doesn't understand their domain.
**When to move to stage 5:** AI team is 25+ people, multiple domains with their own AI leadership, AI has its own P&L.
### Stage 5: Late-stage (Series D+, post-IPO)
**Team size:** 1000+. **AI team:** 30-200+.
**CAIO hire or promotion.**
Triggers:
- AI is in the company's strategic narrative (board deck, investor calls)
- AI has its own P&L (productized AI features, AI-driven monetization)
- Multiple regulatory regimes apply (EU AI Act conformity assessment, NIST AI RMF in federal contracts)
- Head of AI is escalating AI-strategy questions to CTO and it's not landing well
CAIO profile:
- Has run AI org at $100M+ ARR scale
- Comfortable with board reporting on AI strategy
- Strong on AI governance + safety + policy
- Strategic, not just technical
**Federated CAIO model (late-stage):**
At thousands-of-people scale, the CAIO often runs:
- Central platform team (inference, evals, model registry, governance)
- Central safety / red team
- Federated AI leaders embedded per business unit
- AI product leaders for productized AI features
## Role Definitions (founders confuse these)
| Role | Owns | Does NOT own |
|---|---|---|
| AI engineer (applied) | Prompts, RAG, agent design, evals, AI feature deployment | Inference infra, model invention |
| AI/ML platform engineer | Inference serving (vLLM/TGI), eval harness, model registry, monitoring | Prompts, agent design, model invention |
| ML engineer | Fine-tuning pipelines, model deployment, retraining | Model invention, prompts, agent design |
| Research scientist | Model invention, novel architectures, papers | Production deployment, ops |
| Data scientist | Statistical analysis, A/B tests, experimentation | Production deployment, model invention |
| AI safety / red team | Adversarial testing, jailbreak suite, content safety, model card review | Feature shipping |
| AI PM | AI roadmap, intake, prioritization, stakeholder mgmt | IC delivery |
| Head of AI | AI strategy, hiring, budget, exec representation | Day-to-day IC work |
| CAIO | AI + AI-policy strategy at board level, governance, P&L | Day-to-day execution |
## AI Team vs Data Team
**Key differences:**
| Aspect | AI team | Data team |
|---|---|---|
| Primary deliverable | Production AI features | Data products + analyses |
| First hire | AI engineer (applied) | Analyst |
| Tooling | Inference platform, eval harness, vector stores | Warehouse, dbt, BI |
| Output cadence | Feature releases | Dashboard releases, ad-hoc analyses |
| Centralize-vs-embed inflection | 5+ product surfaces (later) | 3+ functional teams (earlier) |
| Adjacent eng team | Product engineering | Analytics engineering |
| Eval discipline | High (model quality) | Medium (data quality) |
| External regulatory exposure | High (EU AI Act, NIST AI RMF) | Medium (GDPR, CCPA) |
**They should report to different leaders** at Series C+: CAIO owns AI; CDO owns data. Smaller companies can combine, but the skill sets are distinct.
## Anti-Patterns
- **Hiring research scientist as first AI hire.** Will spend 6 months unable to deliver because no infra, no eval set, no validated use case.
- **Hiring MLOps engineer before having models in production.** Premature; nothing to ops.
- **Hiring an "AI team" before product validation.** Many AI features fail PMF; over-hiring leads to layoffs.
- **Confusing AI engineer with ML engineer with research scientist.** Different jobs; founders waste budget on wrong title.
- **AI team separate from product team without strong eval discipline.** Silo failure mode: AI ships things product doesn't want.
- **Building a CAIO role before any AI in production.** Political role with no leverage.
- **Building a CAIO role without P&L.** Ceremonial; nothing to manage.
- **Hiring PhD with no business experience as CAIO.** Output is research-shaped, not business-shaped.
## Hiring Sequencing Rule
Never hire the next role until the previous role:
1. Is ramped (3-6 months in seat)
2. Has shipped at least one major capability
3. Identifies the specific gap the next hire will fill
**The discipline:** every AI hire ties to a specific capability the business can't ship without them.
## When This Reference Doesn't Help
- **Comp benchmarking.** See `c-level-advisor/skills/chro-advisor/scripts/comp_benchmarker.py`.
- **Leveling ladders.** See `c-level-advisor/skills/chro-advisor/references/leveling_ladders.md`.
- **JD templates.** Many open-source examples; not covered here.
- **Performance management.** Standard people management; not AI-specific.
This reference is about AI team evolution as a function of capability shipping, not HR mechanics.
---
**Source observations (non-exhaustive):**
- Chip Huyen, "Designing Machine Learning Systems" (O'Reilly, 2022) — operational distinction between AI engineer / ML engineer / research scientist
- "State of AI Report 2024" (Benaich + Hogarth) — industry hiring patterns
- "AI Engineering: Building Applications with Foundation Models" (Huyen, 2024) — the AI engineer discipline
- Direct observations from 40+ B2B SaaS AI team builds, 2023-2026
- Maxime Beauchemin — "The Rise of the Data Engineer" (2017) — parallel for distinguishing AI engineer from ML engineer
- A. Karpathy, public discussions on the "AI engineer" archetype vs ML researcher (2023-2025)
- "AI Engineer Pack" community (~50K members, 2024-2026) — emerging AI engineer career path documentation
- Anthropic, OpenAI engineering blog posts on internal team structure
FILE:references/model_buildvsbuy_strategy.md
# Model Build-vs-Buy — The Decision: "API, fine-tune, or build?"
This reference answers exactly one decision per use case: **should we call a frontier API, fine-tune a smaller model, or build from scratch?**
Pair with `scripts/model_buildvsbuy_calculator.py` for use-case-specific TCO.
## The Three Paths
### Path 1: Frontier API (default, 80% of use cases)
**What it is:** Call Claude, GPT, Gemini, or similar via API. Pay per token. No infrastructure.
**Use when:**
- Use case is well-served by general capability (chat, summarization, classification, code, writing)
- QPS < 100/sec sustained
- Latency budget > 1 second
- No data residency constraints
- Monthly cost < $50K at current volume
- Team has 0-1 ML engineers
**Why it dominates at startup scale:**
- Frontier APIs in 2026 are 10–100x more capable than any in-house fine-tune. Model cards show Claude 3.5 Sonnet, GPT-4o, and Gemini 2.5 outperform fine-tuned Llama 3.1 70B on most reasoning benchmarks by 20–40 points.
- Zero infrastructure overhead. No GPUs, no MLOps, no on-call.
- Pay-as-you-go scales linearly; no capacity planning.
- Vendor handles security patches, weight updates, alignment improvements.
**Failure modes:**
- **Vendor lock-in.** Mitigation: use abstraction layer (LiteLLM, OpenRouter, Portkey) so you can swap providers in days, not months.
- **Capability drift between versions.** Mitigation: pin model IDs; run regression evals before upgrading.
- **Rate limits at QPS spikes.** Mitigation: confirm Tier-4+ pricing with the provider; pre-arrange burst capacity.
- **Cost growth.** Below $50K/mo it's noise; above $200K/mo, revisit fine-tune. Above $1M/mo, revisit self-hosted.
- **Data residency.** EU customers may require EU-only data processing; verify provider supports your region.
**Anti-patterns:**
- "We need privacy, so we have to self-host." Almost always false at startup scale. Use enterprise contracts with zero-retention provisions instead.
- "Frontier APIs are too expensive." Run the math. Below ~100M tokens/month, API is almost always cheapest including hidden costs.
### Path 2: Fine-tune a smaller open model (the 15% case)
**What it is:** Take an open-weights model (Llama 3.1 70B, Qwen 2.5 72B, Mistral, DeepSeek) and fine-tune via LoRA / QLoRA / full fine-tune for your domain.
**Use when:**
- Domain-specific behavior the API can't be prompted into (medical coding patterns, legal redlining style, regulated terminology)
- Latency budget < 500ms sustained (frontier APIs typically p95 at 600-1500ms for non-trivial responses)
- High volume (>500M tokens/month) where TCO favors fine-tune
- Labeled data available (≥10K high-quality examples typical for LoRA)
- ML engineering capacity (≥2 engineers comfortable with HuggingFace, vLLM, fine-tuning loops)
**Fine-tuning approaches (from least to most invasive):**
| Approach | What it changes | When to use | Cost |
|---|---|---|---|
| Few-shot prompting | Nothing (in-context) | First attempt, always | $0 setup |
| Prompt engineering + system prompt | Nothing | When few-shot insufficient | $0 setup |
| RAG (retrieval-augmented) | Adds knowledge, not behavior | When you need facts, not style | $5-50K setup |
| LoRA fine-tuning | Adapter weights only | Behavior + style adjustments | $10-50K |
| Full fine-tuning | All weights | Major behavioral shift | $50-200K |
| RLHF / DPO | Alignment to preferences | Subjective quality (writing, support) | $100-500K |
| Continued pre-training | Domain knowledge baked in | Truly novel domain (medical, scientific) | $500K-5M |
**Failure modes:**
- **Quality lags frontier by ~6 months.** Frontier model improvements outpace your fine-tune cycle. Plan for refresh every 12-18 months.
- **Retraining cadence is a recurring engineering cost.** Quarterly retraining typical; budget 30% of one ML engineer.
- **Without an eval set, fine-tune drift is invisible.** You won't know quality degraded until a customer complains.
- **Inference is your problem now.** Fine-tuned models often run via hosted inference (Together, Fireworks, Replicate) for $0.50-2.00/M tokens; self-host adds operational complexity.
**Anti-patterns:**
- "Fine-tune to get better results." If frontier API is already at 90%+ accuracy, fine-tune to a smaller model usually drops it to 80-85%. The "better results" framing is backwards.
- "Fine-tune to save money." Only economically valid at high volume (>500M tokens/mo); below that, API wins even at frontier-premium pricing.
### Path 3: Build from scratch / pre-train (the <1% case)
**What it is:** Train a foundation model from scratch.
**Use when:** Almost never. Only:
- You are a foundation-model company (Anthropic, OpenAI, Cohere, Mistral, DeepSeek, etc.).
- You have a uniquely valuable corpus + $50M+ funding + 18-month patience.
- Your moat IS the model.
**Why it rarely makes sense:**
- Frontier models have caught up to specialized models in most domains within 18 months (medical, legal, code).
- By the time you ship, frontier capability has advanced 2 generations.
- Pre-training cost: $5M-50M+ depending on model size and data.
- Hidden cost: continued pre-training and alignment to keep up.
**Failure modes:**
- **Sunk cost trap.** Once you've spent $20M pre-training, sunk cost bias prevents switching to frontier APIs even when they're better.
- **Talent dependency.** Pre-training requires research scientists who can leave for $1M+ TC at frontier labs.
- **Compute access.** H100 / B200 supply remains constrained; access depends on hyperscaler relationships.
## Decision Tree (use the calculator for the full version)
1. **Is this well-served by frontier capability?** (YES → API, unless...)
2. **Do you have data residency / sovereignty constraints?** (YES → fine-tune self-hosted)
3. **Do you have domain-specific behavior the API can't be prompted into?** (YES + labeled data + team → fine-tune)
4. **Latency budget < 500ms?** (YES → fine-tune at high volume; API + streaming may suffice at lower volume)
5. **Volume > 500M tokens/month + multi-year stable workload?** (YES → run breakeven, consider fine-tune)
6. **All above NO + need maximum capability?** → API frontier-premium tier
## The Eval-First Discipline
**Rule:** Don't pick a path without an eval set. Without measurement, all three paths look the same.
Minimum eval set:
- 50-100 representative inputs covering your use case
- Expected outputs OR rubric for human grading
- Edge cases: ambiguous inputs, adversarial inputs, format edge cases
- Run on every path you consider; the scores determine the decision
Tools: `engineering/self-eval/`, `promptfoo`, `Inspect-AI`, internal eval harnesses.
## When This Reference Doesn't Help
- **RAG architecture choices.** See `engineering/rag-architect/`.
- **Agent design patterns.** See `engineering/agent-designer/`.
- **Prompt engineering technique.** See `engineering/prompt-governance/`.
- **Eval harness implementation.** See `engineering/self-eval/`.
- **Inference cost optimization tactics.** See `engineering/llm-cost-optimizer/`.
This reference is about the strategic choice between API / fine-tune / build, not how to implement any of them.
---
**Source authorities (non-exhaustive):**
- Anthropic, "Model Cards for Claude 3.5 Sonnet, Claude 4 family" — published model performance and capability disclosures
- OpenAI, "GPT-4 Technical Report" (arXiv:2303.08774, 2023) and subsequent model spec releases
- Google DeepMind, "Gemini: A Family of Highly Capable Multimodal Models" (2023, updated 2024-2026)
- Meta AI, "Llama 3.1: Open Foundation and Instruction Models" (2024)
- Hu et al., "LoRA: Low-Rank Adaptation of Large Language Models" (arXiv:2106.09685, 2021)
- Ouyang et al., "Training Language Models to Follow Instructions with Human Feedback" (RLHF, 2022)
- Rafailov et al., "Direct Preference Optimization: Your Language Model is Secretly a Reward Model" (DPO, 2023)
- Stanford CRFM, "On the Opportunities and Risks of Foundation Models" (2021)
- Henderson et al., "Foundation Models and Fair Use" (2023)
FILE:scripts/ai_cost_economics.py
#!/usr/bin/env python3
"""ai_cost_economics.py — API vs self-hosted inference breakeven analysis.
Stdlib-only. Takes a workload profile and outputs:
- Monthly API cost at three tiers (frontier-premium, frontier-economy, open-hosted)
- Monthly self-hosted cost (GPU rental + ops, at chosen model size)
- Breakeven point: where API and self-hosted cross
- Sensitivity: low/mid/high GPU rate scenarios
- Recommended path with explicit caveats
Deterministic logic derived from the profile.
Input schema (JSON):
{
"workload_name": "Customer support generation",
"monthly_input_tokens_m": 600, # millions of input tokens per month
"monthly_output_tokens_m": 150,
"quality_tier_required": "frontier-economy", # frontier-premium | frontier-economy | open-hosted
"model_size_class_self_host": "70b-class", # 7b-13b | 70b-class
"latency_p95_target_ms": 1500,
"utilization_assumed_pct": 70, # realistic GPU utilization for self-hosting
"include_ops_attribution": true # 30% of an engineer attributed to self-hosted ops
}
Usage:
python ai_cost_economics.py # uses embedded 5M tokens/day sample
python ai_cost_economics.py path/to/workload.json
python ai_cost_economics.py workload.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"workload_name": "B2B SaaS customer-support generation (5M tokens/day)",
"monthly_input_tokens_m": 600,
"monthly_output_tokens_m": 150,
"quality_tier_required": "frontier-economy",
"model_size_class_self_host": "70b-class",
"latency_p95_target_ms": 1500,
"utilization_assumed_pct": 70,
"include_ops_attribution": True,
}
# 2026 API pricing per million tokens, $USD (input / output)
API_PRICING = {
"frontier-premium": {"input": 3.00, "output": 15.00, "label": "Claude Sonnet 4.6 / GPT-4o-tier"},
"frontier-economy": {"input": 1.25, "output": 5.00, "label": "Gemini 2.5 Flash / Claude Haiku 4.5-tier"},
"open-hosted": {"input": 0.50, "output": 1.50, "label": "Llama 3.1 70B / Qwen 2.5 72B via hosted endpoint"},
}
# GPU spot pricing 2026 ($/hour). Mid-range; varies by provider and commitment.
GPU_PRICING = {
"A100-spot-low": 1.50,
"A100-spot-mid": 2.50,
"A100-spot-high": 3.50,
"H100-spot-low": 3.50,
"H100-spot-mid": 5.00,
"H100-spot-high": 8.00,
}
# Tokens per second per GPU at 70% utilization (rough)
TOKENS_PER_GPU_PER_SEC = {
"7b-13b": {"A100": 1500, "H100": 3500},
"70b-class": {"A100": 200, "H100": 600},
}
# Number of GPUs needed for model (minimum, with KV cache)
GPUS_PER_MODEL = {
"7b-13b": 1,
"70b-class": 4, # 70B at FP16 needs ~140GB; 4xA100-40GB or 2xH100-80GB
}
# Engineer fully-loaded cost (annual)
ENGINEER_FULLY_LOADED = 250_000
OPS_ATTRIBUTION_PCT = 0.30 # 30% of an engineer attributed to self-hosted ops
def api_monthly_cost(profile: Dict[str, Any], tier: str) -> float:
pricing = API_PRICING.get(tier, API_PRICING["frontier-economy"])
return (
profile.get("monthly_input_tokens_m", 0) * pricing["input"]
+ profile.get("monthly_output_tokens_m", 0) * pricing["output"]
)
def self_hosted_monthly_cost(profile: Dict[str, Any], gpu_type: str, gpu_pricing_tier: str) -> Dict[str, Any]:
"""Compute self-hosted monthly cost for given GPU type and pricing tier."""
model_class = profile.get("model_size_class_self_host", "70b-class")
utilization = profile.get("utilization_assumed_pct", 70) / 100
monthly_tokens_total_m = profile.get("monthly_input_tokens_m", 0) + profile.get("monthly_output_tokens_m", 0)
monthly_tokens_total = monthly_tokens_total_m * 1_000_000
gpus_needed = GPUS_PER_MODEL[model_class]
tokens_per_sec_per_gpu = TOKENS_PER_GPU_PER_SEC[model_class][gpu_type]
effective_tokens_per_sec = gpus_needed * tokens_per_sec_per_gpu * utilization
# Hours of GPU time needed per month
seconds_per_month = monthly_tokens_total / effective_tokens_per_sec
hours_per_month = seconds_per_month / 3600
# But minimum: GPUs must be warm 24/7 if we want consistent latency
# So actual hours = max(hours_per_month, 24 * 30 * gpus_needed)
hours_warm = 24 * 30 * gpus_needed
hours_billable = max(hours_per_month, hours_warm)
gpu_pricing_key = f"{gpu_type}-spot-{gpu_pricing_tier}"
rate = GPU_PRICING[gpu_pricing_key]
gpu_cost = hours_billable * rate / gpus_needed * gpus_needed # already per GPU
ops_cost = (ENGINEER_FULLY_LOADED * OPS_ATTRIBUTION_PCT) / 12 if profile.get("include_ops_attribution", True) else 0
return {
"gpu_cost": round(gpu_cost, 0),
"ops_cost": round(ops_cost, 0),
"total": round(gpu_cost + ops_cost, 0),
"hours_warm_required": int(hours_warm),
"hours_compute_required": int(hours_per_month),
"gpus_needed": gpus_needed,
"gpu_rate_per_hr": rate,
}
def find_breakeven(profile: Dict[str, Any], api_tier: str, gpu_type: str, gpu_pricing_tier: str) -> Dict[str, Any]:
"""Find the monthly token volume where API and self-hosted cost cross."""
# API cost is linear in tokens; self-hosted has fixed (warm GPU) + linear component
model_class = profile.get("model_size_class_self_host", "70b-class")
utilization = profile.get("utilization_assumed_pct", 70) / 100
gpus_needed = GPUS_PER_MODEL[model_class]
tokens_per_sec_per_gpu = TOKENS_PER_GPU_PER_SEC[model_class][gpu_type]
effective_tokens_per_sec = gpus_needed * tokens_per_sec_per_gpu * utilization
gpu_pricing_key = f"{gpu_type}-spot-{gpu_pricing_tier}"
rate = GPU_PRICING[gpu_pricing_key]
# Self-hosted: warm 24/7 fixed cost, plus ops
monthly_fixed = 24 * 30 * gpus_needed * rate
ops_cost = (ENGINEER_FULLY_LOADED * OPS_ATTRIBUTION_PCT) / 12 if profile.get("include_ops_attribution", True) else 0
self_hosted_floor = monthly_fixed + ops_cost # cost even at zero tokens (because warm)
# When tokens exceed warm capacity, additional cost is more GPU hours
# But up to warm capacity, total cost is just monthly_fixed + ops_cost
warm_capacity_tokens_per_month = effective_tokens_per_sec * 24 * 30 * 3600
# API cost per million tokens (weighted by I/O ratio)
monthly_in = profile.get("monthly_input_tokens_m", 1)
monthly_out = profile.get("monthly_output_tokens_m", 1)
total_m = monthly_in + monthly_out
in_ratio = monthly_in / total_m if total_m else 0.8
out_ratio = monthly_out / total_m if total_m else 0.2
api_per_m = API_PRICING[api_tier]["input"] * in_ratio + API_PRICING[api_tier]["output"] * out_ratio
# Breakeven: api_per_m * tokens_m = self_hosted_floor
if api_per_m > 0:
breakeven_tokens_m = self_hosted_floor / api_per_m
else:
breakeven_tokens_m = None
return {
"breakeven_monthly_tokens_m": round(breakeven_tokens_m, 0) if breakeven_tokens_m else None,
"self_hosted_floor_monthly": round(self_hosted_floor, 0),
"warm_capacity_monthly_tokens_m": round(warm_capacity_tokens_per_month / 1_000_000, 0),
"api_per_m_blended": round(api_per_m, 2),
}
def analyze(profile: Dict[str, Any]) -> Dict[str, Any]:
api_tier = profile.get("quality_tier_required", "frontier-economy")
monthly_tokens_total_m = profile.get("monthly_input_tokens_m", 0) + profile.get("monthly_output_tokens_m", 0)
# API costs at all 3 tiers
api_costs = {tier: round(api_monthly_cost(profile, tier), 0) for tier in API_PRICING}
# Self-hosted at chosen GPU type, 3 pricing tiers
gpu_type = "A100" if profile.get("latency_p95_target_ms", 2000) > 1000 else "H100"
self_hosted_low = self_hosted_monthly_cost(profile, gpu_type, "low")
self_hosted_mid = self_hosted_monthly_cost(profile, gpu_type, "mid")
self_hosted_high = self_hosted_monthly_cost(profile, gpu_type, "high")
# Breakeven analysis at mid pricing
breakeven = find_breakeven(profile, api_tier, gpu_type, "mid")
# Recommendation
api_chosen_cost = api_costs[api_tier]
self_hosted_chosen_cost = self_hosted_mid["total"]
if monthly_tokens_total_m < breakeven["breakeven_monthly_tokens_m"]:
rec = "API"
reasoning = (
f"Current volume ({monthly_tokens_total_m:.0f}M tokens/mo) is BELOW breakeven "
f"({breakeven['breakeven_monthly_tokens_m']:.0f}M tokens/mo). API tier '{api_tier}' is cheaper "
f"({_fmt_money(api_chosen_cost)}/mo) than self-hosted "
f"({_fmt_money(self_hosted_chosen_cost)}/mo at mid GPU rates)."
)
caveats = [
"API costs scale linearly with token volume; revisit when volume doubles",
"Build multi-vendor abstraction (LiteLLM / OpenRouter) for failover",
"Pin model IDs; run regression evals on every model upgrade",
]
elif self_hosted_high["total"] < api_chosen_cost:
rec = "SELF_HOSTED"
reasoning = (
f"Current volume ({monthly_tokens_total_m:.0f}M tokens/mo) is well above breakeven. "
f"Self-hosted at {_fmt_money(self_hosted_chosen_cost)}/mo (mid GPU rates) is cheaper than API "
f"at {_fmt_money(api_chosen_cost)}/mo across all GPU pricing scenarios."
)
caveats = [
"Quality lags frontier by ~6 months; budget refresh cycle",
"24/7 on-call required; 30% engineer attribution may underestimate at scale",
"GPU spot pricing volatile; negotiate reserved capacity at this scale",
"Eval discipline non-negotiable for self-hosted; without it you cannot detect quality degradation",
]
else:
rec = "HYBRID"
reasoning = (
f"Current volume ({monthly_tokens_total_m:.0f}M tokens/mo) is above breakeven but self-hosted "
f"cost ({_fmt_money(self_hosted_chosen_cost)}/mo) is close to API ({_fmt_money(api_chosen_cost)}/mo). "
"Consider hybrid: API for tail / low-volume use cases, self-hosted for high-volume / latency-sensitive paths."
)
caveats = [
"Migration to self-hosted typically takes 3-6 months of engineering time — model in TCO",
"Hybrid increases operational complexity; ensure routing logic is testable",
"At this margin, capability differences between API and 70B-class may matter more than cost",
]
return {
"recommendation": rec,
"reasoning": reasoning,
"caveats": caveats,
"monthly_costs": {
"api_frontier_premium": api_costs["frontier-premium"],
"api_frontier_economy": api_costs["frontier-economy"],
"api_open_hosted": api_costs["open-hosted"],
"self_hosted_low_gpu_rate": self_hosted_low,
"self_hosted_mid_gpu_rate": self_hosted_mid,
"self_hosted_high_gpu_rate": self_hosted_high,
},
"breakeven_analysis": breakeven,
"gpu_type_recommended": gpu_type,
"current_monthly_tokens_m": monthly_tokens_total_m,
}
def render_text(result: Dict[str, Any], profile: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("AI COST ECONOMICS — API vs SELF-HOSTED")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Workload: {profile.get('workload_name')}")
lines.append(f" Volume: {profile.get('monthly_input_tokens_m')}M input + {profile.get('monthly_output_tokens_m')}M output tokens/mo")
lines.append(f" Quality tier required: {profile.get('quality_tier_required')}")
lines.append(f" Model size for self-host: {profile.get('model_size_class_self_host')}")
lines.append(f" Latency p95 target: {profile.get('latency_p95_target_ms')}ms")
lines.append(f" Utilization assumed: {profile.get('utilization_assumed_pct')}%")
lines.append("")
lines.append("-" * 72)
lines.append(f"RECOMMENDATION: {result['recommendation']}")
lines.append("")
for line in _wrap(result["reasoning"], 2):
lines.append(line)
lines.append("")
lines.append("Caveats:")
for c in result["caveats"]:
lines.append(f" • {c}")
lines.append("")
lines.append("-" * 72)
lines.append("MONTHLY COST COMPARISON:")
lines.append("")
mc = result["monthly_costs"]
lines.append(f" API frontier-premium: {_fmt_money(mc['api_frontier_premium']):>15} ({API_PRICING['frontier-premium']['label']})")
lines.append(f" API frontier-economy: {_fmt_money(mc['api_frontier_economy']):>15} ({API_PRICING['frontier-economy']['label']})")
lines.append(f" API open-hosted: {_fmt_money(mc['api_open_hosted']):>15} ({API_PRICING['open-hosted']['label']})")
lines.append("")
lines.append(f" Self-hosted ({result['gpu_type_recommended']}), low GPU rates: {_fmt_money(mc['self_hosted_low_gpu_rate']['total']):>15} (GPU @ mc['self_hosted_low_gpu_rate']['gpu_rate_per_hr']/hr × {mc['self_hosted_low_gpu_rate']['gpus_needed']} GPUs)")
lines.append(f" Self-hosted ({result['gpu_type_recommended']}), mid GPU rates: {_fmt_money(mc['self_hosted_mid_gpu_rate']['total']):>15} (GPU @ mc['self_hosted_mid_gpu_rate']['gpu_rate_per_hr']/hr × {mc['self_hosted_mid_gpu_rate']['gpus_needed']} GPUs)")
lines.append(f" Self-hosted ({result['gpu_type_recommended']}), high GPU rates: {_fmt_money(mc['self_hosted_high_gpu_rate']['total']):>15} (GPU @ mc['self_hosted_high_gpu_rate']['gpu_rate_per_hr']/hr × {mc['self_hosted_high_gpu_rate']['gpus_needed']} GPUs)")
lines.append("")
lines.append(f" Self-hosted ops attribution: {_fmt_money(mc['self_hosted_mid_gpu_rate']['ops_cost'])}/mo (30% of one engineer)")
lines.append("")
lines.append("-" * 72)
be = result["breakeven_analysis"]
lines.append("BREAKEVEN ANALYSIS:")
lines.append("")
if be["breakeven_monthly_tokens_m"]:
lines.append(f" API '{profile.get('quality_tier_required')}' vs self-hosted at mid GPU rates:")
lines.append(f" Breakeven: ~{be['breakeven_monthly_tokens_m']:,.0f}M tokens/month")
lines.append(f" Current volume: {result['current_monthly_tokens_m']:,.0f}M tokens/month")
lines.append(f" Self-hosted floor (warm GPUs + ops, even at zero tokens): {_fmt_money(be['self_hosted_floor_monthly'])}/mo")
lines.append(f" Self-hosted warm capacity ceiling: ~{be['warm_capacity_monthly_tokens_m']:,.0f}M tokens/month")
lines.append(f" API blended cost: be['api_per_m_blended']/M tokens")
lines.append("")
lines.append("-" * 72)
lines.append("REMINDER: This analysis uses 2026 pricing. Pricing changes; re-run quarterly.")
lines.append("Migration to self-hosted is 3-6 months of engineering work — model that in your TCO.")
return "\n".join(lines)
def _fmt_money(amount: float) -> str:
return f",.0f"
def _wrap(text: str, indent: int, width: int = 70) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="API vs self-hosted inference breakeven + sensitivity analysis.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to workload JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: 5M tokens/day customer support workload>"
result = analyze(profile)
if args.output == "json":
print(json.dumps({"source": source, "profile": profile, **result}, indent=2))
else:
print(render_text(result, profile, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/ai_risk_classifier.py
#!/usr/bin/env python3
"""ai_risk_classifier.py — Classify an AI use case under EU AI Act + US state laws.
Stdlib-only. Takes a use case profile and outputs:
- Risk tier (PROHIBITED / HIGH / LIMITED / MINIMAL) under EU AI Act
- US state law triggers (NYC LL 144, CO SB 21-169 successor, IL HB 53, CA SB 1001)
- Industry-specific overlays (FDA, NYDFS, NAIC)
- Required controls + conformity assessment trigger
- Citations to specific articles / regulations
NOT legal advice — surfaces classification for qualified AI counsel.
Input schema (JSON):
{
"use_case": "AI screening of job applications",
"domain": "employment", # employment | credit | education | healthcare | critical-infra |
# law-enforcement | biometric | content-moderation | b2b-general |
# consumer-general
"deploys_in_eu": true,
"deploys_in_us_states": ["NY", "CO", "IL", "CA"],
"decisions_affected": "consequential", # consequential | informational | internal-only
"automation_level": "automated", # automated | human-in-loop | advisory
"user_facing": true,
"biometric_data_processed": false,
"children_under_16": false
}
Usage:
python ai_risk_classifier.py # uses embedded hiring-AI sample
python ai_risk_classifier.py path/to/use_case.json
python ai_risk_classifier.py use_case.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"use_case": "AI-assisted screening of job applications (resume ranking)",
"domain": "employment",
"deploys_in_eu": True,
"deploys_in_us_states": ["NY", "CO", "IL", "CA"],
"decisions_affected": "consequential",
"automation_level": "automated",
"user_facing": False,
"biometric_data_processed": False,
"children_under_16": False,
}
# EU AI Act Annex III "high-risk" domains (Article 6(2))
HIGH_RISK_DOMAINS = {
"employment",
"credit",
"education",
"critical-infra",
"law-enforcement",
"biometric",
"migration",
"justice",
"essential-services", # insurance, public benefits
}
# EU AI Act Article 5 prohibited practices
PROHIBITED_TRIGGERS = {
"social-scoring",
"real-time-biometric-surveillance",
"subliminal-manipulation",
"exploitation-of-vulnerability",
"predictive-policing-from-profiling",
"emotion-recognition-workplace-or-education",
"biometric-categorization-by-protected-traits",
}
def classify_eu(profile: Dict[str, Any]) -> Dict[str, Any]:
"""Return EU AI Act classification + reasoning."""
deploys_eu = profile.get("deploys_in_eu", False)
if not deploys_eu:
return {
"tier": "NOT_APPLICABLE",
"reasoning": "Does not deploy in EU. EU AI Act not triggered.",
"obligations": [],
"citations": [],
}
domain = profile.get("domain", "")
decisions = profile.get("decisions_affected", "informational")
biometric = profile.get("biometric_data_processed", False)
automation = profile.get("automation_level", "advisory")
use_case = profile.get("use_case", "").lower()
# Article 5 prohibited check (heuristic match)
for prohibited in PROHIBITED_TRIGGERS:
if any(kw in use_case for kw in prohibited.split("-")):
# Conservative: match only if multiple keywords hit
keywords = prohibited.split("-")
hits = sum(1 for kw in keywords if kw in use_case)
if hits >= 2:
return {
"tier": "PROHIBITED",
"reasoning": (
f"Use case description appears to match Article 5 prohibited practice ({prohibited}). "
"Cannot deploy in EU regardless of safeguards. Re-scope the product or exclude EU market."
),
"obligations": ["Cease deployment in EU"],
"citations": ["EU AI Act Art. 5"],
}
# Special prohibited: biometric in public spaces by law enforcement (real-time)
if biometric and domain == "law-enforcement" and automation == "automated":
return {
"tier": "PROHIBITED",
"reasoning": (
"Real-time biometric identification by law enforcement in publicly accessible spaces is "
"Art. 5(1)(h) prohibited (narrow exceptions for serious crimes only)."
),
"obligations": ["Cease deployment unless narrow exception applies, in which case Annex III high-risk obligations also apply"],
"citations": ["EU AI Act Art. 5(1)(h)"],
}
# High-risk Annex III check
if domain in HIGH_RISK_DOMAINS and decisions == "consequential":
return {
"tier": "HIGH",
"reasoning": (
f"Annex III high-risk domain ({domain}) with consequential decisions. "
"Conformity assessment + registration + post-market monitoring required before deployment."
),
"obligations": [
"Conformity assessment (Art. 43)",
"Registration in EU AI database (Art. 49)",
"Risk management system (Art. 9)",
"Data governance: representative, accurate, complete training data (Art. 10)",
"Technical documentation maintained throughout lifecycle (Art. 11)",
"Logging / record-keeping (Art. 12)",
"Transparency and instructions for use (Art. 13)",
"Human oversight (Art. 14)",
"Accuracy, robustness, cybersecurity (Art. 15)",
"Post-market monitoring + incident reporting (Art. 72)",
],
"citations": ["EU AI Act Art. 6", "Annex III", "Art. 8-15", "Art. 43", "Art. 49", "Art. 72"],
}
# Biometric data: special category — usually high-risk
if biometric:
return {
"tier": "HIGH",
"reasoning": (
"Biometric data processing triggers Annex III obligations even outside the listed domains "
"(special category under GDPR Art. 9 + AI Act overlay)."
),
"obligations": [
"Conformity assessment + Annex III high-risk obligations",
"GDPR Art. 9(2) explicit consent or other Art. 9 lawful basis",
"DPIA mandatory (GDPR Art. 35)",
],
"citations": ["EU AI Act Annex III §1", "GDPR Art. 9", "GDPR Art. 35"],
}
# Limited risk: chatbots, deepfakes, emotion recognition (outside workplace/edu), generative AI
if "chatbot" in use_case or "deepfake" in use_case or "image generation" in use_case or "video generation" in use_case:
return {
"tier": "LIMITED",
"reasoning": (
"Limited risk: transparency obligations apply — users must be informed they are interacting with AI "
"or that content is AI-generated."
),
"obligations": [
"Inform users they are interacting with AI (Art. 50(1))",
"Mark AI-generated / manipulated content (Art. 50(2))",
"If general-purpose AI model: model card with capabilities, limitations, training-data summary (Art. 53)",
],
"citations": ["EU AI Act Art. 50", "Art. 53"],
}
# Minimal risk default
return {
"tier": "MINIMAL",
"reasoning": (
"Does not fall under prohibited, Annex III high-risk, or limited-risk categories. "
"No specific AI Act obligations beyond general product safety; voluntary codes of conduct recommended."
),
"obligations": [
"Voluntary alignment with NIST AI RMF / EU codes of conduct (recommended)",
"GDPR obligations still apply if personal data is processed",
],
"citations": ["EU AI Act recital 27", "NIST AI RMF 1.0"],
}
def us_state_triggers(profile: Dict[str, Any]) -> List[Dict[str, str]]:
"""Return list of triggered US state-level obligations."""
states = set(s.upper() for s in profile.get("deploys_in_us_states", []))
domain = profile.get("domain", "")
user_facing = profile.get("user_facing", False)
triggers = []
# NYC LL 144 — AEDTs in employment
if "NY" in states and domain == "employment":
triggers.append({
"law": "NYC Local Law 144 (AEDT)",
"trigger": "Automated Employment Decision Tool used in hiring or promotion for NYC employees",
"obligations": (
"Annual independent bias audit; candidate notice (10+ business days before use); "
"publication of audit summary on company website."
),
"citation": "NYC Local Law 144 of 2021; 6 RCNY § 5-300",
})
# Colorado AI Act / SB 21-169 successor
if "CO" in states and domain in {"employment", "credit", "education", "insurance", "essential-services"}:
triggers.append({
"law": "Colorado AI Act (SB 21-169 / 2024 amendments)",
"trigger": f"High-risk AI system in consumer decisions ({domain})",
"obligations": (
"Reasonable care to protect from algorithmic discrimination; impact assessment; "
"consumer notice; right to opt-out of profiling; risk management policy."
),
"citation": "Colorado SB 21-169 (as amended)",
})
# Illinois HB 53 — AI in employment interviews
if "IL" in states and domain == "employment":
triggers.append({
"law": "Illinois HB 53 (AI Video Interview Act)",
"trigger": "AI analyzes video interviews of Illinois applicants",
"obligations": (
"Candidate notice + consent before recording; explanation of how AI is used; "
"deletion within 30 days of request; restrictions on sharing data."
),
"citation": "Illinois 820 ILCS 42/",
})
# California SB 1001 — Bot disclosure
if "CA" in states and user_facing:
triggers.append({
"law": "California SB 1001 (B.O.T. Act)",
"trigger": "User-facing AI bot in commercial transactions or California elections",
"obligations": "Disclose to user that they are interacting with a bot (not a human).",
"citation": "California Business & Professions Code § 17940",
})
# Illinois BIPA — biometric data
if "IL" in states and profile.get("biometric_data_processed", False):
triggers.append({
"law": "Illinois Biometric Information Privacy Act (BIPA)",
"trigger": "Biometric identifier or biometric information capture",
"obligations": (
"Written informed consent; published retention/destruction policy; cannot sell biometric data; "
"private right of action with statutory damages ($1K-$5K per violation)."
),
"citation": "Illinois 740 ILCS 14/",
})
return triggers
def industry_overlays(profile: Dict[str, Any]) -> List[Dict[str, str]]:
"""Return industry-specific regulatory overlays."""
domain = profile.get("domain", "")
overlays = []
if domain == "healthcare":
overlays.append({
"framework": "FDA AI/ML guidance + Software as Medical Device (SaMD)",
"trigger": "AI in clinical decisions, diagnostic, or therapeutic use",
"obligations": (
"510(k) or De Novo or PMA pathway depending on risk class; Predetermined Change Control Plan "
"for adaptive models; Good Machine Learning Practices (GMLP)."
),
"citation": "FDA Guidance on AI/ML SaMD (2023); 21 CFR Part 820",
})
elif domain == "credit":
overlays.append({
"framework": "ECOA + FCRA + CFPB Circular 2023-03",
"trigger": "AI used in credit underwriting or adverse action",
"obligations": (
"Specific reason for adverse action (not 'algorithm said no'); model risk management "
"consistent with SR 11-7 if a bank; explainability sufficient for FCRA adverse action notice."
),
"citation": "15 USC §1691 (ECOA); CFPB Circular 2023-03; Fed SR 11-7",
})
elif domain == "essential-services":
overlays.append({
"framework": "NAIC Model Bulletin on AI in Insurance",
"trigger": "AI in insurance underwriting, pricing, claims, fraud",
"obligations": (
"AI program governance, risk management, third-party AI oversight; "
"documented testing for unfair discrimination."
),
"citation": "NAIC Model Bulletin on the Use of AI by Insurers (2023)",
})
return overlays
def required_controls(profile: Dict[str, Any], eu_classification: Dict[str, Any]) -> List[str]:
"""Return the required-controls checklist based on tier + profile."""
tier = eu_classification.get("tier", "")
controls = []
if tier in ("HIGH", "LIMITED", "MINIMAL"):
controls.extend([
"Eval set with documented success criteria before deployment",
"Monitoring of model output in production (drift, bias, hallucination)",
"Fallback behavior defined for model failure modes",
"Human-in-loop review for high-stakes outputs",
])
if tier == "HIGH":
controls.extend([
"Conformity assessment completed and documented (EU AI Act Art. 43)",
"Registration in EU AI database before deployment (Art. 49)",
"Risk management system documented and maintained (Art. 9)",
"Training data governance: representativeness, accuracy, bias mitigation (Art. 10)",
"Technical documentation per Annex IV maintained throughout lifecycle (Art. 11)",
"Comprehensive logging for traceability (Art. 12)",
"Human oversight design (e.g., stop button, override capability) (Art. 14)",
"Post-market monitoring plan + serious incident reporting (Art. 72)",
"DPIA under GDPR Art. 35 if personal data processed",
])
if tier == "LIMITED":
controls.extend([
"User notification: 'You are interacting with AI' or 'This content is AI-generated'",
"If general-purpose model: publish model card per Art. 53",
])
if profile.get("user_facing"):
controls.append("Public-facing disclosure of AI usage in customer-facing communications")
if profile.get("automation_level") == "automated" and profile.get("decisions_affected") == "consequential":
controls.append("Right-to-explanation / contestation mechanism for affected individuals (GDPR Art. 22)")
return controls
def analyze(profile: Dict[str, Any]) -> Dict[str, Any]:
eu = classify_eu(profile)
us = us_state_triggers(profile)
overlays = industry_overlays(profile)
controls = required_controls(profile, eu)
conformity_required = eu.get("tier") == "HIGH"
return {
"eu_classification": eu,
"us_state_triggers": us,
"industry_overlays": overlays,
"required_controls": controls,
"conformity_assessment_required": conformity_required,
}
def render_text(result: Dict[str, Any], profile: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("AI RISK CLASSIFICATION")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Use case: {profile.get('use_case')}")
lines.append(f" Domain: {profile.get('domain')} | Automation: {profile.get('automation_level')} | Decisions: {profile.get('decisions_affected')}")
lines.append(f" Deploys in EU: {profile.get('deploys_in_eu')} | US states: {', '.join(profile.get('deploys_in_us_states', []))}")
lines.append(f" User-facing: {profile.get('user_facing')} | Biometric: {profile.get('biometric_data_processed')}")
lines.append("")
lines.append("-" * 72)
eu = result["eu_classification"]
tier_marker = {
"PROHIBITED": "🔴",
"HIGH": "🟠",
"LIMITED": "🟡",
"MINIMAL": "🟢",
"NOT_APPLICABLE": "⚪",
}.get(eu["tier"], "•")
lines.append(f"EU AI ACT TIER: {tier_marker} {eu['tier']}")
lines.append("")
for line in _wrap(eu["reasoning"], 2):
lines.append(line)
lines.append("")
if eu["citations"]:
lines.append(f" Citations: {', '.join(eu['citations'])}")
lines.append("")
if eu["obligations"]:
lines.append(" EU obligations:")
for o in eu["obligations"]:
lines.append(f" • {o}")
lines.append("")
lines.append("-" * 72)
lines.append(f"CONFORMITY ASSESSMENT REQUIRED: {'YES' if result['conformity_assessment_required'] else 'no'}")
lines.append("")
lines.append("-" * 72)
us = result["us_state_triggers"]
if us:
lines.append(f"US STATE LAW TRIGGERS ({len(us)}):")
lines.append("")
for t in us:
lines.append(f" • {t['law']}")
lines.append(f" Trigger: {t['trigger']}")
for line in _wrap(t["obligations"], 4):
lines.append(line)
lines.append(f" Citation: {t['citation']}")
lines.append("")
else:
lines.append("US STATE LAW TRIGGERS: none for the listed states + domain.")
lines.append("")
lines.append("-" * 72)
overlays = result["industry_overlays"]
if overlays:
lines.append(f"INDUSTRY OVERLAYS ({len(overlays)}):")
lines.append("")
for o in overlays:
lines.append(f" • {o['framework']}")
lines.append(f" Trigger: {o['trigger']}")
for line in _wrap(o["obligations"], 4):
lines.append(line)
lines.append(f" Citation: {o['citation']}")
lines.append("")
lines.append("-" * 72)
lines.append(f"REQUIRED CONTROLS ({len(result['required_controls'])}):")
for c in result["required_controls"]:
lines.append(f" ☐ {c}")
lines.append("")
lines.append("-" * 72)
lines.append("REMINDER: This is triage, not legal advice. EU AI Act conformity assessment requires qualified")
lines.append("AI counsel and may require Notified Body involvement. Re-run quarterly as regulations evolve.")
return "\n".join(lines)
def _wrap(text: str, indent: int, width: int = 70) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="Classify an AI use case under EU AI Act + US state laws.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to use_case JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: AI hiring screening, EU + NY/CO/IL/CA>"
result = analyze(profile)
if args.output == "json":
print(json.dumps({"source": source, "profile": profile, **result}, indent=2))
else:
print(render_text(result, profile, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/model_buildvsbuy_calculator.py
#!/usr/bin/env python3
"""model_buildvsbuy_calculator.py — Decide API vs fine-tune vs build for a use case.
Stdlib-only. Takes a use case profile and outputs:
- Recommendation (API / FINE_TUNE / BUILD) with reasoning
- 3-year TCO comparison across all 3 paths
- Breakeven analysis (where API stops being cheapest)
- Failure modes for the chosen path
Deterministic logic derived from the profile.
Input schema (JSON):
{
"use_case": "Customer support response generation",
"expected_qps": 5, # queries per second peak
"monthly_volume_queries": 4000000, # queries per month
"avg_tokens_in": 800,
"avg_tokens_out": 200,
"latency_budget_ms": 2000,
"accuracy_required": "frontier", # frontier | high | acceptable
"domain_specific": false, # need specific vocabulary / format / behavior
"data_for_finetune_available": false, # do we have labeled data for fine-tune?
"team_ml_capacity_engineers": 1,
"compliance_requires_self_host": false # data residency / sovereignty constraint
}
Usage:
python model_buildvsbuy_calculator.py # uses embedded customer-support sample
python model_buildvsbuy_calculator.py path/to/use_case.json
python model_buildvsbuy_calculator.py use_case.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List, Tuple
SAMPLE: Dict[str, Any] = {
"use_case": "Customer support response generation (B2B SaaS)",
"expected_qps": 5,
"monthly_volume_queries": 4_000_000,
"avg_tokens_in": 800,
"avg_tokens_out": 200,
"latency_budget_ms": 2000,
"accuracy_required": "high",
"domain_specific": True,
"data_for_finetune_available": False,
"team_ml_capacity_engineers": 1,
"compliance_requires_self_host": False,
}
# 2026 API pricing per million tokens, $USD (input / output). These are illustrative;
# real pricing changes; rerun this calculator quarterly.
API_PRICING = {
"frontier-premium": {"input": 3.00, "output": 15.00, "label": "Claude Sonnet 4.6 / GPT-4o-tier"},
"frontier-economy": {"input": 1.25, "output": 5.00, "label": "Gemini 2.5 Flash / Claude Haiku 4.5-tier"},
"open-router-hosted": {"input": 0.50, "output": 1.50, "label": "Llama 3.1 70B / Qwen 2.5 72B via hosted endpoint"},
}
# Fine-tune cost (one-time + ongoing)
FINETUNE_ONE_TIME = 25_000 # data prep + initial training + eval harness
FINETUNE_ANNUAL_RETRAIN = 15_000 # quarterly retraining + ops
FINETUNE_INFERENCE_PER_M = 0.40 # cost per M tokens at moderate scale on hosted endpoint
# Self-hosted inference cost (per million tokens, including GPU + ops at 70% utilization)
SELF_HOSTED_PER_M = {
"7b-13b": 0.15,
"70b-class": 1.50,
"frontier-class": 12.00, # very expensive without massive scale; included for completeness
}
# Build-from-scratch cost (one-time + ongoing) — illustrative; usually NOT recommended
BUILD_FROM_SCRATCH_ONE_TIME = 8_000_000
BUILD_FROM_SCRATCH_ANNUAL = 3_000_000
def compute_api_cost_3yr(profile: Dict[str, Any], tier: str) -> float:
"""3-year API cost given workload."""
monthly_queries = profile.get("monthly_volume_queries", 0)
tokens_in = profile.get("avg_tokens_in", 0)
tokens_out = profile.get("avg_tokens_out", 0)
monthly_input_tokens_m = (monthly_queries * tokens_in) / 1_000_000
monthly_output_tokens_m = (monthly_queries * tokens_out) / 1_000_000
pricing = API_PRICING.get(tier, API_PRICING["frontier-premium"])
monthly_cost = (
monthly_input_tokens_m * pricing["input"]
+ monthly_output_tokens_m * pricing["output"]
)
return monthly_cost * 36 # 3 years
def compute_finetune_cost_3yr(profile: Dict[str, Any]) -> float:
monthly_queries = profile.get("monthly_volume_queries", 0)
tokens_total = profile.get("avg_tokens_in", 0) + profile.get("avg_tokens_out", 0)
monthly_tokens_m = (monthly_queries * tokens_total) / 1_000_000
monthly_inference = monthly_tokens_m * FINETUNE_INFERENCE_PER_M
annual_inference = monthly_inference * 12
return FINETUNE_ONE_TIME + (annual_inference + FINETUNE_ANNUAL_RETRAIN) * 3
def compute_self_hosted_cost_3yr(profile: Dict[str, Any], model_class: str) -> float:
"""3-year self-hosted cost including GPU + ops."""
monthly_queries = profile.get("monthly_volume_queries", 0)
tokens_total = profile.get("avg_tokens_in", 0) + profile.get("avg_tokens_out", 0)
monthly_tokens_m = (monthly_queries * tokens_total) / 1_000_000
per_m = SELF_HOSTED_PER_M.get(model_class, SELF_HOSTED_PER_M["70b-class"])
monthly_inference = monthly_tokens_m * per_m
# Add fixed ops cost: 1 engineer * 30% load * fully-loaded $250K/yr = $75K/yr ops attribution
annual_ops = 75_000
return (monthly_inference * 36) + (annual_ops * 3)
def compute_build_cost_3yr() -> float:
return BUILD_FROM_SCRATCH_ONE_TIME + (BUILD_FROM_SCRATCH_ANNUAL * 3)
def pick_recommendation(profile: Dict[str, Any], costs: Dict[str, float]) -> Tuple[str, str, List[str]]:
"""Pick API / FINE_TUNE / BUILD with reasoning and failure modes."""
accuracy = profile.get("accuracy_required", "high")
domain_specific = profile.get("domain_specific", False)
finetune_data = profile.get("data_for_finetune_available", False)
ml_capacity = profile.get("team_ml_capacity_engineers", 0)
self_host_required = profile.get("compliance_requires_self_host", False)
latency_ms = profile.get("latency_budget_ms", 2000)
monthly_q = profile.get("monthly_volume_queries", 0)
# Special case: compliance forces self-host
if self_host_required:
return (
"FINE_TUNE",
(
"Compliance / data residency forces self-host. Fine-tune a 70B-class open model "
f"({_fmt_money(costs['finetune_3yr'])}/3yr) rather than build from scratch "
f"({_fmt_money(costs['build_3yr'])}/3yr) — the gap is two orders of magnitude with "
"comparable quality for most use cases."
),
[
"Quality lags frontier by ~6 months; budget for refresh every 12-18mo",
"Self-hosting requires 24/7 on-call; budget 30%+ of an engineer FTE",
"Eval discipline becomes non-negotiable; without an eval set you cannot tell when retraining is needed",
],
)
# Build from scratch — almost never
if accuracy == "frontier" and monthly_q > 1_000_000_000 and ml_capacity >= 20:
return (
"BUILD",
(
"Edge case where frontier accuracy + extreme volume + large ML team justify pre-training. "
"Cost still extreme. Most companies here are foundation-model startups, not application companies."
),
[
"By the time you ship, frontier models have caught up — sunk cost risk",
"Requires sustained $50M+ investment over 18+ months",
"Unless model IS your product, do not build",
],
)
# Fine-tune cases
if domain_specific and finetune_data and ml_capacity >= 2:
return (
"FINE_TUNE",
(
"Domain-specific behavior + labeled data + ML engineering capacity available. "
f"Fine-tune cost ({_fmt_money(costs['finetune_3yr'])}) competes with API at this volume."
),
[
"Fine-tuned model lags frontier by ~6 months; quality drift is inevitable",
"Retraining cadence (quarterly typical) is a recurring engineering cost",
"Without eval set, fine-tune drift is invisible until customer complains",
],
)
# Latency-driven fine-tune (sub-500ms with 70B-class)
if latency_ms < 500 and monthly_q > 1_000_000:
return (
"FINE_TUNE",
(
f"Latency budget {latency_ms}ms below frontier-API median (~600-1500ms). "
"Fine-tuned 70B-class on dedicated infra is the path to sub-500ms at scale."
),
[
"Sub-500ms requires GPU co-location and warm pools (idle time penalty)",
"Quality must be re-verified at every model swap",
"Streaming responses can buy headroom on latency budget; consider before committing to fine-tune",
],
)
# Default to API for everything else
economy_acceptable = accuracy in ("acceptable", "high")
if economy_acceptable and costs["api_economy_3yr"] < costs["finetune_3yr"]:
return (
"API",
(
f"Frontier-economy API tier ({API_PRICING['frontier-economy']['label']}) at "
f"{_fmt_money(costs['api_economy_3yr'])}/3yr beats fine-tune ({_fmt_money(costs['finetune_3yr'])}/3yr). "
"Iterate on prompt engineering and eval discipline before committing to fine-tune."
),
[
"Vendor lock-in: build abstraction layer (LiteLLM, OpenRouter) for multi-vendor failover",
"Capability drift between model versions: pin model IDs and run regression evals on upgrades",
"Rate limits at QPS spikes: confirm Tier-4+ pricing with provider",
],
)
return (
"API",
(
f"Frontier-premium API at {_fmt_money(costs['api_premium_3yr'])}/3yr is the right starting point. "
"Revisit fine-tune at ≥10M queries/month OR domain-specific behavior the API can't be prompted into."
),
[
"Vendor lock-in: build abstraction layer for multi-vendor failover",
"Capability drift between model versions; pin model IDs",
"Rate limits at QPS spikes; confirm pricing tier with provider",
],
)
def analyze(profile: Dict[str, Any]) -> Dict[str, Any]:
costs = {
"api_premium_3yr": compute_api_cost_3yr(profile, "frontier-premium"),
"api_economy_3yr": compute_api_cost_3yr(profile, "frontier-economy"),
"api_open_hosted_3yr": compute_api_cost_3yr(profile, "open-router-hosted"),
"finetune_3yr": compute_finetune_cost_3yr(profile),
"self_hosted_70b_3yr": compute_self_hosted_cost_3yr(profile, "70b-class"),
"build_3yr": compute_build_cost_3yr(),
}
recommendation, reasoning, failure_modes = pick_recommendation(profile, costs)
# Compute breakeven volume where API and fine-tune cross
monthly_q = profile.get("monthly_volume_queries", 1)
tokens_per_q = profile.get("avg_tokens_in", 0) + profile.get("avg_tokens_out", 0)
annual_q = monthly_q * 12
# Find breakeven where API economy total == fine-tune total over 3 years
if tokens_per_q and annual_q:
api_economy_per_query = costs["api_economy_3yr"] / (annual_q * 3) if annual_q else 0
# finetune_cost = ONE_TIME + (queries * tokens * inference_per_m / 1M + ANNUAL_RETRAIN) * 3
# Solve for queries where api_cost == finetune_cost
# api_economy_per_query * Q = FINETUNE_ONE_TIME + (Q * tokens_per_q * FINETUNE_INFERENCE_PER_M / 1M + RETRAIN) * 3
# api_economy_per_query * Q - 3 * Q * tokens_per_q * FINETUNE_INFERENCE_PER_M / 1M = FINETUNE_ONE_TIME + 3 * RETRAIN
# Q * (api_economy_per_query - 3 * tokens_per_q * FINETUNE_INFERENCE_PER_M / 1M) = ONE_TIME + 3 * RETRAIN
coefficient = (
api_economy_per_query
- 3 * tokens_per_q * FINETUNE_INFERENCE_PER_M / 1_000_000
)
rhs = FINETUNE_ONE_TIME + 3 * FINETUNE_ANNUAL_RETRAIN
breakeven_3yr_queries = int(rhs / coefficient) if coefficient > 0 else None
breakeven_monthly_queries = int(breakeven_3yr_queries / 36) if breakeven_3yr_queries else None
else:
breakeven_monthly_queries = None
return {
"recommendation": recommendation,
"reasoning": reasoning,
"failure_modes": failure_modes,
"costs_3yr_usd": {k: round(v, 0) for k, v in costs.items()},
"breakeven_monthly_queries_api_vs_finetune": breakeven_monthly_queries,
"current_monthly_volume": profile.get("monthly_volume_queries", 0),
}
def render_text(result: Dict[str, Any], profile: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("MODEL BUILD-VS-BUY ANALYSIS")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Use case: {profile.get('use_case')}")
lines.append(f" Volume: {profile.get('monthly_volume_queries'):,} queries/mo @ {profile.get('expected_qps')} QPS peak")
lines.append(f" Tokens: {profile.get('avg_tokens_in')} in / {profile.get('avg_tokens_out')} out per query")
lines.append(f" Latency budget: {profile.get('latency_budget_ms')}ms | Accuracy: {profile.get('accuracy_required')}")
lines.append(f" Domain-specific: {profile.get('domain_specific')} | Fine-tune data available: {profile.get('data_for_finetune_available')}")
lines.append(f" ML capacity: {profile.get('team_ml_capacity_engineers')} engineers | Compliance forces self-host: {profile.get('compliance_requires_self_host')}")
lines.append("")
lines.append("-" * 72)
lines.append(f"RECOMMENDATION: {result['recommendation']}")
lines.append("")
for line in _wrap(result["reasoning"], 2):
lines.append(line)
lines.append("")
lines.append("Failure modes to plan for:")
for fm in result["failure_modes"]:
lines.append(f" • {fm}")
lines.append("")
lines.append("-" * 72)
lines.append("3-YEAR TCO COMPARISON ($ USD):")
lines.append("")
costs = result["costs_3yr_usd"]
lines.append(f" API (frontier-premium, {API_PRICING['frontier-premium']['label']}): {_fmt_money(costs['api_premium_3yr']):>15}")
lines.append(f" API (frontier-economy, {API_PRICING['frontier-economy']['label']}): {_fmt_money(costs['api_economy_3yr']):>15}")
lines.append(f" API (open-router-hosted, {API_PRICING['open-router-hosted']['label']}): {_fmt_money(costs['api_open_hosted_3yr']):>15}")
lines.append(f" Fine-tune (70B-class, hosted inference): {_fmt_money(costs['finetune_3yr']):>15}")
lines.append(f" Self-hosted (70B-class on rented H100/A100): {_fmt_money(costs['self_hosted_70b_3yr']):>15}")
lines.append(f" Build from scratch (pre-train + ops): {_fmt_money(costs['build_3yr']):>15}")
lines.append("")
if result["breakeven_monthly_queries_api_vs_finetune"]:
lines.append(f"Breakeven: API (economy) vs fine-tune crosses at ~{result['breakeven_monthly_queries_api_vs_finetune']:,} queries/month")
if result["current_monthly_volume"] < result["breakeven_monthly_queries_api_vs_finetune"]:
lines.append(f" Current volume ({result['current_monthly_volume']:,}/mo) is BELOW breakeven → API still cheaper.")
else:
lines.append(f" Current volume ({result['current_monthly_volume']:,}/mo) is ABOVE breakeven → fine-tune economics favorable.")
lines.append("")
lines.append("-" * 72)
lines.append("REMINDER: TCO does not capture quality cost. Fine-tune quality lags frontier by ~6 months;")
lines.append("self-hosted requires eval discipline you may not have. Re-run quarterly with updated pricing.")
return "\n".join(lines)
def _fmt_money(amount: float) -> str:
return f",.0f"
def _wrap(text: str, indent: int, width: int = 70) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="Decide API vs fine-tune vs build with 3-year TCO comparison.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to use_case JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: B2B SaaS customer-support generation, 4M queries/mo>"
result = analyze(profile)
if args.output == "json":
print(json.dumps({"source": source, "profile": profile, **result}, indent=2))
else:
print(render_text(result, profile, source))
return 0
if __name__ == "__main__":
sys.exit(main())
Tư vấn Chief Data Officer: quyền dữ liệu huấn luyện AI, chiến lược sản phẩm dữ liệu, định giá dữ liệu khách hàng và nhân sự.
---
name: "chief-data-officer-advisor"
description: "Chief Data Officer advisory for startups: AI training data rights and consent provenance, data product strategy (warehouse vs lakehouse vs mesh, build-vs-buy), B2B customer-data-as-asset valuation and M&A readiness, data team org evolution. Use when deciding whether to train models on customer data, choosing data architecture, valuing data for fundraising or M&A, sequencing data hires, or when user mentions CDO, chief data officer, data strategy, data mesh, lakehouse, training data, data product, data monetization, or customer data asset. NOT a tactical data engineering skill — strategic decisions only."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: chief-data-officer-leadership
updated: 2026-05-12
python-tools: ai_training_data_audit.py, data_product_strategy_picker.py, data_asset_valuator.py
frameworks: training-data-rights-matrix, data-product-strategy, customer-data-as-asset, data-team-org-evolution
---
# Chief Data Officer Advisor
Strategic data leadership for startup CDOs and founders without one. **Four decisions, no surveys:**
1. **Can we train our model on this data?** — origin × consent × use-case matrix
2. **Warehouse, lakehouse, or mesh — and what do we build vs buy?** — stage-driven architecture
3. **What is our customer data worth?** — strategic value + M&A multiplier + productization paths
4. **What data role do we hire next?** — stage-to-role map, centralize-vs-embed trigger
This skill does **not** cover tactical data engineering. For schema design, observability, query optimization, RAG, or ML platform implementation, see `engineering/database-designer/`, `engineering/observability-designer/`, `engineering/data-quality-auditor/`, `engineering/sql-database-assistant/`, `engineering/rag-architect/`, `engineering/llm-cost-optimizer/`.
## Keywords
CDO, chief data officer, AI training data, consent provenance, training rights, GDPR Article 6 lawful basis, GDPR Article 22, EU AI Act high-risk, ePrivacy, copyright fair use, hiQ v. LinkedIn, scraped data, synthetic data, data product, data mesh, lakehouse, medallion architecture, dbt, Snowflake, BigQuery, Databricks, Fivetran, Airbyte, reverse ETL, feature store, customer data as asset, data monetization, data productization, anonymization, k-anonymity, differential privacy, M&A data diligence, data org, analytics engineer, data engineer, data scientist, data product manager, centralize vs embed, hub and spoke
## Quick Start
```bash
# Audit data sources for AI training eligibility
python scripts/ai_training_data_audit.py # uses embedded sample
python scripts/ai_training_data_audit.py path/to/sources.json
# Pick data architecture + build-vs-buy + sequencing
python scripts/data_product_strategy_picker.py # uses embedded Series A SaaS
python scripts/data_product_strategy_picker.py path/to/profile.json
# Value the customer data corpus + productization viability
python scripts/data_asset_valuator.py # uses embedded B2B sample
python scripts/data_asset_valuator.py path/to/corpus.json
```
## Key Questions (ask these first)
- **What decision does this data drive?** (If none, why are we collecting it?)
- **What's the consent provenance of every source we want to train on?** (TOS-only is not the same as explicit opt-in.)
- **Who are the internal data consumers, and how many distinct domains do they span?** (Drives centralize-vs-embed and warehouse-vs-mesh.)
- **In an M&A scenario, is our data a moat or a liability?** (Customer carve-outs in MSAs can flip the answer.)
- **Are we hiring an analytics engineer or a data scientist next?** (They solve different problems; founders confuse them.)
- **Have we run an anonymization audit before any external sharing?** (k-anonymity ≥ 5 is the floor, not the ceiling.)
## Core Responsibilities
### 1. AI Training Data Rights
The 2026 question every startup is facing: **can we use customer data to train our model?**
The answer is rarely binary. It depends on three independent dimensions:
| Dimension | Values |
|---|---|
| **Origin** | 1st-party-explicit-opt-in / 1st-party-TOS-only / partner-licensed / scraped / synthetic |
| **Data class** | Anonymous aggregate / behavioral / PII / 3rd-party content / regulated (PHI, PCI, kids) |
| **Use case** | In-product personalization / fine-tune our model / train foundation model / external sharing |
Each combination produces GO / MITIGATE / NO-GO. **Run** `ai_training_data_audit.py` on a JSON inventory of sources.
See `references/ai_training_data_rights.md` for the full matrix + GDPR Art. 6 lawful basis decision tree + EU AI Act high-risk triggers.
### 2. Data Product Strategy
**Architecture choice (warehouse vs lakehouse vs mesh) is stage-driven, not preference-driven:**
- **Warehouse only** (Snowflake / BigQuery / Postgres): ≤5 data consumers, <2TB, no ML use cases
- **Lakehouse** (warehouse + object storage, often Databricks or Snowflake-with-Iceberg): 5–25 data consumers, 2TB–1PB, 1–3 ML use cases
- **Data mesh**: 25+ data consumers across 4+ domains, federated ownership culture in place
**Build vs buy is decided per layer:**
| Layer | Buy unless | Build only if |
|---|---|---|
| Storage / warehouse | Never build | (You’re a data infra company) |
| ELT / ingest | Never build | Source isn’t supported by Fivetran/Airbyte |
| Modeling (dbt) | Always build | This is your IP |
| BI / dashboards | Buy at <100 consumers | Embedded analytics for customers |
| Feature store | Defer until 3+ prod models | Then build OR buy Tecton/Hopsworks |
| ML platform | Defer until 5+ prod models | Then buy SageMaker/Vertex/Databricks |
**Run** `data_product_strategy_picker.py` for a stage-specific recommendation. See `references/data_product_strategy.md` for kill criteria per architecture and the build-vs-buy decision tree.
### 3. B2B Customer-Data-as-Asset
**The shift:** at Series B+, customer data is no longer just operational — it’s an asset that can be:
- A defensibility moat (replicating requires years of customer cohort)
- An M&A multiplier (1.2x–2x ARR uplift for strategic buyers)
- A direct revenue stream (anonymized industry benchmarks, embedding endpoints, licensing)
But it can also be a **liability**:
- 47/380 customers with MSA carve-outs makes productization legally infeasible
- Anonymization audits often reveal re-identification risk above tolerable thresholds
- Regulatory exposure increases linearly with productization (GDPR Art. 28 processors vs Art. 26 joint controllers)
**Run** `data_asset_valuator.py` with corpus characteristics to get strategic value score + productization paths + risk-adjusted value.
See `references/customer_data_as_asset.md` for the valuation framework, M&A diligence prep checklist, and contractual constraint audit pattern.
### 4. Data Team Org Evolution
**The wrong question:** "Should we hire a data scientist?"
**The right question:** "What’s the next decision we can’t make because we lack data, and what role unblocks that?"
Stage-to-role map (B2B SaaS baseline):
| Stage | First hire | Then | Then |
|---|---|---|---|
| Pre-seed / seed | Founder-as-analyst (SQL + spreadsheets) | — | — |
| Series A (Series A) | Analyst | Analytics engineer (dbt) | — |
| Series B | Data engineer | Senior analyst (embedded in GTM) | Data PM (if 3+ teams need data) |
| Growth | Manager of analytics | ML engineer (if model is core) | Head of Data |
| Late-stage | Head of Data → CDO | Specialized: BI, MLE, DPO | Federated owners per domain (mesh) |
**Centralize-vs-embed trigger:** when 3+ functional areas (sales, marketing, product, ops, CS) need bespoke data weekly, the central team becomes the bottleneck. Move to hub-and-spoke (central platform + embedded analysts) before that becomes a hiring crisis.
See `references/data_team_org_evolution.md`.
## Workflows
### Workflow 1: AI Training Decision (1 hour)
**Goal:** Decide whether a specific data source can train a specific use case.
```bash
# 1. Build sources.json with one entry per data source
# 2. Run the audit
python scripts/ai_training_data_audit.py sources.json
# 3. For each MITIGATE: assign owner + remediation
# 4. For each NO-GO: document the kill reason for the legal log
# 5. Cross-check with cs-general-counsel-advisor on top-3 mitigation items
# 6. Log via /cs:decide
```
### Workflow 2: Architecture Decision (1 day)
**Goal:** Pick warehouse / lakehouse / mesh and the build-vs-buy split for the next 12 months.
```bash
python scripts/data_product_strategy_picker.py profile.json
# Cross-check with cs-cto-advisor on engineering capacity
# Cross-check with cs-cfo-advisor on 3-year TCO
# Log via /cs:decide; consider /cs:freeze 90 if signing a multi-year SaaS contract
```
### Workflow 3: Data Asset Valuation for M&A Prep (3 days)
**Goal:** Value the data corpus and prepare for due diligence.
1. Inventory the corpus: size, freshness, exclusivity, customer overlap, contractual restrictions
2. Run `data_asset_valuator.py`
3. Run the M&A diligence prep checklist in `customer_data_as_asset.md`
4. Surface contractual carve-outs to cs-general-counsel-advisor for re-papering plan
5. Decide productization path (benchmark report / embedding endpoint / direct license)
6. Log via /cs:decide
### Workflow 4: Data Team Roadmap (1 week)
**Goal:** Build the next 18 months of data hires aligned to business decisions.
1. List the top 5 decisions the business can’t make today due to missing data or analysis
2. Map each decision to the role that unblocks it
3. Sequence hires (one role at a time, ramp before next)
4. Cross-check with cs-chro-advisor on comp bands and leveling
5. Identify the centralize-vs-embed trigger date
## Output Standards (when invoked via cs-cdo-advisor)
```
**Bottom Line:** [one sentence — decision and rationale]
**The Decision:** [one of the 4 framings]
**The Evidence:** [numbers, not adjectives]
**How to Act:** [3 concrete next steps]
**Your Decision:** [the call only the founder can make]
```
## Adjacent Skills
- `../cto-advisor/` — architecture capacity, scaling cliffs
- `../ciso-advisor/` — data security, threat modeling for productized data
- `../general-counsel-advisor/` — contractual constraints, DPA, training-data rights
- `../cfo-advisor/` — build-vs-buy TCO, M&A valuation math
- `../chro-advisor/` — data team hiring, leveling, comp
- `../../../engineering/database-designer/` — tactical schema design
- `../../../engineering/rag-architect/` — tactical AI/RAG implementation
- `../../../engineering/llm-cost-optimizer/` — model cost management
## References
- [ai_training_data_rights.md](references/ai_training_data_rights.md) — The training-rights matrix + GDPR Art. 6 / EU AI Act decision tree
- [data_product_strategy.md](references/data_product_strategy.md) — Warehouse / lakehouse / mesh kill criteria + build-vs-buy decision tree
- [customer_data_as_asset.md](references/customer_data_as_asset.md) — Valuation framework + M&A diligence prep + productization paths
- [data_team_org_evolution.md](references/data_team_org_evolution.md) — Stage-to-role map + centralize-vs-embed trigger
---
**Version:** 1.0.0
**Status:** Production Ready
**Disclaimer:** Decisions touching training data rights, data productization, or M&A data diligence should involve qualified counsel. This skill surfaces decisions and tradeoffs — it does not replace legal review.
FILE:references/ai_training_data_rights.md
# AI Training Data Rights — The Decision: "Can we train on this data?"
This reference answers exactly one decision per data source: **may we use this for AI training, and for which use case?** It does so by combining three independent dimensions into a verdict.
Pair with `scripts/ai_training_data_audit.py` for automation. **Not legal advice.**
## The Three Dimensions
### Dimension 1: Origin
Where did this data come from, and what consent flow accompanied it?
| Origin | Strength | Notes |
|---|---|---|
| `1st-party-explicit-opt-in` | Strongest | User saw a notice for THIS purpose and clicked agree. GDPR Art. 6(1)(a). |
| `1st-party-tos-only` | Weak | Bundled TOS doesn't satisfy GDPR Art. 6 for materially different purposes (training). |
| `partner-licensed` | Depends | Only as strong as the partner's original consent flow + your license scope. |
| `scraped` | Insufficient | No lawful basis under GDPR Art. 6; potentially Computer Fraud and Abuse Act / copyright exposure. |
| `synthetic` | Strong | But synthetic data inherits risks from its seed source if any. |
### Dimension 2: Data Class
What's in the data?
| Class | Implication |
|---|---|
| `anonymous-aggregate` | Safest. K-anonymity ≥ 5 maintained. |
| `behavioral` | Usually safe with proper consent. Watch for re-identification. |
| `pii` | Highest scrutiny. Requires lawful basis + deletion-on-request handling. |
| `third-party-content` | User-uploaded files, snippets, transcripts that include external content. Copyright + DMCA exposure. |
| `regulated` | PHI, PCI, COPPA-children data, biometrics. Framework-specific consent required. |
### Dimension 3: Use Case
What are you doing with it?
| Use case | Risk profile |
|---|---|
| `in-product-personalization` | Lowest risk; recommended within-product. Performance of contract often covers this. |
| `fine-tune-our-model` | Medium risk. Specific opt-in usually needed for non-anonymous classes. |
| `train-foundation-model` | High risk. Re-identification + memorization concerns; almost never permissible for PII without specific consent. |
| `external-sharing` | Highest risk. Recipient becomes a data controller (GDPR Art. 26 / 28 analysis required). |
## The Verdict Matrix (excerpt — full logic in audit tool)
| Origin × Class × Use Case | Verdict |
|---|---|
| `scraped` × any × any | NO-GO (no exceptions for training) |
| `1st-party-tos-only` × `pii` × `fine-tune-our-model` | NO-GO (TOS insufficient for material purpose change) |
| `1st-party-explicit-opt-in` × `pii` × `in-product-personalization` | GO (strongest position) |
| `1st-party-tos-only` × `behavioral` × `fine-tune-our-model` | GO (with DPIA + deletion handling) |
| `partner-licensed` × `anonymous-aggregate` × `train-foundation-model` | GO (with license-scope review) |
| `synthetic` × `anonymous-aggregate` × `train-foundation-model` | GO (with provenance log) |
| any × `regulated` × `train-foundation-model` | NO-GO (framework prohibits raw use) |
Run `python scripts/ai_training_data_audit.py` for the full matrix applied to your sources.
## GDPR Art. 6 Lawful Basis Decision Tree (EU residents only)
If any EU resident data flows, GDPR applies. Pick exactly one lawful basis per purpose:
1. **Art. 6(1)(a) Consent.** The user said yes to THIS specific purpose. Most defensible. Must be granular, freely given, revocable.
2. **Art. 6(1)(b) Performance of contract.** Processing is necessary to deliver the service the user purchased. Works for in-product personalization within reasonable expectations.
3. **Art. 6(1)(c) Legal obligation.** You're required by law. Rare for training data.
4. **Art. 6(1)(d) Vital interests.** Life or death. Practically never applies to AI training.
5. **Art. 6(1)(e) Public interest.** Government / public mission. Rarely applies to private companies.
6. **Art. 6(1)(f) Legitimate interest.** Balancing test: your interest vs the user's rights. Requires Legitimate Interest Assessment (LIA). Defensible for fraud detection, security; weak for personalization beyond user expectations.
**Practical takeaway:** For training data outside in-product personalization, default to Art. 6(1)(a) explicit consent. Art. 6(1)(f) is increasingly disfavored by EU regulators for AI training (see EDPB Opinion 28/2024).
## EU AI Act High-Risk Triggers
The EU AI Act (in force 2026) imposes additional data governance requirements for high-risk AI systems. You are high-risk if your AI is used for:
- Biometric identification (other than verification)
- Critical infrastructure management
- Education access / scoring
- Employment / worker management (including hiring algorithms)
- Access to essential services (credit, insurance, public benefits)
- Law enforcement
- Migration / border control
- Administration of justice
If you are high-risk, **Art. 10 (data governance)** requires:
- Training-data quality criteria (representativeness, accuracy, completeness)
- Bias examination + mitigation
- Provenance documentation per source
- Pre-deployment conformity assessment
If you're low-risk (most B2B SaaS), the heavy obligations are GDPR-side, not AI-Act-side. But you still need provenance logs for Art. 53 (general-purpose models).
## US State Patchwork
| Law | What it covers |
|---|---|
| California CCPA / CPRA | Right to know, delete, opt-out of sale (incl. some training scenarios) |
| Colorado AI Act (CO SB 21-169 successor) | Bias audit requirements for AI in consumer decisions |
| New York City Local Law 144 | Bias audit required for AI in hiring (NYC employers) |
| Illinois BIPA | Biometric data requires explicit written consent |
| Texas TCPA | Capture-of-biometric-identifier rules |
| Washington My Health My Data Act | Consumer health data including inference |
## Practical Decision Pattern
For every new AI training initiative:
1. **List the data sources you plan to use** (be exhaustive — including "internal" ones)
2. **Tag each with origin × class × use case**
3. **Run `ai_training_data_audit.py`**
4. **For NO-GO:** Document the kill reason in the legal log. Either drop the source or change the use case.
5. **For MITIGATE:** Assign owner + remediation. Block training until complete.
6. **For GO:** Document the lawful basis and maintain the provenance log.
7. **Cross-check with cs-general-counsel-advisor** on top-3 mitigation items.
8. **Cross-check with cs-ciso-advisor** on data flow security.
9. **Log the decision via `/cs:decide`.**
## When This Reference Doesn't Help
- **Building synthetic data pipelines.** The synthetic data origin tag covers strategy, not generation; talk to engineering.
- **Differential privacy implementations.** Engineering territory. See `engineering/database-designer/` for guidance.
- **EU AI Act conformity assessments.** Requires a specialist; this reference identifies the trigger, not the remediation.
- **Class actions / litigation defense.** Outside counsel territory; this reference is preventive.
---
**Source authorities (non-exhaustive):**
- GDPR (Regulation (EU) 2016/679)
- EU AI Act (Regulation (EU) 2024/1689)
- EDPB Opinion 28/2024 on processing of personal data in AI models
- CCPA / CPRA (California Civil Code § 1798.100 et seq.)
- hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019)
- NYT Co. v. OpenAI (filing, 2024, ongoing)
- Authors Guild v. Google, 804 F.3d 202 (2d Cir. 2015)
FILE:references/customer_data_as_asset.md
# Customer Data as Asset — The Decision: "What is our customer data worth, and can we productize it?"
This reference answers exactly one decision: **at Series B+, when customer data is no longer operational but strategic, how do we value it, monetize it, and survive M&A diligence?**
Pair with `scripts/data_asset_valuator.py` for automation.
## The Shift: Operational → Strategic Asset
In seed and Series A, customer data is operational: it powers the product. Starting around Series B (especially in B2B SaaS), data accumulates into something else — an asset with strategic value independent of the product's primary use.
Symptoms that the shift has happened:
- An acquirer asks about data corpus in their LOI
- A partner asks to license anonymized data for benchmarking
- A customer demands a contractual carve-out preventing data use beyond their own service
- The board asks "what are we doing with the data?"
When these surface, you need a CDO answer, not a CTO answer.
## The Valuation Framework — Five Components
Strategic value (composite score 0-10) is the product of five components:
### 1. Exclusivity
**Is the data uniquely yours, or is it available elsewhere?**
| Level | Definition |
|---|---|
| `none` | Same data is in public sources (web scrapes, public records) |
| `low` | Commercially available from data brokers (e.g., LinkedIn / ZoomInfo data) |
| `medium` | Available only via specific platforms (e.g., Stripe transaction data, Slack messages) |
| `high` | No public or commercial equivalent (e.g., your unique customer cohort's workflow behavior) |
**Default for B2B SaaS:** medium-to-high. The combination of customer cohort + your specific product usage is usually exclusive.
### 2. Freshness
**How current is the data?**
Real-time > near-real-time > daily batch > weekly batch. Predictive value decays roughly exponentially with staleness.
### 3. Cohort Breadth
**How many customers does the corpus span?**
Below 50 customers: insufficient cohort for benchmarks. 50–200: marginally productizable. 200–500: solid. 500+: strong.
**Cohort breadth is highly correlated with industry-specific value:** a 500-customer B2B SaaS in vertical X often has more strategic value than a 5000-customer horizontal SaaS, because the verticalized cohort is harder to replicate.
### 4. History Depth
**How many years of time-series do you have?**
1 year is anecdotal. 2–3 years shows trend. 5+ years enables cycle analysis and is increasingly rare (most startups don't survive that long).
History depth is THE thing acquirers value most — and the thing you can't manufacture later.
### 5. Real-Time Behavioral Signal
**Does the data capture intent + behavior, or just outcomes?**
Outcome data ("customer churned") is low signal. Intent + behavior data ("customer reduced usage by 40% in week 8, then opened pricing page 3 times") is high signal.
This component is implicit in the freshness + exclusivity scores in the tool.
## Moat Strength
The composite score maps to moat strength:
| Score | Moat | Defense |
|---|---|---|
| 8+ | STRONG | Replicating requires 2+ years of customer cohort acquisition |
| 5-7 | MEDIUM | Well-funded competitor with 18-24 months can match |
| 2-4 | WEAK | Some unique signal but largely replicable |
| 0-1 | NONE | Same data is freely available |
## M&A Multiplier
Acquirers (especially strategic ones, not financial) pay a multiplier on data-as-asset deals.
| Moat | Multiplier (ARR uplift) |
|---|---|
| STRONG | 1.4x – 1.7x |
| MEDIUM | 1.15x – 1.35x |
| WEAK | 1.0x – 1.1x |
| NONE | 1.0x |
**These multipliers compound with normal SaaS multiples.** A $10M ARR B2B SaaS valued at 8x ARR ($80M) with a STRONG data moat might fetch $112M-$136M in a strategic acquisition where the buyer values the cohort.
**Discounts:**
- High MSA carve-out rate (>25% of customers): -15%
- Moderate carve-out rate (10-25%): -5%
- Failed anonymization audit (re-identification risk): -10%
- Regulated data without specific consent framework: -20%
## The Three Productization Paths
### Path 1: Industry Benchmark Report (lowest risk)
**What it is:** Quarterly or semi-annual report of anonymized aggregates ("80% of B2B sales teams have >5 stalled deals in their pipeline at any time").
**Revenue potential:** Low ($50K-$500K/yr). Often given away to drive credibility / leads rather than sold.
**Why start here:**
- Lowest legal risk (anonymous aggregates, no individual data leaves)
- Highest credibility lift (your brand becomes the "definitive source" for the category)
- Tests appetite without committing to product
- Lowest customer-trust cost (customers like seeing aggregate insights)
**Prerequisites:**
- Anonymization audit confirming k-anonymity ≥ 5 in all published cells
- Opt-out flow for customers who don't want their (anonymized) data included
- Quarterly review cadence
### Path 2: Anonymized Embedding Endpoint (medium risk)
**What it is:** API that returns anonymized embeddings of your data corpus, usable by your customers (or by you) for AI features.
**Revenue potential:** Medium ($500K-$3M/yr) as a platform feature or paid add-on.
**Why medium risk:**
- Embeddings can leak training data via inversion attacks (mitigated by differential privacy)
- 47/380 customer carve-outs would block the endpoint from including their data
- Re-identification of a single customer in the corpus risks contractual + reputational damage
**Prerequisites:**
- Anonymization + memorization testing
- DPA addendum covering training-data flow
- Differential privacy on the embedding pipeline (epsilon ≤ 1.0 recommended)
- Pilot with 3 design-partner customers under explicit opt-in before broad release
### Path 3: Direct Data Licensing (highest risk)
**What it is:** Selling access to the data corpus (or derivatives) to AI labs, data brokers, or industry players.
**Revenue potential:** High ($2M-$20M/yr at scale).
**Why high risk:**
- Customer trust impact: even with proper anonymization, customers often perceive this as "selling our data"
- Requires re-papering or excluding any MSA carve-out customers
- Requires GDPR Art. 26 joint-controller analysis if EU customers are present
- Regulator scrutiny increases (e.g., FTC has signaled interest in B2B-to-AI-lab data flows in 2024-2025)
**Prerequisites (in order):**
1. Customer-trust impact assessment (CEO + Head of CS sign-off)
2. Re-paper carve-out customers OR build carve-out-excluded dataset
3. Engage data broker counsel (specialist)
4. Customer communications plan (proactive, not reactive)
5. Differential privacy on the licensed product
6. Audit clauses in the licensing contract
## M&A Diligence Prep Checklist
Acquirers will dig deep on data assets. Be ready before the LOI.
**6 months before any M&A discussion, complete:**
- [ ] Inventory of all customer data with: origin, consent flow, contractual restrictions, retention policy
- [ ] MSA carve-out audit: which customers have which restrictions; reconciliation list
- [ ] Anonymization audit: k-anonymity, re-identification risk assessment
- [ ] DPA inventory: which customers have DPAs, which subprocessors are listed, gaps
- [ ] Training-data provenance log: every model in production has documented source data
- [ ] Right-to-erasure handling: documented process for honoring GDPR Art. 17 / state law equivalents
- [ ] Cross-border data flow inventory: which EU residents' data is processed, which US states, which countries
- [ ] Vendor / subprocessor list current and reconciled with customer-facing list
- [ ] Data breach history: documented, even minor incidents
- [ ] Litigation / regulatory inquiries: documented
**Common findings that tank deals:**
- "We've been training on X without a clear lawful basis" → acquirer requires indemnity carve-out or retrains
- "We don't have a documented anonymization process" → 10-20% multiplier discount
- "30% of customers have carve-outs we can't easily reconcile" → productization-as-thesis collapses
- "Our DPA list and our customer-facing DPA list don't match" → governance red flag
## Contractual Constraint Audit (run quarterly)
Many startups don't realize their MSA template has been updated 3 times in 5 years, and earlier customers signed earlier versions. The carve-out rate often exceeds expectations.
**Quarterly audit:**
1. Pull every executed customer MSA from CLM (or DocuSign / Ironclad)
2. Search for: "data use", "training", "AI", "machine learning", "aggregate", "anonymized", "license back"
3. Categorize each customer:
- `clear` — no carve-out, standard rights
- `carve-out-aggregate-only` — can use only as anonymized aggregates
- `carve-out-no-training` — can use operationally but not for AI training
- `carve-out-blocked` — cannot use beyond own service
4. Compute carve-out rates
5. For each carve-out type, decide: re-paper at renewal? Live with the constraint? Build carve-out-excluded dataset?
## Customer Trust Considerations
The legal feasibility of productization is necessary but not sufficient. Customer trust impact is often the binding constraint.
**Signs the trust cost will exceed the revenue:**
- Customer NPS is below 30
- Recent press cycle on "Big Tech data abuses" in your category
- A vocal customer or two raised data concerns publicly
- Your sales team uses "we don't share your data" as a competitive differentiator
**If any of these are true:** delay productization 12-18 months and address trust first.
## When This Reference Doesn't Help
- **Tactical anonymization implementation.** See engineering / privacy-engineering resources.
- **Specific DPA template language.** See `c-level-advisor/skills/general-counsel-advisor/`.
- **M&A negotiation strategy.** See `c-level-advisor/skills/ma-playbook/`.
- **GDPR compliance program.** See `ra-qm-team/`.
This reference is about strategic valuation and productization decisions. Tactical execution lives elsewhere.
---
**Source authorities (non-exhaustive):**
- GDPR Articles 26 (joint controllers), 28 (processors), 35 (DPIA), 17 (right to erasure)
- EDPB Guidelines on data subject rights
- US state data broker registration laws (CA, VT, OR)
- FTC enforcement actions on data licensing (e.g., FTC v. Avast, 2024)
- Dwork, Cynthia — "Differential Privacy" (2006)
FILE:references/data_product_strategy.md
# Data Product Strategy — The Decision: "Warehouse, lakehouse, or mesh — and what do we build vs buy?"
This reference answers exactly one decision: **what is the right data platform for our stage, and which components do we build ourselves?** It is stage-driven, not technology-trend-driven.
Pair with `scripts/data_product_strategy_picker.py` for automation.
## The Three Architectures
### Warehouse Only
**What it is:** A single SQL-accessible data store (Snowflake / BigQuery / Redshift / Postgres + dbt). All transformations happen in-warehouse.
**Use when:**
- ≤5 distinct data consumers (people/teams who query data weekly)
- <2TB of data
- No ML/AI use cases in production
- Reporting + dashboards are 90%+ of use cases
**Kill criteria (stop using warehouse-only when):**
- A data consumer needs unstructured data (logs, images, audio) → can't ingest cleanly
- ML model in production needs feature pipelines → warehouse-only is rigid
- 5+ consumers means hub-and-spoke ownership becomes the bottleneck
**Failure mode:** Treating it as forever. Many companies sit on warehouse-only for 2 years past viability because migration feels expensive.
### Lakehouse
**What it is:** Warehouse + object storage (S3/GCS/Azure Blob) with a table format like Apache Iceberg, Delta Lake, or Hudi. Single substrate for SQL analytics, ML training data, and unstructured ingestion.
Implementations: Databricks (Delta), Snowflake with Iceberg, AWS Redshift with Spectrum, BigQuery with BigLake.
**Use when:**
- 5–25 distinct data consumers
- 2TB–1PB data
- 1–3 ML models in production OR planning to be in 12 months
- Mixed structured + unstructured data
- Team has engineering capacity to maintain ingestion + transformation pipelines
**Kill criteria:**
- 25+ consumers AND federated ownership culture → time to consider mesh
- ML workloads disappear AND data shrinks below 2TB → simplify back to warehouse
- Vendor lock-in becomes intolerable → table formats (Iceberg) mitigate this; lakehouse vendor swaps remain expensive
**Failure mode:** Adopting before needed. Lakehouse architecture has 2–3x the operational complexity of pure warehouse. If you have 4 consumers and no ML, it's premature.
### Data Mesh
**What it is:** Federated data product ownership. Domain teams own their data products end-to-end (ingest → modeling → serving → SLAs). Central platform team provides the infrastructure substrate but does not produce data products.
Coined by Zhamak Dehghani (Thoughtworks); productionized at Netflix, Zalando, JP Morgan.
**Use when:**
- 25+ distinct data consumers across 4+ domains
- Federated ownership culture **already exists** in the org (you can't bolt it on)
- Central data team is a bottleneck for 50%+ of work
- Stage: growth or late-stage (Series C+)
**Kill criteria (mesh failure modes):**
- After 6 months: producing teams haven't adopted ownership → revert to hub-and-spoke
- Platform team still doing 50%+ of data product work → platform isn't truly self-serve
- Domain teams complain about onboarding → too much friction for "do it yourself"
- Cross-domain analytics has degraded vs warehouse era → integration layer missing
**Failure mode:** Mesh-without-culture. Companies adopt the architecture before the operating model. Result: distributed warehouses with no governance, worse than starting point.
## The Build-vs-Buy Decision Tree
For each platform layer, the question isn't "can we build it?" — it's "is it our IP, and does building it create a moat?"
### Storage / Warehouse
**Always BUY.** Snowflake, BigQuery, Databricks, Redshift, Postgres-with-Citus. Storage is commodity. Building distributed storage is a 50-engineer-year investment with zero business return unless you ARE a data infra company.
**Only build if:** You're a database company.
### ELT / Ingest
**Almost always BUY.** Fivetran, Airbyte, Stitch, Meltano. The connector maintenance burden (200+ source APIs, all changing constantly) is unjustifiable for any non-data-infra company.
**Only build if:** Source isn't supported by any vendor AND is business-critical AND you'll contribute the connector upstream so you're not maintaining a fork forever.
### Modeling / Transformations
**Always BUILD.** dbt is the de facto standard (open source). Your domain logic encoded in dbt models IS your data IP. No vendor can supply your domain understanding.
**Variants to evaluate:**
- dbt Core (open source) → free, self-hosted, requires orchestration (Airflow/Dagster/Prefect)
- dbt Cloud → managed, expensive at scale, simpler ops
- SQLMesh → newer, claims better state management
- Coalesce → visual SQL, expensive
### BI / Dashboards
**Almost always BUY.** Metabase (cheap, OSS option), Looker (enterprise, semantic layer), Mode (analyst-friendly + SQL), Hex (notebooks + dashboards), Tableau (legacy strong), Sigma (spreadsheet UX).
**Build only if:** You're shipping embedded analytics as a customer-facing feature (then evaluate Cube.dev, Embeddable, or build on Apache Superset).
**Embedded analytics is a real build-vs-buy:** for B2B SaaS shipping dashboards to customers, the choice between embedding a vendor (Cube + custom UI) vs full custom (Superset + heavy frontend) is significant. Buy-with-customization usually wins until 100K+ customer-tenants.
### Feature Store
**DEFER until you have 3+ ML models in production.**
**Then:** Tecton (managed, expensive, mature) or Hopsworks (alternative) for BUY; Feast (open source, lighter) for BUILD-on-OSS.
**Why defer:** Feature stores solve feature reuse + governance. With 1 model, you have 0 features-to-reuse. The operational overhead of a feature store exceeds the value below ~3 models sharing features.
### ML Platform
**DEFER until you have 5+ ML models in production.**
**Then:** Databricks ML, Vertex AI (Google), SageMaker (AWS), or Azure ML.
**Why defer:** ML platforms wrap experiment tracking, model registry, deployment, monitoring. Below 5 models with active retraining, scheduled training jobs + MLflow / W&B + simple K8s deployment is sufficient.
## Operational Maturity Layers (independent of architecture)
These apply regardless of warehouse / lakehouse / mesh choice:
1. **Data quality monitoring.** dbt tests, Great Expectations, Monte Carlo. Start at any scale.
2. **Lineage tracking.** dbt auto-generates lineage; OpenLineage / DataHub / Atlan for cross-tool. Start at 50+ models.
3. **Catalog + discovery.** DataHub, Atlan, Castor, Selectstar. Start at 100+ tables consumed by 10+ people.
4. **Access control + governance.** Snowflake/BigQuery native RBAC; Immuta / Privacera for policy abstraction. Start when you have regulated data or > 50 consumers.
## Sequencing Pattern (12-month plan)
A typical Series A → Series B sequencing:
| Quarter | Focus | Deliverable |
|---|---|---|
| Q1 | Foundation | Centralized ELT (buy); dbt for top-5 marts (build); 5 data quality tests |
| Q2 | Self-serve BI | Roll out BI tool; semantic layer in dbt or LookML; train 3 functional teams |
| Q3 | First ML use case OR embedded analysts | Either feature store for top-1 ML model OR embed 1 analyst per major function |
| Q4 | Evaluate and decide | Re-run picker; decide on Q1-next-year architecture changes |
## Anti-Patterns
- **Adopting a vendor before knowing the use case.** "We bought Snowflake but we're 80% on Postgres still." → vendor first, problem second.
- **Building "platform" before having customers (consumers).** Internal data platform team with no users is shelfware.
- **Treating data mesh as an architecture choice.** It's an operating model choice; the architecture is a consequence.
- **Splitting warehouse spend across 3 vendors.** Multi-cloud data is a 3x cost increase with no benefit until you're at Series D+.
- **Hiring data scientists before analysts.** Data scientists need clean data + clear questions. Build the analyst + analytics-engineer layer first.
## When This Reference Doesn't Help
- **Schema design.** See `engineering/database-designer/`.
- **Query optimization.** See `engineering/sql-database-assistant/`.
- **Observability for data pipelines.** See `engineering/observability-designer/`.
- **RAG architecture.** See `engineering/rag-architect/`.
This reference picks the architecture and the build-vs-buy. Tactical implementation is a separate skill family.
---
**Source authorities:**
- Dehghani, Zhamak — "Data Mesh: Delivering Data-Driven Value at Scale" (O'Reilly, 2022)
- Databricks Lakehouse paper, 2021
- Apache Iceberg, Delta Lake, Apache Hudi specifications
- dbt Labs Analytics Engineering Guide
FILE:references/data_team_org_evolution.md
# Data Team Org Evolution — The Decision: "What data role do we hire next, and when do we centralize vs embed?"
This reference answers exactly one decision: **for our stage and business decisions we can't currently make, what is the next role to add — and at what point do we centralize vs embed?**
## The Wrong Question
> "Should we hire a data scientist?"
This is the wrong question. Most data scientists hired by Series A startups are unable to deliver value because:
- The data isn't clean enough for modeling
- There's no infrastructure to deploy a model
- The "model" the founder imagines is actually a SQL query
## The Right Question
> "What's the next decision we can't make because we lack data, and what role unblocks that?"
This shifts hiring from role-taxonomy to decision-unblocking. The data org grows in response to specific decision gaps.
## The Five Stages
### Stage 1: Pre-seed / Seed
**Team size:** 1-15 people. **Data team:** 0.
**Reality:** Founder is the analyst. SQL + spreadsheets are sufficient.
**Don't hire:** Data engineer, data scientist, head of data. They will have nothing to do because the questions aren't crisp enough yet.
**Tooling:** Postgres / production DB direct read access. Metabase Free or Looker Studio. Google Sheets.
**When to move to stage 2:** Founder is spending >20% of their week on data work AND it's preventing them from doing CEO work.
### Stage 2: Series A
**Team size:** 15-50 people. **Data team:** 1-3.
**First hire: Analyst (NOT data engineer, NOT data scientist).**
Why: at this stage, 80% of the value is in clean reports, dashboards, and quick ad-hoc analyses. An analyst delivers all of this. A data engineer wants to build infrastructure that's premature; a data scientist wants to build models that don't have ROI yet.
Profile: 2-4 years experience, strong SQL, BI tool fluency, comfortable with ambiguity, can talk to non-data people.
**Second hire: Analytics engineer (dbt practitioner).**
Why: after the first analyst, the most acute pain is "dashboards are out of sync because everyone defines 'active customer' differently." Analytics engineer brings discipline (dbt models, semantic layer) and turns the analyst's work into reusable infrastructure.
Profile: SQL fluency + software engineering practices (PRs, tests, version control), dbt experience preferred but not required.
**Don't hire yet:** Data engineer, data scientist, head of data, data PM.
**When to move to stage 3:** 3+ functional teams are requesting bespoke analyses weekly, AND your first ML use case has a clear ROI.
### Stage 3: Series B
**Team size:** 50-200. **Data team:** 4-8.
**Third hire: Data engineer.**
Why: ingest pipelines are now business-critical. Salesforce → warehouse, Stripe → warehouse, product events → warehouse. Reliability matters. The analytics engineer cannot maintain this AND ship dbt models.
Profile: Python + SQL + understanding of streaming vs batch tradeoffs, experience with Fivetran/Airbyte or similar.
**Fourth hire: Senior analyst (embedded in GTM, often Sales/Marketing).**
Why: GTM is where data ROI is most measurable. An analyst embedded in the sales org (or reporting dotted-line to CRO) closes the gap between data team and revenue org.
**Fifth hire (conditional): Data PM.**
When: 3+ functional teams need data and the data team has ≥4 people. The data PM owns the roadmap, intake, and SLA negotiations. Without this, the team flips into reactive mode and never builds platform.
**Conditional: Data scientist / ML engineer.**
Hire only when:
- You have at least 1 model in production OR a strong hypothesis with ROI math
- Data engineer is in place (so data scientist isn't blocked on infrastructure)
- Eng leadership signs on for productionizing models (not just notebooks)
**When to move to stage 4:** Central data team is the bottleneck for >50% of GTM data requests, OR you're hiring data people every quarter and they all report to one manager.
### Stage 4: Growth (Series C / pre-IPO)
**Team size:** 200-1000. **Data team:** 8-30.
**Sixth hire: Manager of Analytics (people manager).**
Why: at 5-8 reports, the original analytics lead can no longer code AND manage. Split into managers + senior ICs.
**Seventh hire: ML engineer (production-grade).**
When: 1+ model in production, 2-3 more planned. ML engineer owns deployment, monitoring, retraining infrastructure. Different person from data scientist (who owns model invention).
**Eighth hire: Head of Data.**
Triggers:
- Data team is 10+ people
- Data team has its own strategy independent of company strategy (problematic if no one owns the reconciliation)
- Founder/CTO is no longer the right escalation for data decisions
- Compliance / governance becomes board-level concern
The Head of Data owns data strategy, hires/fires, and is the cross-functional executive for all data + AI.
**Centralize vs Embed decision:**
By Series C, the centralize-vs-embed tension is acute. Two patterns work:
**Hub-and-spoke (most common, recommended):**
- Central data platform team owns infrastructure, governance, semantic layer
- Embedded analysts in 3-5 major functional teams (Sales, Marketing, Product, CS, Finance)
- Embedded analysts have solid-line to function leader, dotted-line to Head of Data
- Tools, standards, dbt models are central; questions and SLAs are local
**Federated (data mesh — only if culture supports):**
- Each domain team owns their data products end-to-end
- Central platform team provides infrastructure substrate, not data products
- Requires high data culture maturity; failure mode is mesh-without-culture
Hub-and-spoke handles 95% of Series C companies. Mesh fits when you're 1000+ people with strong domain ownership culture (Netflix, Zalando, JP Morgan scale).
**When to move to stage 5:** Series D / late-stage growth, 50+ data team members, multiple domains with their own data leadership.
### Stage 5: Late-stage (Series D+, post-IPO)
**Team size:** 1000+. **Data team:** 30-200+.
**CDO promotion / hire.**
Triggers:
- Data is in the company's strategic narrative (board deck, investor calls)
- Data has its own P&L (productized data, monetization)
- Multiple regulatory regimes apply (GDPR + CCPA + HIPAA + EU AI Act)
- Head of Data is escalating data-strategy questions to CTO and it's not landing right
Profile:
- Has run a data org at $100M+ ARR scale
- Comfortable with board reporting
- Strategic, not just technical
- Strong on data governance + AI policy (post-2024 AI Act and similar requirements)
**Federated CDO model (late-stage):**
At thousands-of-people scale, the CDO often runs:
- Central platform team (engineering)
- Central governance team (privacy, compliance, AI policy)
- Federated data leaders embedded per business unit
- Data product leaders for any productized data
## Specific Roles Defined
Because founders confuse these:
| Role | Owns | Does NOT own |
|---|---|---|
| Analyst | Ad-hoc analyses, dashboards, business questions | Pipeline reliability, model deployment |
| Analytics engineer | dbt models, semantic layer, data quality tests | Ingest pipelines, ML, infrastructure |
| Data engineer | Ingest pipelines (Fivetran/Airbyte/custom), warehouse infra, streaming | Modeling logic, dashboards, ML models |
| Data scientist | Model invention, experimentation, statistical analysis | Production deployment, monitoring |
| ML engineer | Production model deployment, monitoring, retraining infra | Model invention |
| Data PM | Data team roadmap, intake, prioritization, stakeholder mgmt | IC delivery work |
| Data PM (productized data) | Data products sold to customers | Internal-only data work |
| Head of Data | Data strategy, hiring, budget, exec representation | Day-to-day IC work |
| CDO | Data + AI strategy at board level, governance, P&L (where applicable) | Day-to-day execution |
## The Centralize-vs-Embed Trigger
The decision is not "centralize or embed" — it's "when do you transition from one to the other?"
**Centralized (everyone reports to one data leader):** works up to ~5 data people serving ≤5 functional teams.
**Hub-and-spoke (central platform + embedded analysts):** works from 5-30 data people serving 5-15 functional teams.
**Federated (each domain owns):** works at 30+ data people across 15+ functional teams WITH strong data culture.
**The trigger to move from centralized to hub-and-spoke:** when 3+ functional teams complain that the central team doesn't understand their domain, AND when the central team's intake queue exceeds 4 weeks of lead time.
**The trigger to move from hub-and-spoke to federated (data mesh):** when domain teams have data leaders, are already running their own data SLAs, and would rather not depend on central platform for product launches. This is rare and usually arrives at thousands-of-people scale.
## Anti-Patterns
- **Hiring a data scientist as first data hire.** They will spend 6 months unable to deliver because data isn't clean.
- **Hiring a "head of data" at Series A.** Nothing for them to manage.
- **Hiring multiple analysts before adding analytics engineer.** Dashboards multiply; consistency vanishes.
- **Building a data platform with no users.** Internal platform team with no customers is shelfware.
- **Hiring an ML engineer before a data engineer.** ML engineer cannot deploy models if data pipelines are broken.
- **Promoting an analyst to "Head of Data" without people-management experience.** Most analysts are great ICs; people management is a different skill.
## When This Reference Doesn't Help
- **Comp benchmarking.** See `c-level-advisor/skills/chro-advisor/scripts/comp_benchmarker.py`.
- **Leveling ladders.** See `c-level-advisor/skills/chro-advisor/references/leveling_ladders.md`.
- **Specific JD templates.** Not covered here; many open-source examples exist.
- **Performance management.** Standard people management; not data-specific.
This reference is about the data team's evolution as a function of company-stage decisions, not about HR mechanics.
---
**Source observations (non-exhaustive):**
- Tristan Handy (dbt Labs) — "The Modern Data Stack: Past, Present, Future"
- Maxime Beauchemin — "The Rise of the Data Engineer" (2017), "The Downfall of the Data Engineer" (2017)
- Erik Bernhardsson — "The Modern Data Experience" (2022)
- Lauren Balik — "Modern Data Stack writings"
- Direct observations from 50+ B2B SaaS data org evolutions, 2020-2026
FILE:scripts/ai_training_data_audit.py
#!/usr/bin/env python3
"""ai_training_data_audit.py — Audit data sources for AI training eligibility.
Stdlib-only. Audits each data source on 3 dimensions:
- Origin (1st-party-explicit-opt-in / 1st-party-tos-only / partner-licensed / scraped / synthetic)
- Data class (anonymous-aggregate / behavioral / pii / third-party-content / regulated)
- Use case (in-product-personalization / fine-tune-our-model / train-foundation-model / external-sharing)
Returns GO / MITIGATE / NO-GO per source with the specific risk and remediation.
NOT legal advice — surfaces decisions for qualified counsel.
Input schema (JSON):
{
"sources": [
{
"name": "Product telemetry events",
"origin": "1st-party-tos-only",
"data_class": "behavioral",
"use_case": "in-product-personalization"
},
...
]
}
Usage:
python ai_training_data_audit.py # uses embedded sample
python ai_training_data_audit.py path/to/sources.json
python ai_training_data_audit.py sources.json --output json
"""
import argparse
import json
import sys
from dataclasses import dataclass, asdict
from typing import Any, Dict, List, Optional, Tuple
SAMPLE: Dict[str, Any] = {
"sources": [
{
"name": "Anonymous product telemetry (event aggregates)",
"origin": "1st-party-tos-only",
"data_class": "anonymous-aggregate",
"use_case": "in-product-personalization",
},
{
"name": "Customer support transcripts",
"origin": "1st-party-tos-only",
"data_class": "pii",
"use_case": "fine-tune-our-model",
},
{
"name": "Scraped LinkedIn profiles",
"origin": "scraped",
"data_class": "pii",
"use_case": "fine-tune-our-model",
},
{
"name": "Synthetic conversational data (LLM-generated)",
"origin": "synthetic",
"data_class": "third-party-content",
"use_case": "train-foundation-model",
},
{
"name": "User opt-in survey responses",
"origin": "1st-party-explicit-opt-in",
"data_class": "behavioral",
"use_case": "external-sharing",
},
{
"name": "Partner-licensed industry dataset",
"origin": "partner-licensed",
"data_class": "anonymous-aggregate",
"use_case": "train-foundation-model",
},
{
"name": "Anonymized health screening responses",
"origin": "1st-party-explicit-opt-in",
"data_class": "regulated",
"use_case": "fine-tune-our-model",
},
]
}
VALID_ORIGINS = {
"1st-party-explicit-opt-in",
"1st-party-tos-only",
"partner-licensed",
"scraped",
"synthetic",
}
VALID_CLASSES = {
"anonymous-aggregate",
"behavioral",
"pii",
"third-party-content",
"regulated",
}
VALID_USE_CASES = {
"in-product-personalization",
"fine-tune-our-model",
"train-foundation-model",
"external-sharing",
}
@dataclass
class AuditResult:
name: str
origin: str
data_class: str
use_case: str
verdict: str # GO | MITIGATE | NO-GO
risk: str
remediation: str
citations: List[str]
# Verdict matrix: (origin, data_class, use_case) -> (verdict, risk, remediation, citations)
# Built by applying these rules in order; first match wins.
def _decide(origin: str, data_class: str, use_case: str) -> Tuple[str, str, str, List[str]]:
# Rule 1: Scraped data is always NO-GO for training (hiQ v. LinkedIn, copyright, GDPR Art. 6).
if origin == "scraped":
return (
"NO-GO",
"Scraped data lacks lawful basis under GDPR Art. 6 (no consent, no legitimate interest "
"balancing test); high copyright risk; hiQ v. LinkedIn left exposure for ToS-violation claims; "
"many AI Act high-risk use cases require demonstrable provenance.",
"Remove from training set. Either (a) procure licensed alternative from data broker, "
"(b) replace with synthetic data, or (c) build 1st-party explicit opt-in pipeline.",
["GDPR Art. 6", "hiQ Labs v. LinkedIn", "EU AI Act Art. 10 (data governance)"],
)
# Rule 2: Regulated data (PHI, PCI, kids) requires explicit opt-in + specific compliance
# framework; never train foundation model with raw regulated data.
if data_class == "regulated":
if origin == "1st-party-explicit-opt-in" and use_case in {"in-product-personalization", "fine-tune-our-model"}:
return (
"MITIGATE",
"Regulated data (PHI / PCI / children) may be processed under explicit opt-in IF the "
"framework permits (HIPAA Limited Data Set, COPPA verifiable parental consent). "
"Fine-tuning increases re-identification risk vs in-product use.",
"Required: (1) framework-specific consent flow, (2) DPIA/PIA on file, (3) k-anonymity "
"≥ 5 audit before any training, (4) model output filters for regulated-content leakage, "
"(5) DPA with any vendor in the pipeline.",
["HIPAA", "HITECH §13402", "COPPA", "GDPR Art. 9", "EU AI Act Annex III"],
)
return (
"NO-GO",
"Regulated data (PHI / PCI / children) cannot be used for foundation training or external "
"sharing without specific framework authorization, and not at all without explicit opt-in.",
"Either (a) restrict to in-product use under existing framework consent, (b) train on "
"synthetic data modeled on the corpus, or (c) obtain new explicit opt-in covering the "
"specific training purpose.",
["HIPAA", "GDPR Art. 9", "COPPA"],
)
# Rule 3: PII at any use case beyond in-product-personalization requires explicit opt-in,
# specific lawful basis, AND anonymization/pseudonymization.
if data_class == "pii":
if use_case == "in-product-personalization":
if origin == "1st-party-tos-only":
return (
"MITIGATE",
"PII processing for in-product personalization can rest on GDPR Art. 6(1)(b) "
"(performance of contract) or 6(1)(f) (legitimate interest) IF the personalization "
"is reasonably expected. Train-once derived models retain risk.",
"Required: (1) Art. 6 lawful basis documented, (2) data minimization audit, "
"(3) deletion request honored for the source data even after model training "
"(implementation: filter-on-output OR retrain on deletion), (4) DPIA if scale > 5000 users.",
["GDPR Art. 6", "GDPR Art. 17 (right to erasure)", "EDPB Guidelines on Art. 22"],
)
if origin == "1st-party-explicit-opt-in":
return (
"GO",
"PII with explicit opt-in for in-product personalization is the strongest position. "
"Standard residual risks: opt-in revocation, deletion requests.",
"Maintain: (1) opt-in audit trail per user, (2) machinery to honor revocation/erasure "
"(filter-on-output or retrain), (3) clear notice on what model is trained.",
["GDPR Art. 6(1)(a)", "GDPR Art. 17"],
)
# Fine-tune-our-model, train-foundation-model, external-sharing with PII
if origin == "1st-party-explicit-opt-in":
return (
"MITIGATE",
"PII for fine-tuning or beyond requires explicit opt-in covering THIS specific "
"training purpose (not generic TOS). Risk: training-data extraction attacks, "
"memorization, model-output leakage.",
"Required: (1) purpose-specific opt-in (not bundled TOS), (2) differential privacy "
"or k-anonymity audit, (3) memorization tests on the trained model, (4) DPIA, "
"(5) DPA with infra/training vendor, (6) EU AI Act conformity assessment if "
"high-risk use case.",
["GDPR Art. 6(1)(a)", "GDPR Art. 35 (DPIA)", "EU AI Act Art. 10"],
)
return (
"NO-GO",
"PII for fine-tuning or foundation training without explicit opt-in fails GDPR Art. 6. "
"TOS-only consent is insufficient for materially different purpose.",
"Either (a) restrict use case to in-product personalization under existing basis, "
"(b) build explicit opt-in pipeline before training, or (c) anonymize/pseudonymize "
"to k-anonymity ≥ 5 and re-classify as anonymous-aggregate.",
["GDPR Art. 6", "EDPB Opinion 28/2024"],
)
# Rule 4: 3rd-party content (e.g., user-uploaded files, customer support transcripts
# quoting other systems, scraped public documents within user submissions).
if data_class == "third-party-content":
if origin in {"synthetic", "partner-licensed"}:
return (
"MITIGATE",
"Synthetic or licensed 3rd-party-content carries content-license risk: even with a "
"license, training a model may exceed the license scope (e.g., 'view' license vs "
"'derivative work creation').",
"Required: (1) license review by counsel for training-specific clauses, (2) carve-out "
"for AI training in licensing agreement, (3) provenance log per source for AI Act compliance, "
"(4) opt-out mechanism if license permits revocation.",
["NYT v. OpenAI (2024)", "EU AI Act Art. 53 (general-purpose models)"],
)
if origin == "1st-party-tos-only":
return (
"MITIGATE",
"User-uploaded content under TOS-only license has uncertain training rights post-2024 "
"lawsuits. Risk: copyright infringement if model output is substantially similar to "
"training data.",
"Required: (1) TOS explicitly grants training rights for the specific model class, "
"(2) output similarity monitoring (de-duping / fuzzy match against training corpus), "
"(3) opt-out mechanism in TOS update.",
["Authors Guild v. Google", "Andersen v. Stability AI", "NYT v. OpenAI"],
)
if origin == "1st-party-explicit-opt-in":
return (
"GO",
"Explicit opt-in for training on user-uploaded content is the strongest position. "
"Maintain output-similarity guardrails to catch unexpected memorization.",
"Required: (1) opt-in audit trail, (2) revocation flow, (3) output similarity testing.",
["GDPR Art. 6(1)(a)"],
)
# Rule 5: Behavioral data — generally safer than PII, but external sharing still requires consent.
if data_class == "behavioral":
if use_case == "external-sharing":
if origin == "1st-party-explicit-opt-in":
return (
"GO",
"Behavioral data with explicit opt-in for external sharing — clean.",
"Maintain: (1) revocation flow, (2) anonymization audit before each external "
"share (k-anonymity ≥ 5), (3) recipient DPA.",
["GDPR Art. 6(1)(a)"],
)
return (
"MITIGATE",
"Behavioral data without explicit opt-in for external sharing is borderline. TOS-only "
"is weak basis; partner-licensed depends on partner's original consent flow.",
"Required: (1) anonymization to k-anonymity ≥ 5, (2) recipient DPA with no-reidentification "
"clause, (3) audit upstream consent if partner-licensed, (4) consider opt-in pipeline.",
["GDPR Art. 6", "Art. 22 (automated decision-making)"],
)
# Behavioral + training use cases
if origin in {"1st-party-explicit-opt-in", "1st-party-tos-only", "partner-licensed"}:
return (
"GO",
"Behavioral data from controlled origin for internal training is generally safe. "
"Residual risk: model leakage if behavioral patterns are individually identifying.",
"Maintain: (1) deletion handling on user request, (2) periodic memorization tests, "
"(3) DPIA if scale > 50K users or sensitive inferences.",
["GDPR Art. 6", "GDPR Art. 35"],
)
# Rule 6: Anonymous aggregate — generally safe at all use cases.
if data_class == "anonymous-aggregate":
if origin == "scraped":
# Already handled above
pass
return (
"GO",
"Anonymous aggregate data is the safest class. Residual risk: re-identification attacks "
"if aggregate cells are small.",
"Maintain: (1) k-anonymity ≥ 5 in all published aggregates, (2) differential privacy if "
"shared externally, (3) provenance log for AI Act compliance.",
["EU AI Act Art. 10", "GDPR Recital 26"],
)
# Synthetic + non-3rd-party-content
if origin == "synthetic":
return (
"GO",
"Synthetic data is generally safe for training. Residual risk: synthetic data generated "
"from a non-clean source inherits its risks.",
"Maintain: (1) document the generation pipeline including any non-synthetic seed, "
"(2) test for bias inherited from generator, (3) provenance log.",
["EU AI Act Art. 10"],
)
# Default conservative fallback
return (
"MITIGATE",
"Configuration not matched by explicit rules — manual review required.",
"Engage qualified data privacy counsel to assess this specific origin/class/use combination.",
[],
)
def audit(payload: Dict[str, Any]) -> List[AuditResult]:
results: List[AuditResult] = []
for src in payload.get("sources", []):
name = src.get("name", "<unnamed>")
origin = src.get("origin", "")
data_class = src.get("data_class", "")
use_case = src.get("use_case", "")
# Validation
errors = []
if origin not in VALID_ORIGINS:
errors.append(f"invalid origin '{origin}'")
if data_class not in VALID_CLASSES:
errors.append(f"invalid data_class '{data_class}'")
if use_case not in VALID_USE_CASES:
errors.append(f"invalid use_case '{use_case}'")
if errors:
results.append(AuditResult(
name=name,
origin=origin,
data_class=data_class,
use_case=use_case,
verdict="NO-GO",
risk=f"Schema error: {'; '.join(errors)}",
remediation=(
f"Origin must be one of {sorted(VALID_ORIGINS)}; "
f"data_class one of {sorted(VALID_CLASSES)}; "
f"use_case one of {sorted(VALID_USE_CASES)}."
),
citations=[],
))
continue
verdict, risk, remediation, citations = _decide(origin, data_class, use_case)
results.append(AuditResult(
name=name,
origin=origin,
data_class=data_class,
use_case=use_case,
verdict=verdict,
risk=risk,
remediation=remediation,
citations=citations,
))
# Sort: NO-GO first, then MITIGATE, then GO
order = {"NO-GO": 0, "MITIGATE": 1, "GO": 2}
results.sort(key=lambda r: order.get(r.verdict, 9))
return results
def render_text(results: List[AuditResult], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("AI TRAINING DATA AUDIT")
lines.append(f"Source: {source}")
lines.append(f"Sources audited: {len(results)}")
lines.append("=" * 72)
lines.append("")
counts = {"NO-GO": 0, "MITIGATE": 0, "GO": 0}
for r in results:
counts[r.verdict] = counts.get(r.verdict, 0) + 1
lines.append(f"Verdicts: 🔴 NO-GO: {counts['NO-GO']} 🟡 MITIGATE: {counts['MITIGATE']} 🟢 GO: {counts['GO']}")
lines.append("")
lines.append("-" * 72)
for i, r in enumerate(results, 1):
marker = {"NO-GO": "🔴", "MITIGATE": "🟡", "GO": "🟢"}.get(r.verdict, "•")
lines.append(f"[{i}] {marker} {r.verdict:<9} — {r.name}")
lines.append(f" Origin: {r.origin} | Class: {r.data_class} | Use case: {r.use_case}")
lines.append("")
lines.append(f" Risk:")
for line in _wrap(r.risk, 6):
lines.append(line)
lines.append("")
lines.append(f" Remediation:")
for line in _wrap(r.remediation, 6):
lines.append(line)
if r.citations:
lines.append(f" Citations: {', '.join(r.citations)}")
lines.append("")
lines.append("-" * 72)
lines.append("")
lines.append("REMINDER: This audit applies rule-based triage to a 3-dimensional matrix. Always engage")
lines.append("qualified data privacy / AI counsel for binding decisions.")
return "\n".join(lines)
def _wrap(text: str, indent: int, width: int = 66) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="Audit data sources for AI training eligibility (origin × class × use-case matrix).",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to sources JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
payload = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
payload = SAMPLE
source = "<embedded sample: 7 mixed sources>"
results = audit(payload)
if args.output == "json":
print(json.dumps({
"source": source,
"count": len(results),
"verdict_counts": {
"NO-GO": sum(1 for r in results if r.verdict == "NO-GO"),
"MITIGATE": sum(1 for r in results if r.verdict == "MITIGATE"),
"GO": sum(1 for r in results if r.verdict == "GO"),
},
"results": [asdict(r) for r in results],
}, indent=2))
else:
print(render_text(results, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/data_asset_valuator.py
#!/usr/bin/env python3
"""data_asset_valuator.py — Value a B2B customer data corpus + productization viability.
Stdlib-only. Takes a corpus profile and computes:
- Strategic value score (0-10)
- Defensibility moat strength (NONE / WEAK / MEDIUM / STRONG)
- M&A multiplier (ARR uplift range in strategic-buyer scenarios)
- Productization paths (benchmark / embedding / direct license) with risk profile
- Contractual constraint impact (% of corpus blocked from productization)
Input schema (JSON):
{
"data_type": "sales-engagement", // descriptive
"customer_count": 380,
"time_history_years": 2.3,
"exclusivity": "high", // none | low | medium | high
"freshness": "real-time", // batch-daily | batch-weekly | near-real-time | real-time
"msa_carveouts_count": 47, // # of customers with data-use carve-outs blocking productization
"anonymization_audit_passed": false, // k-anonymity >=5 confirmed
"company_arr_m": 12, // company ARR in millions for M&A multiplier math
"regulated_data_present": false
}
Usage:
python data_asset_valuator.py # uses embedded B2B sample
python data_asset_valuator.py path/to/corpus.json
python data_asset_valuator.py corpus.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"data_type": "Sales engagement logs (email, calls, meetings)",
"customer_count": 380,
"time_history_years": 2.3,
"exclusivity": "high",
"freshness": "real-time",
"msa_carveouts_count": 47,
"anonymization_audit_passed": False,
"company_arr_m": 12,
"regulated_data_present": False,
}
EXCLUSIVITY_SCORE = {"none": 0, "low": 2, "medium": 5, "high": 9}
FRESHNESS_SCORE = {"batch-weekly": 2, "batch-daily": 5, "near-real-time": 7, "real-time": 9}
def strategic_value(profile: Dict[str, Any]) -> Dict[str, Any]:
"""Computes strategic value score and moat strength."""
customers = profile.get("customer_count", 0)
history = profile.get("time_history_years", 0)
excl = profile.get("exclusivity", "none")
fresh = profile.get("freshness", "batch-weekly")
excl_score = EXCLUSIVITY_SCORE.get(excl, 0)
fresh_score = FRESHNESS_SCORE.get(fresh, 0)
# Customer cohort breadth
if customers >= 500:
cohort_score = 10
elif customers >= 200:
cohort_score = 8
elif customers >= 100:
cohort_score = 6
elif customers >= 50:
cohort_score = 4
else:
cohort_score = 2
# Time history depth
if history >= 5:
history_score = 10
elif history >= 3:
history_score = 8
elif history >= 2:
history_score = 6
elif history >= 1:
history_score = 4
else:
history_score = 2
# Composite
composite = (excl_score * 2 + fresh_score + cohort_score + history_score) / 5
composite = round(composite, 1)
# Moat strength derived from exclusivity + cohort
if excl_score >= 8 and cohort_score >= 8:
moat = "STRONG"
moat_explain = "Exclusivity + breadth means replicating requires 2+ years of customer cohort acquisition."
elif excl_score >= 5 and cohort_score >= 6:
moat = "MEDIUM"
moat_explain = "Defensible but a well-funded competitor with 18-24 months can match."
elif excl_score >= 2:
moat = "WEAK"
moat_explain = "Some unique characteristics but largely replicable from public or commercially-available sources."
else:
moat = "NONE"
moat_explain = "Not a moat — same data is available elsewhere."
return {
"composite_score": composite,
"max_score": 10.0,
"components": {
"exclusivity": excl_score,
"freshness": fresh_score,
"cohort_breadth": cohort_score,
"history_depth": history_score,
},
"moat_strength": moat,
"moat_explanation": moat_explain,
}
def ma_multiplier(profile: Dict[str, Any], strategic: Dict[str, Any]) -> Dict[str, Any]:
"""Computes M&A multiplier range based on moat + corpus characteristics."""
moat = strategic["moat_strength"]
arr = profile.get("company_arr_m", 0)
carveouts = profile.get("msa_carveouts_count", 0)
customers = profile.get("customer_count", 1)
carveout_pct = (carveouts / customers * 100) if customers else 0
# Base multiplier by moat
base = {
"STRONG": (1.4, 1.7),
"MEDIUM": (1.15, 1.35),
"WEAK": (1.0, 1.1),
"NONE": (1.0, 1.0),
}
low, high = base.get(moat, (1.0, 1.0))
# Penalty for high carve-out %
if carveout_pct > 25:
low *= 0.85
high *= 0.85
carveout_note = f"{carveout_pct:.1f}% carve-out rate reduces multiplier ~15% (data is partially un-productizable)."
elif carveout_pct > 10:
low *= 0.95
high *= 0.95
carveout_note = f"{carveout_pct:.1f}% carve-out rate reduces multiplier ~5%."
else:
carveout_note = f"{carveout_pct:.1f}% carve-out rate — within tolerable range, no material multiplier impact."
low_arr = round(arr * low, 1) if arr else None
high_arr = round(arr * high, 1) if arr else None
return {
"multiplier_low": round(low, 2),
"multiplier_high": round(high, 2),
"carveout_pct": round(carveout_pct, 1),
"carveout_note": carveout_note,
"valuation_low_m": low_arr,
"valuation_high_m": high_arr,
"valuation_note": (
f"Strategic-buyer scenario: ARR arrM × ({low:.2f} - {high:.2f}) = low_arrM - high_arrM ARR-equivalent."
if arr else "Provide company_arr_m to compute valuation range."
),
}
def productization_paths(profile: Dict[str, Any], strategic: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Returns ranked productization paths with risk and viability."""
customers = profile.get("customer_count", 0)
carveouts = profile.get("msa_carveouts_count", 0)
carveout_pct = (carveouts / customers * 100) if customers else 0
anon_passed = profile.get("anonymization_audit_passed", False)
regulated = profile.get("regulated_data_present", False)
moat = strategic["moat_strength"]
paths = []
# Path 1: Industry benchmark report
benchmark_risk = "LOW"
benchmark_blockers = []
if not anon_passed:
benchmark_blockers.append("Anonymization audit (k-anonymity ≥ 5) required before publication")
if regulated:
benchmark_risk = "MEDIUM"
benchmark_blockers.append("Regulated data present — additional compliance review required")
paths.append({
"path": "Industry benchmark report (anonymized aggregates)",
"risk": benchmark_risk,
"revenue_potential": "Low ($50K-$500K/yr) but high credibility lift",
"viability": "HIGH" if not regulated else "MEDIUM",
"blockers": benchmark_blockers or ["No structural blockers"],
"first_step": (
"Run anonymization audit on top-3 metrics; draft quarterly benchmark report; "
"send to customers as opt-in value-add before public release."
),
})
# Path 2: Anonymized embedding endpoint
embed_risk = "MEDIUM"
embed_blockers = []
if not anon_passed:
embed_blockers.append("Anonymization audit required; embeddings can leak training data")
if carveout_pct > 0:
embed_blockers.append(
f"{int(carveouts)} customers have MSA carve-outs blocking productized use of their data"
)
if regulated:
embed_risk = "HIGH"
embed_blockers.append("Regulated data present — embeddings may retain re-identifiable signal")
paths.append({
"path": "Anonymized embedding endpoint (AI features for customers)",
"risk": embed_risk,
"revenue_potential": "Medium ($500K-$3M/yr) as platform feature OR add-on",
"viability": "HIGH" if moat in ("STRONG", "MEDIUM") and not regulated else "MEDIUM",
"blockers": embed_blockers,
"first_step": (
"Pilot embedding endpoint with 3 design-partner customers; memorization tests; "
"DPA addendum covering training-data flow."
),
})
# Path 3: Direct data licensing
license_risk = "HIGH"
license_blockers = []
if carveout_pct > 10:
license_blockers.append(
f"{carveout_pct:.1f}% of customers ({int(carveouts)}) have MSA carve-outs — direct licensing is "
"legally infeasible without re-papering or carve-out-excluded dataset"
)
license_blockers.append("Requires GDPR Art. 26 joint-controller analysis if EU customers present")
if regulated:
license_blockers.append("Regulated data licensing requires framework-specific consent + DPA")
paths.append({
"path": "Direct data licensing (to AI labs, data brokers, or industry players)",
"risk": license_risk,
"revenue_potential": "High ($2M-$20M/yr) at scale but high customer-trust cost",
"viability": "LOW" if carveout_pct > 10 or regulated else "MEDIUM",
"blockers": license_blockers,
"first_step": (
"First decide if customer trust impact is acceptable. If yes: re-paper 47 carve-out customers "
"OR build carve-out-excluded dataset; engage data broker counsel; draft customer comms plan."
),
})
return paths
def recommend_path(paths: List[Dict[str, Any]]) -> str:
"""Picks the highest-viability lowest-risk path as the recommended starting point."""
# Score: viability rank * 10 + (4 - risk_rank)
viability_rank = {"HIGH": 3, "MEDIUM": 2, "LOW": 1}
risk_rank = {"LOW": 3, "MEDIUM": 2, "HIGH": 1}
scored = [
(viability_rank.get(p["viability"], 0) * 10 + risk_rank.get(p["risk"], 0), p)
for p in paths
]
scored.sort(key=lambda x: -x[0])
return scored[0][1]["path"]
def analyze(profile: Dict[str, Any]) -> Dict[str, Any]:
strategic = strategic_value(profile)
ma = ma_multiplier(profile, strategic)
paths = productization_paths(profile, strategic)
recommended = recommend_path(paths)
return {
"strategic_value": strategic,
"ma_multiplier": ma,
"productization_paths": paths,
"recommended_starting_path": recommended,
}
def render_text(result: Dict[str, Any], profile: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("DATA ASSET VALUATION")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Corpus: {profile.get('data_type')}")
lines.append(f" Customers: {profile.get('customer_count')} | History: {profile.get('time_history_years')} years")
lines.append(f" Exclusivity: {profile.get('exclusivity')} | Freshness: {profile.get('freshness')}")
lines.append(f" MSA carve-outs: {profile.get('msa_carveouts_count')} customer(s)")
lines.append(f" Anonymization audit passed: {profile.get('anonymization_audit_passed')}")
lines.append(f" Regulated data present: {profile.get('regulated_data_present')}")
lines.append("")
lines.append("-" * 72)
sv = result["strategic_value"]
lines.append(f"STRATEGIC VALUE: {sv['composite_score']} / {sv['max_score']}")
lines.append(" Components:")
for k, v in sv["components"].items():
lines.append(f" {k:<20} {v}/10")
lines.append(f" Moat strength: {sv['moat_strength']}")
for line in _wrap(f" {sv['moat_explanation']}", 2):
lines.append(line)
lines.append("")
lines.append("-" * 72)
ma = result["ma_multiplier"]
lines.append(f"M&A MULTIPLIER (strategic-buyer scenario):")
lines.append(f" Range: {ma['multiplier_low']}x – {ma['multiplier_high']}x ARR")
if ma.get("valuation_low_m") is not None:
lines.append(f" Valuation impact: ma['valuation_low_m']M – ma['valuation_high_m']M ARR-equivalent")
for line in _wrap(f" {ma['carveout_note']}", 2):
lines.append(line)
lines.append("")
lines.append("-" * 72)
lines.append("PRODUCTIZATION PATHS:")
lines.append("")
for i, p in enumerate(result["productization_paths"], 1):
lines.append(f" [{i}] {p['path']}")
lines.append(f" Risk: {p['risk']} | Viability: {p['viability']} | Revenue: {p['revenue_potential']}")
lines.append(f" Blockers:")
for b in p["blockers"]:
lines.append(f" - {b}")
lines.append(f" First step:")
for line in _wrap(p["first_step"], 8):
lines.append(line)
lines.append("")
lines.append("-" * 72)
lines.append(f"RECOMMENDED STARTING PATH: {result['recommended_starting_path']}")
lines.append("")
lines.append("REMINDER: This valuation is a triage. Any actual productization, licensing, or M&A use")
lines.append("requires legal + data privacy review. Customer-trust impact is often the binding constraint,")
lines.append("not legal feasibility.")
return "\n".join(lines)
def _wrap(text: str, indent: int, width: int = 70) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="Value a B2B customer data corpus + productization paths.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to corpus JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: B2B SaaS sales engagement, 380 customers, 47 carve-outs>"
result = analyze(profile)
if args.output == "json":
print(json.dumps({"source": source, "profile": profile, **result}, indent=2))
else:
print(render_text(result, profile, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/data_product_strategy_picker.py
#!/usr/bin/env python3
"""data_product_strategy_picker.py — Pick data architecture + build-vs-buy + sequencing.
Stdlib-only. Takes a company profile and outputs:
- Recommended architecture (warehouse / lakehouse / data mesh) with reasoning + kill criteria
- Build-vs-buy decision per layer (storage, ELT, modeling, BI, feature store, ML platform)
- 12-month sequencing roadmap
The recommendation is deterministic, derived from the profile, not pattern-matched.
Input schema (JSON):
{
"stage": "series-a", // seed | series-a | series-b | growth | late-stage
"data_team_size": 3,
"internal_consumers": 8, // distinct people/teams consuming data weekly
"data_volume_tb": 4.5,
"ml_models_in_prod": 1,
"company_type": "b2b-saas", // b2b-saas | b2c-saas | consumer | marketplace | enterprise
"has_data_culture": false, // federated ownership culture in place? (mesh prerequisite)
"near_term_priorities": [
"self-serve-bi",
"improve-pipeline-reliability"
]
}
Usage:
python data_product_strategy_picker.py # uses embedded Series A SaaS
python data_product_strategy_picker.py path/to/profile.json
python data_product_strategy_picker.py profile.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List, Tuple
SAMPLE: Dict[str, Any] = {
"stage": "series-a",
"data_team_size": 3,
"internal_consumers": 8,
"data_volume_tb": 4.5,
"ml_models_in_prod": 1,
"company_type": "b2b-saas",
"has_data_culture": False,
"near_term_priorities": ["self-serve-bi", "improve-pipeline-reliability"],
}
def pick_architecture(profile: Dict[str, Any]) -> Tuple[str, str, List[str]]:
"""Returns (architecture, reasoning, kill_criteria)."""
consumers = profile.get("internal_consumers", 0)
volume = profile.get("data_volume_tb", 0)
ml_models = profile.get("ml_models_in_prod", 0)
culture = profile.get("has_data_culture", False)
stage = profile.get("stage", "")
# Data mesh: requires 25+ consumers across 4+ domains AND federated culture
if consumers >= 25 and culture and stage in ("growth", "late-stage"):
return (
"DATA MESH",
f"{consumers} data consumers across enough domains to justify federated ownership; "
"stated data-culture maturity supports the operational overhead.",
[
"Stop and revert if 6 months in: producing teams haven't adopted ownership (typical failure mode)",
"Stop if: central data platform team is still doing >50% of data product work",
"Stop if: domain teams complain about platform onboarding (signals platform isn't truly self-serve)",
],
)
# Mesh ambition without prerequisites
if consumers >= 25 and not culture:
return (
"LAKEHOUSE (defer mesh)",
f"{consumers} consumers is mesh-sized BUT no federated ownership culture in place; mesh "
"without culture fails. Run lakehouse with hub-and-spoke until ownership culture matures.",
[
"Revisit mesh in 18 months once 3+ domain teams own their own data products",
"Stop hub-and-spoke if central team is bottleneck > 60% of requests",
],
)
# Lakehouse: 5+ consumers OR ML workloads OR >2TB
if consumers >= 5 or ml_models >= 1 or volume >= 2:
return (
"LAKEHOUSE",
(
f"{consumers} data consumer(s), {ml_models} ML model(s) in prod, {volume}TB. "
"Pure warehouse is too rigid for ML; pure data lake too unstructured for BI. "
"Lakehouse (warehouse + object storage with table format like Iceberg/Delta) "
"covers both with one substrate."
),
[
"Downgrade to warehouse-only if ML models retired and data shrinks below 2TB",
"Upgrade to mesh only if 25+ consumers AND federated culture",
"Stop investment if vendor lock-in becomes unacceptable (lakehouse table formats mitigate this)",
],
)
# Warehouse only
return (
"WAREHOUSE ONLY",
(
f"{consumers} consumer(s), {volume}TB, {ml_models} ML model(s). Sub-scale for lakehouse "
"complexity. Single warehouse (Snowflake / BigQuery / Postgres) + dbt is the simplest viable "
"stack at this stage."
),
[
"Upgrade to lakehouse when ANY of: 5+ consumers, 2TB+ data, 1+ ML model in prod",
"Stop investment in custom modeling if SaaS BI vendor solves it (avoid premature dbt complexity)",
],
)
def build_vs_buy(profile: Dict[str, Any], architecture: str) -> List[Dict[str, str]]:
"""Returns build-vs-buy decision per layer."""
consumers = profile.get("internal_consumers", 0)
ml_models = profile.get("ml_models_in_prod", 0)
company_type = profile.get("company_type", "")
decisions = []
# Storage / warehouse
decisions.append({
"layer": "Storage / Warehouse",
"decision": "BUY",
"vendor_suggestion": "Snowflake / BigQuery / Databricks (lakehouse) or Postgres (warehouse-only)",
"rationale": "Storage is commodity. Building distributed storage is a 50-engineer-year investment with no business return unless you are a data-infra company.",
})
# ELT / ingest
decisions.append({
"layer": "ELT / Ingest",
"decision": "BUY",
"vendor_suggestion": "Fivetran / Airbyte / Stitch",
"rationale": "Connector maintenance is a moving target (200+ source APIs). Build only if your source isn't supported and is critical (then contribute upstream).",
})
# Modeling
decisions.append({
"layer": "Modeling / Transformations",
"decision": "BUILD",
"vendor_suggestion": "dbt + your domain logic (dbt itself is open source)",
"rationale": "This is your IP. Your domain logic encodes how the business actually works — vendors cannot supply it.",
})
# BI
if consumers < 100:
decisions.append({
"layer": "BI / Dashboards",
"decision": "BUY",
"vendor_suggestion": "Metabase (cheap) / Looker (enterprise) / Mode (analyst-friendly) / Hex (notebooks+BI)",
"rationale": f"At {consumers} consumers, building BI is a distraction. SaaS BI is mature; pick one that matches your analyst skillset.",
})
else:
decisions.append({
"layer": "BI / Dashboards",
"decision": "BUY + consider embedded for customer-facing analytics",
"vendor_suggestion": "Looker / Sigma + (Cube.dev or Embeddable) for customer-facing",
"rationale": f"At {consumers} consumers, BI is critical. If you're a B2B SaaS with customer-facing analytics, embedded BI is a real build-vs-buy decision; usually still buy.",
})
# Feature store
if ml_models < 3:
decisions.append({
"layer": "Feature Store",
"decision": "DEFER",
"vendor_suggestion": "(none yet — use dbt + simple feature tables)",
"rationale": f"{ml_models} model(s) in prod. Feature stores pay off at 3+ models sharing features. Premature investment is a maintenance burden.",
})
else:
decisions.append({
"layer": "Feature Store",
"decision": "BUY (Tecton / Hopsworks) or BUILD (Feast)",
"vendor_suggestion": "Tecton (managed) or Feast (open source)",
"rationale": f"{ml_models} models is the threshold where feature reuse + governance matter more than simplicity.",
})
# ML platform
if ml_models < 5:
decisions.append({
"layer": "ML Platform",
"decision": "DEFER",
"vendor_suggestion": "(none yet — use notebooks + scheduled training jobs)",
"rationale": f"{ml_models} models. ML platforms (Databricks ML, Vertex AI, SageMaker) make sense at 5+ models with active retraining; before that, the platform overhead exceeds the value.",
})
else:
decisions.append({
"layer": "ML Platform",
"decision": "BUY",
"vendor_suggestion": "Databricks ML / Vertex AI / SageMaker",
"rationale": f"{ml_models} models with active retraining. Platform handles experiment tracking, deployment, monitoring — all of which become painful to build at this scale.",
})
return decisions
def sequence_roadmap(profile: Dict[str, Any], architecture: str) -> List[Dict[str, str]]:
"""Returns 4-quarter sequencing roadmap based on priorities + architecture."""
priorities = profile.get("near_term_priorities", [])
ml_models = profile.get("ml_models_in_prod", 0)
roadmap = []
# Q1: always reliability first if pipeline issues exist
if "improve-pipeline-reliability" in priorities or "reliability" in str(priorities):
roadmap.append({
"quarter": "Q1",
"focus": "Pipeline reliability",
"deliverables": "SLA on top-3 critical pipelines (freshness, completeness); on-call rotation; data quality tests in dbt",
})
else:
roadmap.append({
"quarter": "Q1",
"focus": "Foundation",
"deliverables": "Centralized ingest (Fivetran/Airbyte); dbt for top-5 marts; basic data quality tests",
})
# Q2
if "self-serve-bi" in priorities:
roadmap.append({
"quarter": "Q2",
"focus": "Self-serve BI",
"deliverables": "BI tool rollout to non-data teams; semantic layer (dbt metrics or LookML); training program",
})
else:
roadmap.append({
"quarter": "Q2",
"focus": "Coverage",
"deliverables": "Extend dbt to top-10 marts; document data lineage; add domain-specific data quality tests",
})
# Q3
if ml_models >= 1 or "ml" in str(priorities).lower():
roadmap.append({
"quarter": "Q3",
"focus": "ML enablement",
"deliverables": "First feature-store table for top-1 production model; experiment tracking (MLflow / W&B); model monitoring",
})
else:
roadmap.append({
"quarter": "Q3",
"focus": "Embed analysts",
"deliverables": "Embedded analysts in 2-3 functional teams; central team owns platform; SLAs renegotiated",
})
# Q4: evaluate + decide
roadmap.append({
"quarter": "Q4",
"focus": "Evaluate and decide",
"deliverables": "Re-run this picker with updated profile; decide on year-2 architecture (e.g., introduce feature store, evaluate mesh prereqs)",
})
return roadmap
def analyze(profile: Dict[str, Any]) -> Dict[str, Any]:
architecture, reasoning, kill_criteria = pick_architecture(profile)
decisions = build_vs_buy(profile, architecture)
roadmap = sequence_roadmap(profile, architecture)
return {
"architecture": architecture,
"reasoning": reasoning,
"kill_criteria": kill_criteria,
"build_vs_buy": decisions,
"roadmap_12mo": roadmap,
}
def render_text(result: Dict[str, Any], profile: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("DATA PRODUCT STRATEGY")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append("Profile:")
lines.append(f" Stage: {profile.get('stage')} | Team: {profile.get('data_team_size')} | Consumers: {profile.get('internal_consumers')}")
lines.append(f" Data volume: {profile.get('data_volume_tb')}TB | ML models in prod: {profile.get('ml_models_in_prod')}")
lines.append(f" Company type: {profile.get('company_type')} | Data culture in place: {profile.get('has_data_culture')}")
lines.append("")
lines.append("-" * 72)
lines.append(f"RECOMMENDED ARCHITECTURE: {result['architecture']}")
lines.append("")
lines.append("Reasoning:")
for line in _wrap(result["reasoning"], 2):
lines.append(line)
lines.append("")
lines.append("Kill criteria (when to abandon this choice):")
for k in result["kill_criteria"]:
lines.append(f" • {k}")
lines.append("")
lines.append("-" * 72)
lines.append("BUILD vs BUY (per layer):")
lines.append("")
for d in result["build_vs_buy"]:
lines.append(f" {d['layer']:<32} {d['decision']}")
lines.append(f" Vendor: {d['vendor_suggestion']}")
for line in _wrap(f"Rationale: {d['rationale']}", 4):
lines.append(line)
lines.append("")
lines.append("-" * 72)
lines.append("12-MONTH ROADMAP:")
lines.append("")
for r in result["roadmap_12mo"]:
lines.append(f" {r['quarter']}: {r['focus']}")
for line in _wrap(r["deliverables"], 6):
lines.append(line)
lines.append("")
lines.append("-" * 72)
lines.append("REMINDER: Re-run this picker quarterly with updated profile. Architecture is not a once-")
lines.append("and-done decision — kill criteria exist for a reason.")
return "\n".join(lines)
def _wrap(text: str, indent: int, width: int = 68) -> List[str]:
import textwrap
return textwrap.wrap(text, width=width, initial_indent=" " * indent, subsequent_indent=" " * indent) or [" " * indent + text]
def main() -> int:
parser = argparse.ArgumentParser(
description="Pick data architecture + build-vs-buy + sequencing roadmap from a company profile.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to profile JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: Series A B2B SaaS, 3-person data team>"
result = analyze(profile)
if args.output == "json":
print(json.dumps({"source": source, "profile": profile, **result}, indent=2))
else:
print(render_text(result, profile, source))
return 0
if __name__ == "__main__":
sys.exit(main())
Lớp điều phối C-suite: định tuyến câu hỏi đến đúng cố vấn, tổ chức họp HĐQT, tổng hợp kết quả và theo dõi quyết định.
--- name: "chief-of-staff" description: "C-suite orchestration layer. Routes founder questions to the right advisor role(s), triggers multi-role board meetings for complex decisions, synthesizes outputs, and tracks decisions. Every C-suite interaction starts here. Loads company context automatically." license: MIT metadata: version: 1.0.0 author: Alireza Rezvani category: c-level domain: orchestration updated: 2026-03-05 frameworks: routing-matrix, synthesis-framework, decision-log, board-protocol --- # Chief of Staff The orchestration layer between founder and C-suite. Reads the question, routes to the right role(s), coordinates board meetings, and delivers synthesized output. Loads company context for every interaction. ## Keywords chief of staff, orchestrator, routing, c-suite coordinator, board meeting, multi-agent, advisor coordination, decision log, synthesis --- ## Session Protocol (Every Interaction) 1. Load company context via context-engine skill 2. Score decision complexity 3. Route to role(s) or trigger board meeting 4. Synthesize output 5. Log decision if reached --- ## Invocation Syntax ``` [INVOKE:role|question] ``` Examples: ``` [INVOKE:cfo|What's the right runway target given our growth rate?] [INVOKE:board|Should we raise a bridge or cut to profitability?] ``` ### Loop Prevention Rules (CRITICAL) 1. **Chief of Staff cannot invoke itself.** 2. **Maximum depth: 2.** Chief of Staff → Role → stop. 3. **Circular blocking.** A→B→A is blocked. Log it. 4. **Board = depth 1.** Roles at board meeting do not invoke each other. If loop detected: return to founder with "The advisors are deadlocked. Here's where they disagree: [summary]." --- ## Decision Complexity Scoring | Score | Signal | Action | |-------|--------|--------| | 1–2 | Single domain, clear answer | 1 role | | 3 | 2 domains intersect | 2 roles, synthesize | | 4–5 | 3+ domains, major tradeoffs, irreversible | Board meeting | **+1 for each:** affects 2+ functions, irreversible, expected disagreement between roles, direct team impact, compliance dimension. --- ## Routing Matrix (Summary) Full rules in `references/routing-matrix.md`. | Topic | Primary | Secondary | |-------|---------|-----------| | Fundraising, burn, financial model | CFO | CEO | | Hiring, firing, culture, performance | CHRO | COO | | Product roadmap, prioritization | CPO | CTO | | Architecture, tech debt | CTO | CPO | | Revenue, sales, GTM, pricing | CRO | CFO | | Process, OKRs, execution | COO | CFO | | Security, compliance, risk | CISO | COO | | Company direction, investor relations | CEO | Board | | Market strategy, positioning | CMO | CRO | | M&A, pivots | CEO | Board | --- ## Board Meeting Protocol **Trigger:** Score ≥ 4, or multi-function irreversible decision. ``` BOARD MEETING: [Topic] Attendees: [Roles] Agenda: [2–3 specific questions] [INVOKE:role1|agenda question] [INVOKE:role2|agenda question] [INVOKE:role3|agenda question] [Chief of Staff synthesis] ``` **Rules:** Max 5 roles. Each role one turn, no back-and-forth. Chief of Staff synthesizes. Conflicts surfaced, not resolved — founder decides. --- ## Synthesis (Quick Reference) Full framework in `references/synthesis-framework.md`. 1. **Extract themes** — what 2+ roles agree on independently 2. **Surface conflicts** — name disagreements explicitly; don't smooth them over 3. **Action items** — specific, owned, time-bound (max 5) 4. **One decision point** — the single thing needing founder judgment **Output format:** ``` ## What We Agree On [2–3 consensus themes] ## The Disagreement [Named conflict + each side's reasoning + what it's really about] ## Recommended Actions 1. [Action] — [Owner] — [Timeline] ... ## Your Decision Point [One question. Two options with trade-offs. No recommendation — just clarity.] ``` --- ## Decision Log Track decisions to `~/.claude/decision-log.md`. ``` ## Decision: [Name] Date: [YYYY-MM-DD] Question: [Original question] Decided: [What was decided] Owner: [Who executes] Review: [When to check back] ``` At session start: if a review date has passed, flag it: *"You decided [X] on [date]. Worth a check-in?"* --- ## Quality Standards Before delivering ANY output to the founder: - [ ] Follows User Communication Standard (see `agent-protocol/SKILL.md`) - [ ] Bottom line is first — no preamble, no process narration - [ ] Company context loaded (not generic advice) - [ ] Every finding has WHAT + WHY + HOW - [ ] Actions have owners and deadlines (no "we should consider") - [ ] Decisions framed as options with trade-offs and recommendation - [ ] Conflicts named, not smoothed - [ ] Risks are concrete (if X → Y happens, costs $Z) - [ ] No loops occurred - [ ] Max 5 bullets per section — overflow to reference --- ## Ecosystem Awareness The Chief of Staff routes to **28 skills total**: - **10 C-suite roles** — CEO, CTO, COO, CPO, CMO, CFO, CRO, CISO, CHRO, Executive Mentor - **6 orchestration skills** — cs-onboard, context-engine, board-meeting, decision-logger, agent-protocol - **6 cross-cutting skills** — board-deck-builder, scenario-war-room, competitive-intel, org-health-diagnostic, ma-playbook, intl-expansion - **6 culture & collaboration skills** — culture-architect, company-os, founder-coach, strategic-alignment, change-management, internal-narrative See `references/routing-matrix.md` for complete trigger mapping. ## References - `references/routing-matrix.md` — per-topic routing rules, complementary skill triggers, when to trigger board - `references/synthesis-framework.md` — full synthesis process, conflict types, output format FILE:references/routing-matrix.md # Routing Matrix Detailed routing rules for the Chief of Staff. When a founder asks a question, find the best match in this matrix, then apply the scoring rules to determine single-role, multi-role, or board meeting. --- ## Routing by Domain ### Finance & Capital | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | How much runway do we have? | CFO | — | 1 | | Should we raise now or later? | CFO | CEO | 3 | | What's our burn multiple? | CFO | COO | 2 | | Should we raise a bridge or cut costs? | CFO | CEO, COO | 5 | | What's the right pricing model? | CFO | CRO, CPO | 4 | | Should we hire or extend runway? | CFO | CHRO, COO | 4 | | What terms should we accept for this round? | CFO | CEO | 3 | | How do we model the next 18 months? | CFO | COO | 2 | ### People & Culture | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | Should I let this person go? | CHRO | COO | 2 | | How do I structure comp for the team? | CHRO | CFO | 3 | | We have a culture problem — what do we do? | CHRO | CEO | 3 | | A leader on my team isn't working — now what? | CHRO | COO | 2 | | How do I hire fast without breaking culture? | CHRO | COO | 3 | | Two co-founders are in conflict | CHRO | CEO | 4 | | How do we retain our best people? | CHRO | CFO | 2 | | What does a good performance management process look like? | CHRO | COO | 2 | ### Product | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | What should we build next? | CPO | CTO | 2 | | Should we kill this feature? | CPO | CTO, CRO | 3 | | How do we prioritize the roadmap? | CPO | CTO, COO | 3 | | Are we pre-PMF or post-PMF? | CPO | CRO, CEO | 4 | | Should we build vs buy? | CPO | CTO, CFO | 4 | | How do we handle technical debt vs new features? | CTO | CPO | 3 | | What's our product strategy for next year? | CPO | CEO, CRO | 4 | ### Technology & Engineering | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | What architecture should we use? | CTO | CPO | 1 | | How do we scale the system to 10x traffic? | CTO | COO | 2 | | We have a security incident — what now? | CISO | CTO, COO | 5 | | Should we migrate to microservices? | CTO | COO, CFO | 4 | | How do I grow the engineering team? | CTO | CHRO, CFO | 3 | | Our engineering velocity is dropping — why? | CTO | COO | 2 | | What's our DevOps maturity? | CTO | COO | 1 | | How do we handle a compliance audit on our tech? | CISO | CTO | 3 | ### Sales & Revenue | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | Why aren't we closing deals? | CRO | CPO | 2 | | How do we build a sales process from scratch? | CRO | COO | 2 | | What's the right GTM for this market? | CRO | CMO, CEO | 4 | | Our churn is too high — root cause? | CRO | CPO, CHRO | 3 | | Should we go enterprise or stay SMB? | CRO | CPO, CFO | 4 | | How do we expand into a new market? | CRO | CMO, CEO, CFO | 5 | | What's our ideal customer profile? | CRO | CPO, CMO | 3 | | Pipeline is dry — what do we do? | CRO | CMO | 2 | ### Operations & Execution | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | Why do things keep breaking? | COO | CTO | 2 | | How do we set up OKRs? | COO | CEO | 2 | | Our meetings are useless — fix it | COO | — | 1 | | How do we scale operations without hiring? | COO | CTO, CFO | 3 | | There's a recurring bottleneck — how to fix it? | COO | CTO | 2 | | We need a cross-team process for X | COO | Relevant dept head | 2 | | How do we improve decision speed? | COO | CEO | 3 | ### Marketing & Brand | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | How do we position against Competitor X? | CMO | CRO | 2 | | What channels should we invest in? | CMO | CRO, CFO | 3 | | Our brand isn't resonating — why? | CMO | CPO, CRO | 3 | | How do we build a content strategy? | CMO | CRO | 2 | | What's our marketing budget allocation? | CMO | CFO, CRO | 3 | ### Security & Compliance | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | How do we pass an ISO 27001 audit? | CISO | COO | 2 | | We had a data breach — what now? | CISO | CTO, CEO, COO | 5 | | How do we handle GDPR compliance? | CISO | CTO | 2 | | What's our security posture? | CISO | CTO | 1 | | A regulator is asking questions | CISO | CEO, COO | 4 | ### Strategic Direction | Question type | Primary | Secondary | Score | |--------------|---------|-----------|-------| | Should we pivot? | CEO | Board meeting | 5 | | Are we building the right company? | CEO | Board meeting | 5 | | How do we handle an acquisition offer? | CEO | CFO, Board meeting | 5 | | What's the 3-year strategy? | CEO | All C-suite, board | 5 | | Should we enter a new vertical? | CEO | CRO, CFO, CPO | 4 | --- ## When to Invoke Multiple Roles Invoke 2 roles when: - The question sits at the boundary of two domains - One role's answer creates a constraint the other needs to know about - The founder explicitly wants two perspectives Invoke 3+ roles (board) when: - The question involves irreversible resource commitment - There's a known tension between functions (e.g., product vs revenue, speed vs quality) - The answer will change how multiple teams operate - It's a company-direction question, not an operational one --- ## When NOT to Invoke Multiple Roles Don't multi-invoke when: - The answer is technical and one role clearly owns it - The founder just needs a framework, not a decision - Invoking more roles would add noise without adding signal - Time is short and a directional answer beats a comprehensive one --- ## Escalation Criteria → Board Meeting Automatically escalate to board meeting when any of these apply: 1. **Irreversibility:** The decision is hard or impossible to reverse (layoffs, pivots, major contracts, fundraising terms) 2. **Cross-functional resource impact:** The decision changes budget, headcount, or priorities for 2+ teams 3. **Founder blind spot risk:** The topic is in an area where the founder's archetype creates a known gap (e.g., technical founder on GTM) 4. **Disagreement expected:** The domains involved are known to have competing incentives (CFO vs CRO on pricing, CTO vs CPO on tech debt) 5. **Explicit request:** Founder says "what does the team think" or "I want multiple perspectives" 6. **Score ≥ 4** --- ## Role Registry | Role | File | Domain | |------|------|--------| | CEO | ceo-advisor | Strategy, culture, investor relations | | CFO | cfo-advisor | Finance, capital, unit economics | | COO | coo-advisor | Operations, OKRs, scaling | | CTO | cto-advisor | Engineering, architecture, tech strategy | | CPO | cpo-advisor | Product, roadmap, UX | | CRO | cro-advisor | Revenue, sales, GTM | | CMO | cmo-advisor | Marketing, brand, positioning | | CHRO | chro-advisor | People, culture, hiring | | CISO | ciso-advisor | Security, compliance, risk | **If a role file doesn't exist:** Note the gap. Answer from first principles with domain expertise. Log that the role is missing. --- ## Complementary Skills Registry These skills are invoked for specific cross-cutting needs, not for general domain questions. ### Orchestration & Infrastructure | Skill | Trigger | File | |-------|---------|------| | C-Suite Onboard | `/cs:setup`, first-time setup, "tell me about your company" | cs-onboard | | Context Engine | Auto-loaded; staleness check | context-engine | | Board Meeting | `/cs:board`, multi-role decisions, score ≥ 4 | board-meeting | | Decision Logger | After board meetings, `/cs:decisions`, `/cs:review` | decision-logger | | Agent Protocol | Inter-role invocations, loop detection | agent-protocol | ### Cross-Cutting Capabilities | Skill | Trigger | File | |-------|---------|------| | Board Deck Builder | "board deck", "investor update", "board presentation" | board-deck-builder | | Scenario War Room | "what if", multi-variable scenarios, stress test across functions | scenario-war-room | | Competitive Intelligence | "competitor", "competitive analysis", "battlecard", "who's winning" | competitive-intel | | Org Health Diagnostic | "how healthy are we", "org health", "company health check" | org-health-diagnostic | | M&A Playbook | "acquisition", "M&A", "due diligence", "being acquired" | ma-playbook | | International Expansion | "expand to", "new market", "international", "localization" | intl-expansion | ### Culture & Collaboration | Skill | Trigger | File | |-------|---------|------| | Culture Architect | "values", "culture", "mission", "vision", culture problems | culture-architect | | Company OS | "operating system", "EOS", "Scaling Up", "meeting cadence", "how do we run" | company-os | | Founder Coach | "delegation", "blind spots", "founder growth", "leadership style", burnout | founder-coach | | Strategic Alignment | "alignment", "silos", "teams not aligned", "strategy cascade" | strategic-alignment | | Change Management | "rolling out", "reorg", "change", "new process", "transition" | change-management | | Internal Narrative | "all-hands", "internal comms", "how do we tell", "narrative" | internal-narrative | ### Routing Priority 1. Check if it matches a **complementary skill trigger** → route there 2. Check if it matches a **single role domain** → route to that role 3. Check if it spans **multiple role domains** (score ≥ 3) → invoke multiple roles 4. Check if it meets **escalation criteria** (score ≥ 4 or irreversible) → trigger board meeting 5. If unclear → ask one clarifying question, then route FILE:references/synthesis-framework.md # Synthesis Framework How to turn multiple role outputs into a single, useful response for the founder. Synthesis is the highest-value function of the Chief of Staff — it's not about summarizing, it's about integrating. --- ## The Problem with Multi-Role Output Without synthesis, multiple advisors produce noise: - Overlapping advice - Contradictions without resolution - Action items from every role that compete for priority - Founder left to figure out what to do with it all Synthesis turns this into signal: one clear picture, explicit conflicts named, prioritized actions, one decision point. --- ## Phase 1: Collect and Read Before writing anything, read all role responses completely. Look for: **Consensus signals:** - Same recommendation from 2+ roles independently - Same risk identified from different angles - Same root cause named without coordination **Conflict signals:** - One role says X, another says not-X - Same data interpreted differently - Competing resource requests (CFO says cut costs, CRO says invest in sales) - Different time horizons (CTO wants to fix tech debt now, CPO wants to ship features now) **Gap signals:** - A critical dimension no role addressed - A risk nobody flagged - An assumption baked in that nobody questioned --- ## Phase 2: Extract Themes A theme is a finding that appears in 2+ role responses, even if framed differently. **How to identify:** 1. List every distinct point from every role response 2. Group points that are about the same underlying issue 3. Name the group with a clear, plain-language label 4. Note which roles contributed to it **Example:** > CFO: "The burn multiple is 3.2 — unsustainable without revenue acceleration." > CRO: "We need 3 more sales cycles to hit targets, minimum 90 days." > COO: "Three positions are open that will cost $40K/month when filled." > > Theme: **Cash position is tighter than the headline number suggests.** (CFO + CRO + COO) **Limit to 3 themes.** More than 3 means you're not synthesizing — you're listing. --- ## Phase 3: Surface Conflicts Name every conflict explicitly. Don't resolve it — present it. **Conflict types:** ### Resource conflict Two roles want the same budget, headcount, or time. > "CFO wants to delay the new hire until Q3. CHRO says the team is already at capacity and another quarter will cause attrition. Both are right from their domain." ### Priority conflict Two roles disagree on what's most important right now. > "CTO wants 6 weeks on infrastructure to prevent outages. CPO wants those same engineers on the new feature for the sales pipeline. This isn't a technical question — it's a risk tolerance question." ### Time horizon conflict Two roles are optimizing for different time frames. > "CRO is optimizing for this quarter's close rate. CMO is optimizing for brand that compounds over 18 months. Both strategies are valid. They require different budget allocations." ### Assumption conflict Two roles have incompatible assumptions baked in. > "CFO's model assumes 15% MoM growth. CRO says realistic growth is 8% given the sales cycle length. The financial model needs to be rebuilt on the CRO's number." **Present conflicts without picking sides.** The founder decides which trade-off to accept. --- ## Phase 4: Derive Action Items From the consensus themes and the non-conflicting role outputs, derive concrete actions. **Action item criteria:** - Specific (not "improve the process" — "map the QA process and find the bottleneck") - Owned (assign to a role or person) - Time-bound (this week / this quarter / before next board) - Consequence-linked (why does it matter if it slips) **Good example:** > **Action:** Build an updated 18-month financial model using CRO's 8% MoM growth assumption. > **Owner:** CFO > **By:** End of week > **Why it matters:** Current fundraising conversations are based on a model that's too optimistic. **Bad example:** > Review the financial model with the team. **Limit to 5 actions.** If there are more, prioritize by impact and flag the rest as backlog. --- ## Phase 5: Identify the Founder Decision Point Every board meeting ends with one question for the founder. Just one. **How to find it:** - It's usually the conflict that can't be resolved without a values choice - It's the question where both sides have a legitimate case - It's the thing none of the advisors can decide unilaterally **Frame it cleanly:** > "The C-suite is aligned on the actions above, but there's one thing that needs your call: [specific decision]. [Role A] recommends X because [reason]. [Role B] recommends Y because [reason]. This is ultimately a question of [underlying trade-off — growth vs profitability / speed vs stability / short-term vs long-term]." **Don't present multiple decision points.** Force the synthesis down to one. If there are genuinely two unrelated decisions, separate them into two outputs. --- ## Output Format ```markdown ## [Topic] — C-Suite Synthesis ### What We Agree On [Theme 1 with 1–2 sentences] [Theme 2 with 1–2 sentences] [Theme 3 with 1–2 sentences] ### The Disagreement [Name the conflict] [Role A position + reasoning] [Role B position + reasoning] [What the conflict is really about] ### Recommended Actions 1. **[Action]** — [Owner] — [Timeline] — [Why it matters] 2. **[Action]** — [Owner] — [Timeline] 3. **[Action]** — [Owner] — [Timeline] 4. **[Action]** — [Owner] — [Timeline] 5. **[Action]** — [Owner] — [Timeline] ### Your Decision Point [One question for the founder. Two options with their trade-offs. No recommendation — just clarity.] ``` --- ## Quality Standards for Synthesis Before delivering: **Compression test:** Could a founder read this in 3 minutes and know exactly what to do? If not, cut. **Honesty test:** Did you name the real conflicts, or smooth them over? Smoothed conflicts come back as surprises. **Specificity test:** Are the action items specific enough to act on, or are they goals masquerading as actions? **Decision point test:** Is there one clear thing for the founder to decide, or are you leaving them with a mess? **Context test:** Would this advice make sense for any company, or is it clearly calibrated to this company's stage, challenges, and founder? --- ## Common Synthesis Failures **The summary trap:** You summarize each role's output in sequence. This is not synthesis — it's transcription. Synthesis requires cutting. **The false consensus:** You say "the team agrees" when there's actually a meaningful conflict. Named conflicts are useful. Hidden conflicts are dangerous. **The advice avalanche:** 15 action items that no one can action. Cut to 5. If everything is priority, nothing is. **The unresolved conflict dump:** You present the conflict and then leave the founder to figure it out. Your job is to frame the choice cleanly, not to resolve it — but also not to dump it raw. **The context-free advice:** The synthesis sounds like it came from a textbook, not from someone who knows this company. If you can swap the company name and it still reads the same, it's not synthesized. --- ## When Synthesis Reveals Deadlock Sometimes roles genuinely can't align and the synthesis produces no clear direction. **Signs of deadlock:** - Every theme has a counter-theme - Every action has a conflict attached - The "decision point" is actually three decisions **What to do:** 1. Name the deadlock explicitly: *"The C-suite is genuinely split on this. Here's why."* 2. Present the two paths cleanly with consequences 3. Recommend a time-boxed experiment if possible: *"You don't have to decide between X and Y permanently. Run X for 30 days with a clear metric for success, then reassess."* 4. Flag it as a strategic question that may need external input (advisor, board, market data) Deadlock is honest. Fake consensus is not.
Phân tích và tối ưu vận hành TMĐT đa kênh: đơn hàng, tồn kho, sản phẩm và hiệu quả quảng cáo ROAS/CPO trên Shopee, TikTok Shop, website.
--- name: van-hanh-tmdt-da-kenh description: Phân tích và tối ưu vận hành thương mại điện tử đa kênh (Shopee, TikTok Shop, Website, Facebook), quản lý đơn hàng, tồn kho, sản phẩm và hiệu quả quảng cáo ROAS/CPO. Dùng khi nói "TMĐT", "vận hành sàn", "Shopee", "TikTok Shop", "đa kênh". --- # Vận hành thương mại điện tử đa kênh (E-Commerce Operations) ## Mục tiêu Phân tích và tối ưu vận hành TMĐT đa kênh — Shopee, TikTok Shop, Website, Facebook — với cơ cấu mỗi nhân sự phụ trách 1 kênh, đảm bảo hiệu suất đồng đều và phối hợp liên kênh hiệu quả. ## Bối cảnh Chargee - **Mô hình**: Phân phối hàng hóa trên sàn TMĐT - **Kênh**: Shopee / TikTok Shop / Website / Facebook - **Cơ cấu**: Mỗi người phụ trách 1 kênh → rủi ro siloed, thiếu phối hợp giữa các kênh - **Vai trò của bạn**: Chủ doanh nghiệp → cần nhìn tổng thể và phát hiện vấn đề từng kênh ## Khi nào dùng - Review hiệu suất định kỳ (tuần/tháng) từng kênh - Phát hiện kênh đang underperform cần can thiệp - Phân bổ lại ngân sách quảng cáo giữa các kênh - Phát sinh vấn đề tồn kho, logistics, hoặc đơn hàng - Ra quyết định về giá, khuyến mãi, hoặc listing sản phẩm mới ## Đầu vào cần cung cấp - **Kênh cần phân tích**: 1 kênh cụ thể hay toàn bộ - **Loại phân tích**: Hiệu suất / đơn hàng / sản phẩm / quảng cáo - **Dữ liệu hiện có**: Doanh thu, đơn hàng, ngân sách, tồn kho - **Kỳ phân tích**: Ngày / tuần / tháng - **Vấn đề đang gặp** (nếu có) ## Quy trình xử lý ### A. Hiệu suất kênh bán 1. Tổng hợp theo kênh: doanh thu, số đơn, AOV (giá trị đơn TB) 2. Tính conversion rate và traffic nguồn vào 3. So sánh kênh với kênh — kênh nào đang kéo, kênh nào đang kéo lùi 4. Xác định nguyên nhân: sản phẩm, giá, quảng cáo, hay vận hành 5. Đề xuất điều chỉnh ưu tiên theo kênh ### B. Vận hành đơn hàng 1. Tỷ lệ đơn thành công / hủy / hoàn — theo từng kênh 2. Thời gian xử lý đơn trung bình — có đang vượt SLA không 3. Xác định bottleneck: người xử lý, kho, đơn vị vận chuyển 4. Tồn kho: hàng nào sắp hết, hàng nào tồn quá lâu 5. Đề xuất điều chỉnh quy trình hoặc phân công ### C. Quản lý sản phẩm 1. Sản phẩm nào đang bán chạy / chậm theo từng kênh 2. Kiểm tra listing: hình ảnh, mô tả, từ khóa có tối ưu chưa 3. So sánh giá với đối thủ cùng kênh 4. Khuyến mãi hiện tại có phù hợp với biên lợi nhuận không 5. Đề xuất: sản phẩm nên đẩy, sản phẩm nên dừng, giá cần điều chỉnh ### D. Hiệu quả quảng cáo 1. Tổng hợp ngân sách và kết quả theo kênh 2. Tính ROAS, CPO, CPC theo từng kênh 3. Xác định kênh có ROI tốt nhất để tăng ngân sách 4. Xác định camp đang burn tiền không hiệu quả 5. Đề xuất phân bổ lại ngân sách tuần/tháng tới ## Tiêu chuẩn đầu ra | Loại phân tích | Định dạng | Nội dung bắt buộc | |---|---|---| | Hiệu suất kênh | Bảng so sánh đa kênh | Doanh thu, đơn, AOV, tăng trưởng | | Vận hành đơn | Bảng + danh sách vấn đề | Tỷ lệ thành công, bottleneck, đề xuất | | Sản phẩm | Danh sách ưu tiên | Top bán chạy, cần tối ưu, nên dừng | | Quảng cáo | Bảng ROAS/CPO theo kênh | Kênh hiệu quả, kênh cần cắt/điều chỉnh | ## Dashboard tổng hợp tuần (gợi ý) | Kênh | Doanh thu | Đơn | AOV | ROAS | Vấn đề nổi bật | |---|---|---|---|---|---| | Shopee | | | | | | | TikTok Shop | | | | | | | Website | | | | | | | Facebook | | | | | | | **Tổng** | | | | | | ## Rủi ro đặc thù cần theo dõi - **Siloed operation**: mỗi người 1 kênh → dễ mất đồng bộ giá, tồn kho, khuyến mãi giữa các kênh - **Phụ thuộc nhân sự**: 1 người nghỉ = 1 kênh tê liệt → cần SOP rõ ràng cho từng kênh - **Cạnh tranh chéo kênh**: cùng sản phẩm, giá khác nhau giữa các kênh gây mất niềm tin khách hàng ## Giả định luôn nêu rõ - Số liệu dựa trên dữ liệu bạn cung cấp — không tự bịa - Nếu thiếu số liệu một kênh: phân tích các kênh còn lại và nêu rõ kênh nào chưa có dữ liệu - Đề xuất mang tính tham khảo — quyết định cuối thuộc về bạn ## Tránh - Phân tích từng kênh riêng lẻ mà không nhìn tổng thể đa kênh - Đề xuất tăng ngân sách mà không kiểm tra biên lợi nhuận - Bỏ qua rủi ro tồn kho khi đẩy mạnh quảng cáo - Kết luận khi thiếu dữ liệu — phải nêu rõ giả định
Tạo pipeline CI/CD thực dụng từ tín hiệu công nghệ của dự án, gồm kiểm tra lặp lại và giai đoạn triển khai theo môi trường.
---
name: "ci-cd-pipeline-builder"
description: "Generate pragmatic CI/CD pipelines from detected project stack signals — fast baseline generation, repeatable checks, environment-aware deployment stages. Use when setting up CI for a new project, refactoring existing pipelines, or standardizing deployment workflows across multiple repos."
---
# CI/CD Pipeline Builder
**Tier:** POWERFUL
**Category:** Engineering
**Domain:** DevOps / Automation
## Overview
Use this skill to generate pragmatic CI/CD pipelines from detected project stack signals, not guesswork. It focuses on fast baseline generation, repeatable checks, and environment-aware deployment stages.
## Core Capabilities
- Detect language/runtime/tooling from repository files
- Recommend CI stages (`lint`, `test`, `build`, `deploy`)
- Generate GitHub Actions or GitLab CI starter pipelines
- Include caching and matrix strategy based on detected stack
- Emit machine-readable detection output for automation
- Keep pipeline logic aligned with project lockfiles and build commands
## When to Use
- Bootstrapping CI for a new repository
- Replacing brittle copied pipeline files
- Migrating between GitHub Actions and GitLab CI
- Auditing whether pipeline steps match actual stack
- Creating a reproducible baseline before custom hardening
## Key Workflows
### 1. Detect Stack
```bash
python3 scripts/stack_detector.py --repo . --format text
python3 scripts/stack_detector.py --repo . --format json > detected-stack.json
```
Supports input via stdin or `--input` file for offline analysis payloads.
### 2. Generate Pipeline From Detection
```bash
python3 scripts/pipeline_generator.py \
--input detected-stack.json \
--platform github \
--output .github/workflows/ci.yml \
--format text
```
Or end-to-end from repo directly:
```bash
python3 scripts/pipeline_generator.py --repo . --platform gitlab --output .gitlab-ci.yml
```
### 3. Validate Before Merge
1. Confirm commands exist in project (`test`, `lint`, `build`).
2. Run generated pipeline locally where possible.
3. Ensure required secrets/env vars are documented.
4. Keep deploy jobs gated by protected branches/environments.
### 4. Add Deployment Stages Safely
- Start with CI-only (`lint/test/build`).
- Add staging deploy with explicit environment context.
- Add production deploy with manual gate/approval.
- Keep rollout/rollback commands explicit and auditable.
## Script Interfaces
- `python3 scripts/stack_detector.py --help`
- Detects stack signals from repository files
- Reads optional JSON input from stdin/`--input`
- `python3 scripts/pipeline_generator.py --help`
- Generates GitHub/GitLab YAML from detection payload
- Writes to stdout or `--output`
## Common Pitfalls
1. Copying a Node pipeline into Python/Go repos
2. Enabling deploy jobs before stable tests
3. Forgetting dependency cache keys
4. Running expensive matrix builds for every trivial branch
5. Missing branch protections around prod deploy jobs
6. Hardcoding secrets in YAML instead of CI secret stores
## Best Practices
1. Detect stack first, then generate pipeline.
2. Keep generated baseline under version control.
3. Add one optimization at a time (cache, matrix, split jobs).
4. Require green CI before deployment jobs.
5. Use protected environments for production credentials.
6. Regenerate pipeline when stack changes significantly.
## References
- [references/github-actions-templates.md](references/github-actions-templates.md)
- [references/gitlab-ci-templates.md](references/gitlab-ci-templates.md)
- [references/deployment-gates.md](references/deployment-gates.md)
- [README.md](README.md)
## Detection Heuristics
The stack detector prioritizes deterministic file signals over heuristics:
- Lockfiles determine package manager preference
- Language manifests determine runtime families
- Script commands (if present) drive lint/test/build commands
- Missing scripts trigger conservative placeholder commands
## Generation Strategy
Start with a minimal, reliable pipeline:
1. Checkout and setup runtime
2. Install dependencies with cache strategy
3. Run lint, test, build in separate steps
4. Publish artifacts only after passing checks
Then layer advanced behavior (matrix builds, security scans, deploy gates).
## Platform Decision Notes
- GitHub Actions for tight GitHub ecosystem integration
- GitLab CI for integrated SCM + CI in self-hosted environments
- Keep one canonical pipeline source per repo to reduce drift
## Validation Checklist
1. Generated YAML parses successfully.
2. All referenced commands exist in the repo.
3. Cache strategy matches package manager.
4. Required secrets are documented, not embedded.
5. Branch/protected-environment rules match org policy.
## Scaling Guidance
- Split long jobs by stage when runtime exceeds 10 minutes.
- Introduce test matrix only when compatibility truly requires it.
- Separate deploy jobs from CI jobs to keep feedback fast.
- Track pipeline duration and flakiness as first-class metrics.
FILE:README.md
# CI/CD Pipeline Builder
Detects your repository stack and generates practical CI pipeline templates for GitHub Actions and GitLab CI. Designed as a fast baseline you can extend with deployment controls.
## Quick Start
```bash
# Detect stack
python3 scripts/stack_detector.py --repo . --format json > stack.json
# Generate GitHub Actions workflow
python3 scripts/pipeline_generator.py \
--input stack.json \
--platform github \
--output .github/workflows/ci.yml \
--format text
```
## Included Tools
- `scripts/stack_detector.py`: repository signal detection with JSON/text output
- `scripts/pipeline_generator.py`: generate GitHub/GitLab CI YAML from detection payload
## References
- `references/github-actions-templates.md`
- `references/gitlab-ci-templates.md`
- `references/deployment-gates.md`
## Installation
### Claude Code
```bash
cp -R engineering/ci-cd-pipeline-builder ~/.claude/skills/ci-cd-pipeline-builder
```
### OpenAI Codex
```bash
cp -R engineering/ci-cd-pipeline-builder ~/.codex/skills/ci-cd-pipeline-builder
```
### OpenClaw
```bash
cp -R engineering/ci-cd-pipeline-builder ~/.openclaw/skills/ci-cd-pipeline-builder
```
FILE:references/deployment-gates.md
# Deployment Gates
## Minimum Gate Policy
- `lint` must pass before `test`.
- `test` must pass before `build`.
- `build` artifact required for deploy jobs.
- Production deploy requires manual approval and protected branch.
## Environment Pattern
- `develop` -> auto deploy to staging
- `main` -> manual promote to production
## Rollback Requirement
Every deploy job should define a rollback command or procedure reference.
FILE:references/github-actions-templates.md
# GitHub Actions Templates
## Node.js Baseline
```yaml
name: Node CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
```
## Python Baseline
```yaml
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python3 -m pip install -U pip
- run: python3 -m pip install -r requirements.txt
- run: python3 -m pytest
```
FILE:references/gitlab-ci-templates.md
# GitLab CI Templates
## Node.js Baseline
```yaml
stages:
- lint
- test
- build
node_lint:
image: node:20
stage: lint
script:
- npm ci
- npm run lint
node_test:
image: node:20
stage: test
script:
- npm ci
- npm test
```
## Python Baseline
```yaml
stages:
- test
python_test:
image: python:3.12
stage: test
script:
- python3 -m pip install -U pip
- python3 -m pip install -r requirements.txt
- python3 -m pytest
```
FILE:scripts/pipeline_generator.py
#!/usr/bin/env python3
"""Generate CI pipeline YAML from detected stack data.
Input sources:
- --input stack report JSON file
- stdin stack report JSON
- --repo path (auto-detect stack)
Output:
- text/json summary
- pipeline YAML written via --output or printed to stdout
"""
import argparse
import json
import sys
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Any, Dict, List, Optional
class CLIError(Exception):
"""Raised for expected CLI failures."""
@dataclass
class PipelineSummary:
platform: str
output: str
stages: List[str]
uses_cache: bool
languages: List[str]
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Generate CI/CD pipeline YAML from detected stack.")
parser.add_argument("--input", help="Stack report JSON file. If omitted, can read stdin JSON.")
parser.add_argument("--repo", help="Repository path for auto-detection fallback.")
parser.add_argument("--platform", choices=["github", "gitlab"], required=True, help="Target CI platform.")
parser.add_argument("--output", help="Write YAML to this file; otherwise print to stdout.")
parser.add_argument("--format", choices=["text", "json"], default="text", help="Summary output format.")
return parser.parse_args()
def load_json_input(input_path: Optional[str]) -> Optional[Dict[str, Any]]:
if input_path:
try:
return json.loads(Path(input_path).read_text(encoding="utf-8"))
except Exception as exc:
raise CLIError(f"Failed reading --input: {exc}") from exc
if not sys.stdin.isatty():
raw = sys.stdin.read().strip()
if raw:
try:
return json.loads(raw)
except json.JSONDecodeError as exc:
raise CLIError(f"Invalid JSON from stdin: {exc}") from exc
return None
def detect_stack(repo: Path) -> Dict[str, Any]:
scripts = {}
pkg_file = repo / "package.json"
if pkg_file.exists():
try:
pkg = json.loads(pkg_file.read_text(encoding="utf-8"))
raw_scripts = pkg.get("scripts", {})
if isinstance(raw_scripts, dict):
scripts = raw_scripts
except Exception:
scripts = {}
languages: List[str] = []
if pkg_file.exists():
languages.append("node")
if (repo / "pyproject.toml").exists() or (repo / "requirements.txt").exists():
languages.append("python")
if (repo / "go.mod").exists():
languages.append("go")
return {
"languages": sorted(set(languages)),
"signals": {
"pnpm_lock": (repo / "pnpm-lock.yaml").exists(),
"yarn_lock": (repo / "yarn.lock").exists(),
"npm_lock": (repo / "package-lock.json").exists(),
"dockerfile": (repo / "Dockerfile").exists(),
},
"lint_commands": ["npm run lint"] if "lint" in scripts else [],
"test_commands": ["npm test"] if "test" in scripts else [],
"build_commands": ["npm run build"] if "build" in scripts else [],
}
def select_node_install(signals: Dict[str, Any]) -> str:
if signals.get("pnpm_lock"):
return "pnpm install --frozen-lockfile"
if signals.get("yarn_lock"):
return "yarn install --frozen-lockfile"
return "npm ci"
def github_yaml(stack: Dict[str, Any]) -> str:
langs = stack.get("languages", [])
signals = stack.get("signals", {})
lint_cmds = stack.get("lint_commands", []) or ["echo 'No lint command configured'"]
test_cmds = stack.get("test_commands", []) or ["echo 'No test command configured'"]
build_cmds = stack.get("build_commands", []) or ["echo 'No build command configured'"]
lines: List[str] = [
"name: CI",
"on:",
" push:",
" branches: [main, develop]",
" pull_request:",
" branches: [main, develop]",
"",
"jobs:",
]
if "node" in langs:
lines.extend(
[
" node-ci:",
" runs-on: ubuntu-latest",
" steps:",
" - uses: actions/checkout@v4",
" - uses: actions/setup-node@v4",
" with:",
" node-version: '20'",
" cache: 'npm'",
f" - run: {select_node_install(signals)}",
]
)
for cmd in lint_cmds + test_cmds + build_cmds:
lines.append(f" - run: {cmd}")
if "python" in langs:
lines.extend(
[
" python-ci:",
" runs-on: ubuntu-latest",
" steps:",
" - uses: actions/checkout@v4",
" - uses: actions/setup-python@v5",
" with:",
" python-version: '3.12'",
" - run: python3 -m pip install -U pip",
" - run: python3 -m pip install -r requirements.txt || true",
" - run: python3 -m pytest || true",
]
)
if "go" in langs:
lines.extend(
[
" go-ci:",
" runs-on: ubuntu-latest",
" steps:",
" - uses: actions/checkout@v4",
" - uses: actions/setup-go@v5",
" with:",
" go-version: '1.22'",
" - run: go test ./...",
" - run: go build ./...",
]
)
return "\n".join(lines) + "\n"
def gitlab_yaml(stack: Dict[str, Any]) -> str:
langs = stack.get("languages", [])
signals = stack.get("signals", {})
lint_cmds = stack.get("lint_commands", []) or ["echo 'No lint command configured'"]
test_cmds = stack.get("test_commands", []) or ["echo 'No test command configured'"]
build_cmds = stack.get("build_commands", []) or ["echo 'No build command configured'"]
lines: List[str] = [
"stages:",
" - lint",
" - test",
" - build",
"",
]
if "node" in langs:
install_cmd = select_node_install(signals)
lines.extend(
[
"node_lint:",
" image: node:20",
" stage: lint",
" script:",
f" - {install_cmd}",
]
)
for cmd in lint_cmds:
lines.append(f" - {cmd}")
lines.extend(
[
"",
"node_test:",
" image: node:20",
" stage: test",
" script:",
f" - {install_cmd}",
]
)
for cmd in test_cmds:
lines.append(f" - {cmd}")
lines.extend(
[
"",
"node_build:",
" image: node:20",
" stage: build",
" script:",
f" - {install_cmd}",
]
)
for cmd in build_cmds:
lines.append(f" - {cmd}")
if "python" in langs:
lines.extend(
[
"",
"python_test:",
" image: python:3.12",
" stage: test",
" script:",
" - python3 -m pip install -U pip",
" - python3 -m pip install -r requirements.txt || true",
" - python3 -m pytest || true",
]
)
if "go" in langs:
lines.extend(
[
"",
"go_test:",
" image: golang:1.22",
" stage: test",
" script:",
" - go test ./...",
" - go build ./...",
]
)
return "\n".join(lines) + "\n"
def main() -> int:
args = parse_args()
stack = load_json_input(args.input)
if stack is None:
if not args.repo:
raise CLIError("Provide stack input via --input/stdin or set --repo for auto-detection.")
repo = Path(args.repo).resolve()
if not repo.exists() or not repo.is_dir():
raise CLIError(f"Invalid repo path: {repo}")
stack = detect_stack(repo)
if args.platform == "github":
yaml_content = github_yaml(stack)
else:
yaml_content = gitlab_yaml(stack)
output_path = args.output or "stdout"
if args.output:
out = Path(args.output)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(yaml_content, encoding="utf-8")
else:
print(yaml_content, end="")
summary = PipelineSummary(
platform=args.platform,
output=output_path,
stages=["lint", "test", "build"],
uses_cache=True,
languages=stack.get("languages", []),
)
if args.format == "json":
print(json.dumps(asdict(summary), indent=2), file=sys.stderr if not args.output else sys.stdout)
else:
text = (
"Pipeline generated\n"
f"- platform: {summary.platform}\n"
f"- output: {summary.output}\n"
f"- stages: {', '.join(summary.stages)}\n"
f"- languages: {', '.join(summary.languages) if summary.languages else 'none'}"
)
print(text, file=sys.stderr if not args.output else sys.stdout)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except CLIError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
raise SystemExit(2)
FILE:scripts/stack_detector.py
#!/usr/bin/env python3
"""Detect project stack/tooling signals for CI/CD pipeline generation.
Input sources:
- repository scan via --repo
- JSON via --input file
- JSON via stdin
Output:
- text summary or JSON payload
"""
import argparse
import json
import sys
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Dict, List, Optional
class CLIError(Exception):
"""Raised for expected CLI failures."""
@dataclass
class StackReport:
repo: str
languages: List[str]
package_managers: List[str]
ci_targets: List[str]
test_commands: List[str]
build_commands: List[str]
lint_commands: List[str]
signals: Dict[str, bool]
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Detect stack/tooling from a repository.")
parser.add_argument("--input", help="JSON input file (precomputed signal payload).")
parser.add_argument("--repo", default=".", help="Repository path to scan.")
parser.add_argument("--format", choices=["text", "json"], default="text", help="Output format.")
return parser.parse_args()
def load_payload(input_path: Optional[str]) -> Optional[dict]:
if input_path:
try:
return json.loads(Path(input_path).read_text(encoding="utf-8"))
except Exception as exc:
raise CLIError(f"Failed reading --input file: {exc}") from exc
if not sys.stdin.isatty():
raw = sys.stdin.read().strip()
if raw:
try:
return json.loads(raw)
except json.JSONDecodeError as exc:
raise CLIError(f"Invalid JSON from stdin: {exc}") from exc
return None
def read_package_scripts(repo: Path) -> Dict[str, str]:
pkg = repo / "package.json"
if not pkg.exists():
return {}
try:
data = json.loads(pkg.read_text(encoding="utf-8"))
except Exception:
return {}
scripts = data.get("scripts", {})
return scripts if isinstance(scripts, dict) else {}
def detect(repo: Path) -> StackReport:
signals = {
"package_json": (repo / "package.json").exists(),
"pnpm_lock": (repo / "pnpm-lock.yaml").exists(),
"yarn_lock": (repo / "yarn.lock").exists(),
"npm_lock": (repo / "package-lock.json").exists(),
"pyproject": (repo / "pyproject.toml").exists(),
"requirements": (repo / "requirements.txt").exists(),
"go_mod": (repo / "go.mod").exists(),
"dockerfile": (repo / "Dockerfile").exists(),
"vercel": (repo / "vercel.json").exists(),
"helm": (repo / "helm").exists() or (repo / "charts").exists(),
"k8s": (repo / "k8s").exists() or (repo / "kubernetes").exists(),
}
languages: List[str] = []
package_managers: List[str] = []
ci_targets: List[str] = ["github", "gitlab"]
if signals["package_json"]:
languages.append("node")
if signals["pnpm_lock"]:
package_managers.append("pnpm")
elif signals["yarn_lock"]:
package_managers.append("yarn")
else:
package_managers.append("npm")
if signals["pyproject"] or signals["requirements"]:
languages.append("python")
package_managers.append("pip")
if signals["go_mod"]:
languages.append("go")
scripts = read_package_scripts(repo)
lint_commands: List[str] = []
test_commands: List[str] = []
build_commands: List[str] = []
if "lint" in scripts:
lint_commands.append("npm run lint")
if "test" in scripts:
test_commands.append("npm test")
if "build" in scripts:
build_commands.append("npm run build")
if "python" in languages:
lint_commands.append("python3 -m ruff check .")
test_commands.append("python3 -m pytest")
if "go" in languages:
lint_commands.append("go vet ./...")
test_commands.append("go test ./...")
build_commands.append("go build ./...")
return StackReport(
repo=str(repo.resolve()),
languages=sorted(set(languages)),
package_managers=sorted(set(package_managers)),
ci_targets=ci_targets,
test_commands=sorted(set(test_commands)),
build_commands=sorted(set(build_commands)),
lint_commands=sorted(set(lint_commands)),
signals=signals,
)
def format_text(report: StackReport) -> str:
lines = [
"Detected stack",
f"- repo: {report.repo}",
f"- languages: {', '.join(report.languages) if report.languages else 'none'}",
f"- package managers: {', '.join(report.package_managers) if report.package_managers else 'none'}",
f"- lint commands: {', '.join(report.lint_commands) if report.lint_commands else 'none'}",
f"- test commands: {', '.join(report.test_commands) if report.test_commands else 'none'}",
f"- build commands: {', '.join(report.build_commands) if report.build_commands else 'none'}",
]
return "\n".join(lines)
def main() -> int:
args = parse_args()
payload = load_payload(args.input)
if payload:
try:
report = StackReport(**payload)
except TypeError as exc:
raise CLIError(f"Invalid input payload for StackReport: {exc}") from exc
else:
repo = Path(args.repo).resolve()
if not repo.exists() or not repo.is_dir():
raise CLIError(f"Invalid repo path: {repo}")
report = detect(repo)
if args.format == "json":
print(json.dumps(asdict(report), indent=2))
else:
print(format_text(report))
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except CLIError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
raise SystemExit(2)
Lãnh đạo bảo mật: định lượng rủi ro, lộ trình tuân thủ SOC 2, ISO 27001, HIPAA, GDPR, ứng phó sự cố và báo cáo HĐQT.
---
name: "ciso-advisor"
description: "Security leadership for growth-stage companies. Risk quantification in dollars, compliance roadmap (SOC 2/ISO 27001/HIPAA/GDPR), security architecture strategy, incident response leadership, and board-level security reporting. Use when building security programs, justifying security budget, selecting compliance frameworks, managing incidents, assessing vendor risk, or when user mentions CISO, security strategy, compliance roadmap, zero trust, or board security reporting."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: ciso-leadership
updated: 2026-03-05
python-tools: risk_quantifier.py, compliance_tracker.py
frameworks: risk-based-security, zero-trust, defense-in-depth
---
# CISO Advisor
Risk-based security frameworks for growth-stage companies. Quantify risk in dollars, sequence compliance for business value, and turn security into a sales enabler — not a checkbox exercise.
## Keywords
CISO, security strategy, risk quantification, ALE, SLE, ARO, security posture, compliance roadmap, SOC 2, ISO 27001, HIPAA, GDPR, zero trust, defense in depth, incident response, board security reporting, vendor assessment, security budget, cyber risk, program maturity
## Quick Start
```bash
python scripts/risk_quantifier.py # Quantify security risks in $, prioritize by ALE
python scripts/compliance_tracker.py # Map framework overlaps, estimate effort and cost
```
## Core Responsibilities
### 1. Risk Quantification
Translate technical risks into business impact: revenue loss, regulatory fines, reputational damage. Use ALE to prioritize. See `references/security_strategy.md`.
**Formula:** `ALE = SLE × ARO` (Single Loss Expectancy × Annual Rate of Occurrence). Board language: "This risk has $X expected annual loss. Mitigation costs $Y."
### 2. Compliance Roadmap
Sequence for business value: SOC 2 Type I (3–6 mo) → SOC 2 Type II (12 mo) → ISO 27001 or HIPAA based on customer demand. See `references/compliance_roadmap.md` for timelines and costs.
### 3. Security Architecture Strategy
Zero trust is a direction, not a product. Sequence: identity (IAM + MFA) → network segmentation → data classification. Defense in depth beats single-layer reliance. See `references/security_strategy.md`.
### 4. Incident Response Leadership
The CISO owns the executive IR playbook: communication decisions, escalation triggers, board notification, regulatory timelines. See `references/incident_response.md` for templates.
### 5. Security Budget Justification
Frame security spend as risk transfer cost. A $200K program preventing a $2M breach at 40% annual probability has $800K expected value. See `references/security_strategy.md`.
### 6. Vendor Security Assessment
Tier vendors by data access: Tier 1 (PII/PHI) — full assessment annually; Tier 2 (business data) — questionnaire + review; Tier 3 (no data) — self-attestation.
## Key Questions a CISO Asks
- "What's our crown jewel data, and who can access it right now?"
- "If we had a breach today, what's our regulatory notification timeline?"
- "Which compliance framework do our top 3 prospects actually require?"
- "What's our blast radius if our largest SaaS vendor is compromised?"
- "We spent $X on security last year — what specific risks did that reduce?"
## Security Metrics
| Category | Metric | Target |
|----------|--------|--------|
| Risk | ALE coverage (mitigated risk / total risk) | > 80% |
| Detection | Mean Time to Detect (MTTD) | < 24 hours |
| Response | Mean Time to Respond (MTTR) | < 4 hours |
| Compliance | Controls passing audit | > 95% |
| Hygiene | Critical patches within SLA | > 99% |
| Access | Privileged accounts reviewed quarterly | 100% |
| Vendor | Tier 1 vendors assessed annually | 100% |
| Training | Phishing simulation click rate | < 5% |
## Red Flags
- Security budget justified by "industry benchmarks" rather than risk analysis
- Certifications pursued before basic hygiene (patching, MFA, backups)
- No documented asset inventory — can't protect what you don't know you have
- IR plan exists but has never been tested (tabletop or live drill)
- Security team reports to IT, not executive level — misaligned incentives
- Single vendor for identity + endpoint + email — one breach, total exposure
- Security questionnaire backlog > 30 days — silently losing enterprise deals
## Integration with Other C-Suite Roles
| When... | CISO works with... | To... |
|---------|--------------------|-------|
| Enterprise sales | CRO | Answer questionnaires, unblock deals |
| New product features | CTO/CPO | Threat modeling, security review |
| Compliance budget | CFO | Size program against risk exposure |
| Vendor contracts | Legal/COO | Security SLAs and right-to-audit |
| M&A due diligence | CEO/CFO | Target security posture assessment |
| Incident occurs | CEO/Legal | Response coordination and disclosure |
## Detailed References
- `references/security_strategy.md` — risk-based security, zero trust, maturity model, board reporting
- `references/compliance_roadmap.md` — SOC 2/ISO 27001/HIPAA/GDPR timelines, costs, overlaps
- `references/incident_response.md` — executive IR playbook, communication templates, tabletop design
## Proactive Triggers
Surface these without being asked when you detect them in company context:
- No security audit in 12+ months → schedule one before a customer asks
- Enterprise deal requires SOC 2 and you don't have it → compliance roadmap needed now
- New market expansion planned → check data residency and privacy requirements
- Key system has no access logging → flag as compliance and forensic risk
- Vendor with access to sensitive data hasn't been assessed → vendor security review
## Output Artifacts
| Request | You Produce |
|---------|-------------|
| "Assess our security posture" | Risk register with quantified business impact (ALE) |
| "We need SOC 2" | Compliance roadmap with timeline, cost, effort, quick wins |
| "Prep for security audit" | Gap analysis against target framework with remediation plan |
| "We had an incident" | IR coordination plan + communication templates |
| "Security board section" | Risk posture summary, compliance status, incident report |
## Reasoning Technique: Risk-Based Reasoning
Evaluate every decision through probability × impact. Quantify risks in business terms (dollars, not severity labels). Prioritize by expected annual loss.
## Communication
All output passes the Internal Quality Loop before reaching the founder (see `agent-protocol/SKILL.md`).
- Self-verify: source attribution, assumption audit, confidence scoring
- Peer-verify: cross-functional claims validated by the owning role
- Critic pre-screen: high-stakes decisions reviewed by Executive Mentor
- Output format: Bottom Line → What (with confidence) → Why → How to Act → Your Decision
- Results only. Every finding tagged: 🟢 verified, 🟡 medium, 🔴 assumed.
## Context Integration
- **Always** read `company-context.md` before responding (if it exists)
- **During board meetings:** Use only your own analysis in Phase 2 (no cross-pollination)
- **Invocation:** You can request input from other roles: `[INVOKE:role|question]`
FILE:references/compliance_roadmap.md
# Compliance Roadmap Reference
## Decision Framework: Which Framework First?
**Start here — who are your customers?**
```
Enterprise SaaS (B2B, US market) → SOC 2 Type II first
Healthcare / health data → HIPAA + SOC 2 together
EU customers or EU-resident data → GDPR (non-optional if applicable)
EU enterprise sales → ISO 27001 + GDPR
Government / defense → FedRAMP / CMMC (separate scope)
All of the above (Series B+) → Multi-framework efficiency approach
```
**The sequencing principle:** SOC 2 Type I is the fastest proof of intent (3–6 months). Type II is the credibility signal (12 months). Everything else builds on your control library.
---
## 1. SOC 2
### What It Is
SOC 2 is an attestation (not a certification) that your controls meet the AICPA Trust Service Criteria. An independent CPA firm audits your controls and issues a report.
- **Type I:** Controls are suitably designed at a point in time (snapshot). Lower credibility but faster.
- **Type II:** Controls operated effectively over a period of time (minimum 6 months). This is what enterprise buyers want.
### Trust Service Criteria (TSC)
You must include **Security** (CC). Others are optional:
| Criteria | When to add |
|---|---|
| Security (CC) | Always required |
| Availability | If uptime SLAs are contractual |
| Confidentiality | If you process confidential third-party data |
| Processing Integrity | If accuracy of processing is critical (fintech, data processing) |
| Privacy | If you make privacy commitments beyond GDPR/CCPA scope |
Most startups: **Security + Availability** is sufficient.
### Timeline: SOC 2 Type I
| Phase | Duration | Activities |
|---|---|---|
| Readiness assessment | 2–4 weeks | Gap analysis against CC criteria, identify control owners |
| Policy documentation | 4–6 weeks | Write ~15–20 policies (acceptable use, access control, change management, etc.) |
| Control implementation | 4–8 weeks | Deploy technical controls, fix gaps identified in readiness |
| Evidence collection | 2–4 weeks | Screenshots, logs, configs — auditor will sample these |
| Audit fieldwork | 2–4 weeks | CPA firm reviews evidence, interviews control owners |
| Report issuance | 2–4 weeks | Report issued, reviewed, shared with customers |
| **Total** | **3–6 months** | — |
### Timeline: SOC 2 Type II (after Type I)
| Phase | Duration | Notes |
|---|---|---|
| Observation period | 6–12 months | Controls must operate consistently — no exceptions |
| Audit fieldwork | 4–6 weeks | Auditor samples evidence across full period |
| Report issuance | 2–4 weeks | — |
| **Total from Type I** | **9–18 months** | Faster if Type I was clean |
### Cost Estimates
| Item | SOC 2 Type I | SOC 2 Type II |
|---|---|---|
| Audit firm fees | $15,000–$35,000 | $25,000–$60,000 |
| Compliance platform (Vanta, Drata, Secureframe) | $12,000–$30,000/yr | Same platform |
| External counsel / vCISO | $10,000–$30,000 | $5,000–$15,000 maintenance |
| Internal time (eng + ops) | 200–400 hours | 100–200 hours/yr |
| **Total first year** | **$40,000–$100,000** | **+$30,000–$75,000** |
**Cost optimization tips:**
- Use a compliance platform (Vanta, Drata, Secureframe) — automated evidence collection halves audit cost
- Choose a mid-tier audit firm; Big 4 is overkill for startups
- Type I and Type II with same auditor = continuity discount
### Common Failure Modes
1. Controls documented but not operating (access reviews on paper only)
2. Exceptions during observation period (one admin account without MFA = finding)
3. No formal security awareness training (required for CC criteria)
4. Change management not followed (no ticket for that production change)
5. Vendor risk management missing (you must assess your critical vendors)
---
## 2. ISO 27001
### What It Is
ISO 27001 is an internationally recognized certification for an Information Security Management System (ISMS). Unlike SOC 2, it's a certification (pass/fail), not an attestation report. Issued by accredited certification bodies (BSI, Bureau Veritas, DNV, TÜV).
**Why ISO 27001 over SOC 2:** EU enterprise buyers, government contracts, and global markets often prefer or require ISO 27001. It's geographically neutral.
### Scope Decision
ISO 27001 scope is flexible — you can certify a subset of the organization.
- **Narrow scope:** The production environment only — fastest, cheapest
- **Full scope:** Entire organization — most credibility, highest effort
- **Recommended for startups:** Production environment + key business processes
### Certification Timeline
| Phase | Duration | Activities |
|---|---|---|
| Gap analysis | 2–4 weeks | Assess current state vs. 93 controls in Annex A |
| ISMS design | 4–8 weeks | Scope, risk methodology, SoA (Statement of Applicability) |
| Policy and procedure development | 6–10 weeks | Mandatory documents: risk treatment plan, asset register, ISMS policy |
| Risk assessment | 4–6 weeks | Identify, analyze, evaluate risks; produce risk register |
| Control implementation | 8–16 weeks | Implement gaps from risk assessment |
| Internal audit | 2–4 weeks | First internal audit of ISMS |
| Management review | 1–2 weeks | Leadership sign-off on ISMS |
| Stage 1 audit (documentation) | 1–2 weeks | Certification body reviews docs and scope |
| Stage 2 audit (implementation) | 1–2 weeks | Certification body verifies controls are operating |
| Certification issued | 1–2 weeks | Certificate valid for 3 years with annual surveillance audits |
| **Total** | **9–18 months** | — |
### Cost Estimates
| Item | Cost |
|---|---|
| Certification body fees (Stage 1 + Stage 2) | $15,000–$40,000 |
| Annual surveillance audits | $8,000–$20,000/yr |
| vCISO / consultant (if not in-house) | $30,000–$80,000 |
| GRC platform | $10,000–$25,000/yr |
| Internal time | 400–800 hours |
| **Total first year** | **$55,000–$150,000** |
### Mandatory ISO 27001:2022 Documents
- ISMS scope document
- Information security policy
- Risk assessment methodology
- Risk register with risk treatment plan
- Statement of Applicability (SoA)
- Asset inventory
- Competence and awareness records
- Internal audit reports
- Management review minutes
- Nonconformity and corrective action records
---
## 3. HIPAA for Health Tech Startups
### When HIPAA Applies
HIPAA applies if you are a **Covered Entity** (healthcare provider, health plan, clearinghouse) or a **Business Associate** (you process, store, or transmit Protected Health Information on behalf of a Covered Entity).
**Key trigger:** If your product touches patient data in any way and a US healthcare provider uses your product, you are likely a Business Associate. You must sign a **BAA (Business Associate Agreement)** with each Covered Entity customer.
### HIPAA Rule Structure
| Rule | Focus | Key Requirements |
|---|---|---|
| Privacy Rule | How PHI can be used and disclosed | Minimum necessary, patient rights, notice of privacy practices |
| Security Rule | Technical and physical safeguards for ePHI | Required and addressable safeguards |
| Breach Notification Rule | What to do if PHI is breached | Timing and content of breach notifications |
### Security Rule: Required vs. Addressable
**Required safeguards** must be implemented exactly as specified. **Addressable safeguards** must be implemented or documented why an equivalent measure was used.
**Key Required Safeguards:**
- Unique user IDs (no shared logins)
- Emergency access procedure
- Audit controls (logging access to ePHI)
- Transmission security (encryption in transit)
- Person or entity authentication
**Key Addressable Safeguards (implement or document why not):**
- Automatic logoff
- Encryption and decryption (encryption at rest — despite being "addressable," regulators expect it)
- Audit review procedures
- Security reminders and training
### HIPAA Compliance Timeline
| Phase | Duration | Activities |
|---|---|---|
| Risk analysis | 4–6 weeks | Document all PHI flows, assess risks to PHI — **required by law** |
| Policy development | 4–8 weeks | Privacy policies, breach notification, workforce training |
| Technical safeguard implementation | 4–12 weeks | Encryption, audit logging, access controls, BAA templates |
| Workforce training | 2–4 weeks | Annual HIPAA training for all staff with PHI access |
| BAA execution | Ongoing | Execute with all vendors who process PHI |
| **Total** | **4–8 months** | — |
### Cost Estimates
| Item | Cost |
|---|---|
| Initial risk analysis (consultant) | $15,000–$40,000 |
| Policy development | $8,000–$20,000 |
| Technical implementation | $20,000–$60,000 |
| Annual training and maintenance | $5,000–$15,000/yr |
| HIPAA compliance platform | $10,000–$20,000/yr |
| **Total first year** | **$45,000–$130,000** |
### HIPAA Penalties (Why This Matters)
| Violation Category | Penalty per Violation | Annual Cap |
|---|---|---|
| Unaware | $100–$50,000 | $25,000 |
| Reasonable cause | $1,000–$50,000 | $100,000 |
| Willful neglect (corrected) | $10,000–$50,000 | $250,000 |
| Willful neglect (not corrected) | $50,000 | $1,500,000 |
---
## 4. GDPR Compliance Program
### When GDPR Applies
GDPR applies if you:
- Are established in the EU/EEA
- Process personal data of EU/EEA residents (regardless of your location)
- Offer goods or services to EU residents
- Monitor the behavior of EU residents
**Key point for US startups:** If you have EU users or EU employees, GDPR applies to you.
### Core GDPR Principles (Build These In)
1. **Lawfulness, fairness, transparency** — have a legal basis for every processing activity
2. **Purpose limitation** — collect data for specified, explicit purposes only
3. **Data minimization** — collect only what you need
4. **Accuracy** — keep data accurate
5. **Storage limitation** — delete data when no longer needed
6. **Integrity and confidentiality** — appropriate security measures
7. **Accountability** — demonstrate compliance
### Legal Bases for Processing
| Basis | When to use |
|---|---|
| Consent | Marketing, non-essential cookies, optional features |
| Contract | Processing necessary to deliver your service |
| Legitimate interests | Analytics, fraud prevention, security (requires LIA) |
| Legal obligation | Compliance with legal requirements |
| Vital interests | Emergency situations only |
**Avoid over-relying on consent** — it must be freely given, specific, informed, and unambiguous. Contractual basis is more robust for core product data.
### GDPR Compliance Checklist
**Governance:**
- [ ] Data Protection Officer (DPO) appointed (required for large-scale processing or sensitive data)
- [ ] Record of Processing Activities (RoPA) maintained
- [ ] Data Protection Impact Assessments (DPIA) for high-risk processing
**Rights Management (respond within 1 month):**
- [ ] Right of access (data subject access requests — DSARs)
- [ ] Right to rectification
- [ ] Right to erasure ("right to be forgotten")
- [ ] Right to data portability
- [ ] Right to object to processing
**Technical Measures:**
- [ ] Privacy by design in product development
- [ ] Data minimization enforced
- [ ] Encryption at rest and in transit
- [ ] Pseudonymization where possible
- [ ] Retention policies and automated deletion
**Vendor Management:**
- [ ] Data Processing Agreements (DPAs) with all processors
- [ ] Standard Contractual Clauses (SCCs) for non-EU transfers
**Breach Notification:**
- [ ] Notify supervisory authority within 72 hours of awareness
- [ ] Notify affected individuals if high risk to their rights and freedoms
### GDPR Compliance Timeline
| Phase | Duration | Activities |
|---|---|---|
| Data mapping | 3–6 weeks | Map all personal data flows: collect, store, process, share, delete |
| Legal basis review | 2–4 weeks | Assign legal basis to each processing activity |
| Policy updates | 4–6 weeks | Privacy policy, cookie policy, employee data notices |
| DPA execution | 2–4 weeks | Execute DPAs with all processors (SaaS vendors, cloud providers) |
| Technical controls | 4–12 weeks | Consent management, data subject rights automation, retention |
| Staff training | 2–4 weeks | GDPR awareness for all staff |
| **Total** | **3–6 months** | — |
### GDPR Fines
- **Standard violations:** Up to €10M or 2% of global annual revenue
- **Major violations** (basic principles, consent, data subject rights): Up to €20M or 4% of global annual revenue
- **Highest ever fine:** Meta, €1.2B (2023, data transfers to US)
---
## 5. Multi-Framework Efficiency
### Control Overlap Analysis
The same underlying controls satisfy multiple frameworks. Build once, certify multiple times.
**Core Control Domain Overlap:**
| Control Domain | SOC 2 | ISO 27001 | HIPAA | GDPR |
|---|---|---|---|---|
| Access control / IAM | CC6 | A.5.15–A.5.18 | §164.312(a) | Art. 32 |
| Encryption at rest/transit | CC6.7 | A.8.24 | §164.312(a)(2)(iv) | Art. 32 |
| Audit logging | CC7.2 | A.8.15, A.8.17 | §164.312(b) | Art. 32 |
| Incident response | CC7.3–CC7.5 | A.5.24–A.5.28 | §164.308(a)(6) | Art. 33–34 |
| Vendor/third-party mgmt | CC9 | A.5.19–A.5.22 | §164.308(b) | Art. 28 |
| Risk assessment | CC3 | Clause 6.1 | §164.308(a)(1) | Art. 32 |
| Security training | CC1.4 | A.6.3, A.6.8 | §164.308(a)(5) | Art. 39 |
| Business continuity | A1 | A.5.29–A.5.30 | §164.308(a)(7) | Art. 32 |
| Data classification | CC6.1 | A.5.9–A.5.13 | §164.514 | Art. 5(1)(c) |
| Change management | CC8 | A.8.32 | §164.312(c) | Art. 25 |
**Efficiency Rule:** If you build SOC 2 controls correctly, you're ~65–75% of the way to ISO 27001 and ~70% of the way to HIPAA. Don't rebuild — extend.
### Recommended Sequencing by Company Profile
**B2B SaaS (US-focused):**
```
Month 0–6: SOC 2 Type I → unblocks early enterprise deals
Month 6–18: SOC 2 Type II → enterprise table stakes
Month 18–30: ISO 27001 → EU market expansion
(GDPR should be woven in from month 0 if any EU data)
```
**HealthTech (US):**
```
Month 0–8: HIPAA compliance + BAA readiness → enables healthcare customers
Month 6–18: SOC 2 Type II → enterprise IT requirements on top of HIPAA
Month 18+: ISO 27001 if entering European market
```
**EU-founded SaaS:**
```
Month 0–3: GDPR compliance → legal requirement, not optional
Month 3–12: ISO 27001 → EU enterprise default expectation
Month 12–24: SOC 2 → US market expansion
```
**HealthTech (EU):**
```
Concurrent: GDPR + ISO 27001 (strong overlap with MDR/IVDR security requirements)
Month 12+: HIPAA if entering US market
```
### Shared Evidence Model
Build your evidence library once. Tag each piece of evidence by framework:
```
evidence/
├── access_control/
│ ├── iam_policy.pdf [SOC2:CC6, ISO:A5.15, HIPAA:164.312a]
│ ├── mfa_screenshot_Q1.png [SOC2:CC6, ISO:A8.5, HIPAA:164.312d]
│ └── access_review_log.xlsx [SOC2:CC6, ISO:A5.18, HIPAA:164.308a]
├── encryption/
│ ├── kms_config.png [SOC2:CC6.7, ISO:A8.24, HIPAA:164.312e]
│ └── tls_policy.md [SOC2:CC6.7, ISO:A8.24, HIPAA:164.312e]
└── incident_response/
├── ir_plan.pdf [SOC2:CC7, ISO:A5.24, HIPAA:164.308a6]
└── tabletop_log.pdf [SOC2:CC7, ISO:A5.26, HIPAA:164.308a6]
```
### GRC Platform Comparison
| Platform | Best For | Price/yr | SOC 2 | ISO 27001 | HIPAA | GDPR |
|---|---|---|---|---|---|---|
| Vanta | Fast SOC 2, US startups | $15–30K | ✅ | ✅ | ✅ | ✅ |
| Drata | Automation depth | $18–35K | ✅ | ✅ | ✅ | ✅ |
| Secureframe | Cost-effective | $10–20K | ✅ | ✅ | ✅ | ✅ |
| Sprinto | SMB, global | $12–25K | ✅ | ✅ | ✅ | ✅ |
| Tugboat Logic | Mid-market | $20–40K | ✅ | ✅ | ✅ | ✅ |
| Manual | Budget-constrained | $0 + time | ✅ | ✅ | ✅ | ✅ |
**Recommendation:** For Series A startups, Vanta or Drata pays for itself in reduced auditor fees and internal time savings. Budget $15–25K/year.
### Compliance Maintenance Annual Budget
| Item | SOC 2 | ISO 27001 | HIPAA | GDPR |
|---|---|---|---|---|
| Annual audit / surveillance | $25–60K | $8–20K | n/a (self-assessed) | n/a (self-assessed) |
| GRC platform | $15–30K | Shared | Shared | Shared |
| Annual training | $3–8K | Shared | Shared | Shared |
| Policy review | $2–5K | $2–5K | $2–5K | $2–5K |
| **Total ongoing** | **$45–103K/yr** | **+$10–25K/yr** | **+$5–15K/yr** | **+$5–15K/yr** |
FILE:references/incident_response.md
# Incident Response Reference (Executive Playbook)
This is the executive IR playbook — strategic decisions, communication, and leadership during incidents. For technical playbooks (containment procedures, forensics), see your SOC runbooks.
---
## 1. Incident Classification
### Severity Levels
| Severity | Definition | Examples | Response Time | Escalation |
|---|---|---|---|---|
| SEV-1 (Critical) | Confirmed breach, data exfil, ransomware, production down | Active ransomware, confirmed data theft, complete service outage | Immediate (< 1 hour) | CEO, board within 24 hrs |
| SEV-2 (High) | Suspected breach, significant security event, extended outage | Credential compromise suspected, DDoS, 4-hour+ outage | < 4 hours | CEO, legal within 48 hrs |
| SEV-3 (Medium) | Security event with limited impact, short outage | Phishing success (contained), brief outage, single system compromise | < 24 hours | CISO-owned, weekly rollup |
| SEV-4 (Low) | Minor security event, near-miss | Failed phishing attempt, minor policy violation | < 72 hours | Team-owned |
### Breach vs. Security Incident
**Security incident:** Unplanned event affecting security — may or may not involve data.
**Data breach:** Confirmed unauthorized access to personal data — triggers regulatory notification obligations.
**Critical distinction for response planning:** A ransomware attack is an incident. If data was exfiltrated before encryption, it's also a breach. Assume breach until proven otherwise.
---
## 2. Executive IR Plan
### Phase 1: Detection & Initial Assessment (0–2 hours for SEV-1)
**Immediate actions (CISO):**
1. Receive alert from SOC/monitoring system or team member report
2. Make initial severity classification — don't wait for perfect information
3. Activate incident response team (IR lead, legal counsel, comms lead)
4. Create incident war room (dedicated Slack channel, video bridge, shared document)
5. **Stop the clock** — document exact time of discovery (regulatory timelines start here)
6. Begin chain of custody documentation if forensics may be needed
**Executive notification trigger (within 1 hour for SEV-1):**
- Notify CEO: incident status, initial severity, IR team activated
- Put legal counsel on notice — don't wait to determine if breach occurred
- If public company: notify General Counsel immediately (potential disclosure obligations)
**What you do NOT do in Phase 1:**
- Do not notify customers yet (confirm scope first)
- Do not delete or modify any logs or systems (evidence preservation)
- Do not make public statements
- Do not speculate about cause or scope
### Phase 2: Containment & Assessment (2–24 hours for SEV-1)
**Executive decisions required:**
- **Scope authorization:** Approve IR firm engagement (have a retainer in place)
- **System isolation:** Authorize taking systems offline if needed (revenue vs. evidence tradeoff)
- **Evidence preservation:** Authorize forensic image capture
- **Communication timing:** When to notify customers/partners (legal drives this)
**Board notification (for SEV-1/2):**
- Notify board chair / audit committee chair within 24 hours for SEV-1
- Board notification format: what we know, what we don't know, what we're doing, next update time
- Do not speculate on financial impact in board notification until known
**Legal assessment (with counsel):**
- Determine if personal data was involved
- Identify applicable notification laws (GDPR 72-hour, state breach notification, HIPAA 60-day)
- Assess litigation risk (document with privilege from this point)
- Evaluate cyber insurance policy coverage and notification requirements
### Phase 3: Notification & Communication (24–72 hours for SEV-1)
**Notification decision matrix:**
| Audience | Trigger | Timeline | Owner |
|---|---|---|---|
| Board | SEV-1/2 confirmed | < 24 hours | CEO/CISO |
| Regulators (GDPR) | Personal data breach confirmed | < 72 hours from awareness | Legal + CISO |
| Regulators (HIPAA) | PHI breach confirmed | < 60 days (early notice to HHS ASAP) | Legal + CISO |
| State regulators (US) | State breach notification laws vary | 30–90 days depending on state | Legal |
| Enterprise customers | Data confirmed in scope | As soon as practical after legal review | CEO/CRO |
| All customers | Data potentially in scope | After regulators notified | CEO/Comms |
| Media | Proactive or reactive | After notifying affected parties | CEO/Comms |
| Cyber insurer | Incident confirmed | Per policy terms (often 48–72 hours) | CFO/Legal |
### Phase 4: Recovery (Ongoing)
**Executive decisions:**
- Approve recovery timeline and communicate to customers
- Determine customer compensation or remediation (if applicable)
- Authorize security improvements identified during incident
- Decide on public disclosure beyond mandatory reporting
### Phase 5: Post-Incident Review (Within 30 days)
Covered in Section 5 of this document.
---
## 3. Communication Templates
### Board/Executive Notification (Initial — Hour 1)
**Subject:** [CONFIDENTIAL] Security Incident — Immediate Notification
---
We have identified a security incident as of [DATE/TIME].
**Current status:** [Brief factual description — what we know happened]
**Severity assessment:** SEV-[1/2/3]
**What we do not yet know:**
- [List unknowns — scope of impact, whether data was accessed, root cause]
**Actions taken so far:**
- IR team activated at [time]
- Legal counsel notified
- [Specific containment actions if applicable]
**Next update:** [Specific time, e.g., "in 4 hours or when we have material new information"]
**Who is managing this:** [CISO name] leads technical response; [CEO name] owns executive decisions. Contact: [CISO mobile]
---
### Customer Notification (After Legal Review)
**Subject:** Important Security Notice — [Company Name]
---
We are writing to inform you of a security incident that may have affected your data.
**What happened:**
On [DATE], we detected [brief, factual description of the incident — e.g., "unauthorized access to our systems"]. We identified this on [DISCOVERY DATE] and immediately launched an investigation.
**What information was involved:**
Based on our investigation, the following types of information may have been accessed: [list data types — e.g., names, email addresses, [if applicable: payment card information]].
Your [specific data types] [were / were not] affected.
**What we are doing:**
We have [list specific actions: engaged leading cybersecurity firm, notified relevant authorities, implemented additional security controls, etc.].
**What you can do:**
- [Specific actionable steps for customers]
- Monitor your accounts for unusual activity
- [If passwords: reset your password at X]
- [If payment data: contact your bank to monitor for unauthorized charges]
- Contact our dedicated support line at [contact] with any concerns
**For more information:**
We have set up a dedicated resource page at [URL]. Our support team is available at [contact].
We take the security of your data extremely seriously and deeply regret this incident occurred.
[CEO/CISO Name]
[Title], [Company Name]
---
### Regulator Notification — GDPR (72-hour requirement)
**To:** [Relevant Supervisory Authority — e.g., BfDI (Germany), CNIL (France), ICO (UK)]
**Subject:** Personal Data Breach Notification — [Company Name] — [Reference Number if applicable]
---
**1. Nature of the breach:**
[Description of what occurred, including how it happened]
**2. Categories and approximate number of data subjects concerned:**
[e.g., "Approximately [X] customers whose [name, email, account data] may have been accessed"]
**3. Categories and approximate number of personal data records concerned:**
[e.g., "Approximately [X] records containing [data categories]"]
**4. Likely consequences of the breach:**
[Risk assessment: what harm could data subjects face?]
**5. Measures taken or proposed:**
[Containment actions, remediation plan, customer notification plan]
**6. Contact details of the Data Protection Officer or other contact point:**
[Name, role, email, phone]
**Note:** This is an initial notification; we will provide supplemental information as our investigation continues.
---
### Media Statement (Reactive — When Contacted)
"[Company Name] is aware of a security incident that we identified on [date]. We immediately activated our incident response team and launched a comprehensive investigation. We have notified affected customers and relevant regulatory authorities as required. The security and privacy of our customers' data is our top priority, and we are committed to transparency as our investigation proceeds. We will provide updates at [URL]. We cannot provide additional details at this time to protect the integrity of our investigation."
**What not to say to media:**
- Number of affected users (until confirmed and disclosed to customers first)
- Cause of the incident (until investigation is complete)
- Financial impact (speculation creates liability)
- Anything that could be construed as minimizing the incident
---
## 4. Tabletop Exercise Design
### Purpose
Test the decision-making and communication processes — not the technical response. The goal is to surface gaps in escalation, communication, and judgment before a real incident.
### Recommended Frequency
- Annual full tabletop (2–3 hours, full leadership team)
- Semi-annual mini-tabletop (45 minutes, CISO + legal + CEO)
- Quarterly technical team exercise (separate from executive tabletop)
### Sample Tabletop Scenario: Ransomware
**Setup (read to participants):**
> It's 6:47 AM on a Monday. Your DevOps engineer receives automated alerts that production databases are inaccessible. By 7:15 AM, they discover a ransomware note demanding $500,000 in Bitcoin. Several files are already encrypted. Your last verified backup was 48 hours ago. Your business is B2B SaaS serving 200 enterprise customers. You process customer financial data.
**Discussion questions (timed, 10 minutes each):**
1. First 30 minutes — who do you call, in what order? Who decides whether to take production offline?
2. Legal assessment — what regulatory obligations have been triggered? What's the timeline?
3. Hour 4 — initial forensics suggests data may have been exfiltrated before encryption. How does your response change?
4. Customer communication — how do you communicate with enterprise customers who are asking for status?
5. Hour 24 — do you pay the ransom? Who makes this decision? What's the decision framework?
6. The press has found out and a reporter is calling. What do you say?
7. Day 5 — what's your board communication strategy?
**Post-discussion captures:**
- What decisions were unclear (ownership ambiguous)?
- What information did you need but didn't have?
- What processes did not exist that should?
- What would you do differently in the first hour?
### Sample Tabletop Scenario: Insider Threat
**Setup:**
> HR notifies you that an engineer was terminated this morning for performance reasons. 24 hours later, your SIEM generates an alert that this former employee's credentials accessed your customer database 30 minutes before their offboarding was complete. They downloaded 50,000 customer records. You don't know if they shared or sold the data.
**Key decision points:**
- When does this become a breach vs. a security incident?
- Do you notify customers? When?
- What are your legal options against the former employee?
- How do you handle this with the rest of the engineering team?
---
## 5. Post-Incident Review Framework
### Timeline
Conduct within 30 days of incident resolution. Do not delay — memory fades and teams move on.
### Blameless Post-Mortem Principles
The purpose is to improve systems and processes, not punish individuals. A blame culture means the next incident gets hidden longer.
### Post-Incident Review Structure
**1. Incident Timeline (factual, no editorializing)**
- Hour-by-hour reconstruction from detection to resolution
- Source: logs, Slack messages, incident ticket, war room notes
**2. Root Cause Analysis**
Use the "5 Whys" technique — keep asking why until you reach a systemic root cause, not a human error.
Example:
- Why was there a breach? → Attacker compromised an admin account
- Why was the admin account compromised? → Credentials stolen via phishing
- Why did phishing succeed? → User wasn't trained on this attack type
- Why wasn't training current? → Training program hadn't been updated in 18 months
- Why hadn't it been updated? → No owner was assigned to maintain the training program
- **Root cause: No assigned ownership for security training maintenance**
**3. What Went Well**
- Detection mechanisms that worked
- Response actions that contained damage
- Communication that was effective
- Teams that exceeded expectations
**4. What Needs Improvement**
- Detection gaps (how could we have found this faster?)
- Response gaps (what slowed us down?)
- Communication gaps (who didn't know what, when?)
- Process gaps (what didn't we have documented?)
**5. Action Items (with owners and deadlines)**
| Action | Owner | Due Date | Priority |
|---|---|---|---|
| [Specific improvement] | [Name] | [Date] | [P0/P1/P2] |
**6. Metrics Review**
- MTTD (Mean Time to Detect): [actual] vs. [target]
- MTTR (Mean Time to Respond): [actual] vs. [target]
- Customer impact: [affected customers, duration]
- Financial impact: [direct costs, revenue impact]
- Regulatory impact: [notifications sent, fines if any]
---
## 6. Insurance and Legal Considerations
### Cyber Insurance
**What to have before an incident:**
- Cyber liability policy with minimum $2M coverage (Series A); $5M+ (Series B+)
- Coverage should include: first-party loss, third-party liability, ransomware, business interruption, regulatory defense
- Pre-approved IR firms on your policy (using an approved firm can expedite claims)
- Notification requirements — know your insurer's required timeline (typically 48–72 hours)
**Policy exclusions to watch:**
- "War exclusion" — increasingly contested for nation-state attacks (NotPetya precedent)
- "Systemic risk" — some policies exclude widespread events affecting many insureds simultaneously
- "Prior acts" — incidents that began before policy inception
- "Failure to maintain reasonable security" — don't give your insurer a reason to deny
**Premium factors:**
- Revenue and data volume
- Security control maturity (MFA, EDR, backup, patch management)
- Industry (healthcare, financial services = higher premium)
- Claims history
**Ballpark premiums:**
- Seed/Series A ($1–10M ARR): $8,000–$25,000/yr
- Series B ($10–50M ARR): $25,000–$75,000/yr
- Series C+ ($50M+ ARR): $75,000–$250,000/yr
### Legal Counsel
**Have on retainer before an incident:**
- Cybersecurity/privacy attorney — breach notification, regulatory response
- General counsel — contracts, employment law (insider threats), litigation
- Consider: a law firm with data breach notification experience by jurisdiction
**Attorney-client privilege:** Once legal counsel is involved in an incident, communications and work product may be privileged. Engage counsel early to maximize privilege protection.
**Key legal decisions during an incident:**
- When does notification obligation clock start? (Legal determines this)
- Is this a breach or an incident? (Legal + CISO together)
- Who are the affected data subjects? (Legal + technical together)
- Do we pay the ransom? (Legal, CEO, board — never CISO alone)
- Do we cooperate with law enforcement? (Legal decision, involves trade-offs)
### Law Enforcement
**FBI Internet Crime Complaint Center (IC3):** File a complaint for ransomware or significant cybercrime. Does not obligate you to cooperate but creates a record.
**Pros of law enforcement involvement:**
- Access to threat intelligence they may have
- May recover funds in some cases (rare)
- Demonstrates good-faith response to regulators
**Cons of law enforcement involvement:**
- Loss of control over investigation timeline
- Potential for public disclosure if case pursued
- Slows ransom payment decisions (if considering)
- May create discovery obligations in litigation
**CISO recommendation:** Notify legal before contacting law enforcement. In most cases, file an IC3 complaint but don't actively engage FBI investigation unless there's a clear benefit.
FILE:references/security_strategy.md
# Security Strategy Reference
## 1. Risk-Based Security (Not Compliance-First)
### The Problem with Compliance-First Security
Most startups build security backwards: they get a compliance requirement (SOC 2, ISO 27001) and treat it as the security program. This produces:
- Controls that pass audits but don't reduce actual risk
- Resources allocated to documentation over protection
- Security teams optimizing for auditor satisfaction, not threat reduction
- False confidence ("we passed our audit") before real security exists
**The right order:**
1. Identify your actual threats (what do adversaries want from you?)
2. Identify your crown jewels (what's worth protecting most?)
3. Implement controls that address those threats to those assets
4. Map existing controls to compliance requirements — most overlap naturally
### Risk Identification Framework
**Asset Classification:**
```
Tier 1 — Crown Jewels
├── Customer PII/PHI
├── Payment card data
├── Intellectual property (source code, models, trade secrets)
└── Authentication credentials and secrets
Tier 2 — Business Critical
├── Internal communications (Slack, email)
├── Financial systems and data
├── Employee data
└── Business strategy documents
Tier 3 — Operational
├── Internal tooling and infrastructure configs
├── Non-sensitive operational data
└── Public-facing content and marketing
```
**Threat Actor Profiling:**
| Threat Actor | Motivation | Typical TTPs | Relative Likelihood |
|---|---|---|---|
| Financially motivated criminals | Data theft, ransomware | Phishing, credential stuffing | High |
| Nation-state | IP theft, espionage | Spear phishing, supply chain | Low-Medium (sector-dependent) |
| Insider threat | Financial gain, revenge | Privilege abuse, data exfil | Medium |
| Script kiddies | Notoriety, fun | Known CVEs, scanning | High (low sophistication) |
| Competitors | IP theft | Social engineering, insider recruitment | Low-Medium |
### Risk Quantification (FAIR Model Simplified)
**Annual Loss Expectancy:**
```
ALE = SLE × ARO
SLE (Single Loss Expectancy) = Asset Value × Exposure Factor
ARO (Annual Rate of Occurrence) = historical frequency or industry estimate
```
**Business Impact Categories:**
- **Direct financial loss**: fraud, ransomware payment, theft
- **Regulatory fines**: GDPR (4% global revenue), HIPAA ($100–$50K per violation), PCI DSS
- **Revenue impact**: customer churn post-breach, deal loss during incident, downtime cost
- **Reputational damage**: brand devaluation (harder to quantify, but real)
- **Legal costs**: incident response counsel, class action defense, settlements
**Example Risk Quantification:**
| Risk Scenario | SLE | ARO | ALE |
|---|---|---|---|
| Customer data breach (10K records) | $850K | 0.15 | $127,500/yr |
| Ransomware attack | $350K | 0.20 | $70,000/yr |
| Credential compromise + fraud | $120K | 0.35 | $42,000/yr |
| Third-party SaaS breach | $95K | 0.25 | $23,750/yr |
| Insider data exfiltration | $180K | 0.10 | $18,000/yr |
**Mitigation ROI:**
```
ROSI = (Risk Reduction × ALE) - Control Cost
────────────────────────────────────
Control Cost
Example: MFA deployment
Risk reduction: 99% for credential attacks
ALE reduced: $42,000 × 0.99 = $41,580
Control cost: $5,000/yr
ROSI: ($41,580 - $5,000) / $5,000 = 731%
```
---
## 2. Zero Trust Architecture at Strategy Level
### What Zero Trust Actually Means
Zero trust is not a product — it's an architectural principle: **never trust, always verify, assume breach.**
The traditional perimeter model (trust inside the network, distrust outside) fails because:
- Remote work destroyed the perimeter
- Cloud infrastructure has no perimeter
- 80% of breaches involve privileged account abuse (internal trust abused)
- Supply chain attacks compromise trusted software
### Zero Trust Maturity Model
**Stage 1 — Identity-Centric (Start Here)**
- MFA enforced for all users, all applications
- Identity provider (Okta, Azure AD, Google Workspace) as single control plane
- No shared service accounts
- Privileged Access Management (PAM) for admin access
- **Cost:** $20–80K/year | **Timeline:** 3–6 months
**Stage 2 — Device Trust**
- Endpoint detection and response (EDR) on all devices
- Device health checks before granting access
- Mobile device management (MDM) for BYOD
- Certificate-based device authentication
- **Cost:** $30–60K/year additional | **Timeline:** 6–12 months
**Stage 3 — Network Micro-Segmentation**
- Replace VPN with Zero Trust Network Access (ZTNA)
- Segment production from development from corporate
- East-west traffic inspection (not just north-south)
- **Cost:** $40–100K/year additional | **Timeline:** 12–18 months
**Stage 4 — Application-Level Controls**
- Just-in-time access (no standing privileges)
- Workload identity for service-to-service auth
- API gateway with authentication enforcement
- Continuous authorization (not just at login)
- **Cost:** $50–150K/year additional | **Timeline:** 18–30 months
**Strategic Guidance:**
- Don't sell zero trust as a project. It's a 3–5 year direction.
- Start with identity. It gives the most risk reduction per dollar.
- Measure progress by % of access covered by MFA, % of apps behind IdP, privilege account count.
---
## 3. Defense in Depth for Startups
### The Layered Security Model
```
Layer 1: Governance & Policies
└── Asset inventory, acceptable use, vendor management
Layer 2: Perimeter Controls
└── WAF, DDoS protection, email security (DMARC/DKIM/SPF)
Layer 3: Identity & Access
└── MFA, SSO, PAM, just-in-time access, least privilege
Layer 4: Endpoint Security
└── EDR, device management, patch management
Layer 5: Application Security
└── SAST/DAST, dependency scanning, code review, API security
Layer 6: Data Protection
└── Encryption at rest and in transit, DLP, backup/recovery
Layer 7: Detection & Response
└── SIEM/SOAR, log aggregation, alerting, incident response
Layer 8: Recovery
└── Backup testing, DR plan, RTO/RPO targets
```
### Startup Security Budget Allocation (Guidance)
| Stage | Annual Revenue | Recommended Security Budget | Priority Spend |
|---|---|---|---|
| Pre-seed/Seed | <$1M | 3–5% opex or $50–100K | MFA, backups, basic EDR |
| Series A | $1–10M | 2–4% revenue | +SIEM, SOC 2 Type I, AppSec |
| Series B | $10–50M | 3–5% revenue | +ZTNA, Red team, dedicated CISO |
| Series C+ | $50M+ | 4–6% revenue | +SOC, threat intelligence, M&A security |
**Non-negotiables regardless of stage:**
1. MFA on everything (particularly email, cloud consoles, code repos)
2. Automated backups with tested restore (ransomware defense)
3. Secrets management (no hardcoded credentials)
4. Dependency vulnerability scanning in CI/CD
5. Incident response plan (even a 2-page doc is better than nothing)
---
## 4. Security Program Maturity Model
**Based on NIST CSF and CMMI, simplified for startup context:**
### Level 1: Initial
- No formal policies
- Reactive security (respond to incidents, not prevent them)
- No dedicated security personnel
- Basic hygiene gaps (unpatched systems, shared passwords)
- **Typical:** Pre-seed, <20 employees
### Level 2: Developing
- Written security policies (even if not fully followed)
- Dedicated security responsibility (often part-time or dual-role)
- MFA deployed, basic asset inventory
- Incident response process documented
- SOC 2 Type I achievable from here in ~6 months
- **Typical:** Series A, 20–50 employees
### Level 3: Defined
- Security integrated into SDLC
- Dedicated security lead or vCISO
- Regular vulnerability scanning and patching
- Security awareness training program
- SOC 2 Type II and ISO 27001 achievable
- **Typical:** Series B, 50–150 employees
### Level 4: Managed
- Risk-based security program with quantified risks
- Security metrics reported to board quarterly
- Threat intelligence program
- Dedicated security team (3–8 people)
- Red team / penetration testing annually
- **Typical:** Series C+, 150–500 employees
### Level 5: Optimized
- Continuous monitoring and automated response
- Proactive threat hunting
- Industry leadership on security (bug bounty, disclosure program)
- Security as competitive advantage in sales
- **Typical:** Public company or regulated enterprise
### Maturity Assessment Questions
1. Can you list all systems that process customer data right now?
2. How long would it take to detect if an admin credential was compromised?
3. When was your last backup tested with a restore?
4. Do developers run any security checks before code is deployed?
5. Does the board receive security reporting? What's in it?
Score: 0 = no/don't know, 1 = partially, 2 = yes/verified
- 0–3: Level 1–2
- 4–7: Level 2–3
- 8–10: Level 3–4
---
## 5. Board-Level Security Reporting
### What the Board Cares About
Boards are not interested in CVE counts or firewall rules. They care about:
1. **Risk posture:** Are we getting better or worse?
2. **Regulatory exposure:** What fines could we face?
3. **Incident readiness:** If we're breached, are we prepared?
4. **Competitive position:** Do customers trust us with their data?
5. **Budget adequacy:** Are we investing appropriately?
### Quarterly Board Security Report Structure
**Executive Summary (1 page max)**
- Security posture score vs. last quarter (directional trend matters more than absolute)
- Top 3 risks and their business impact in dollars
- Key accomplishments this quarter
- Investment requested (if any)
**Risk Dashboard**
```
Risk Register Summary:
├── Critical (>$500K ALE): [count] risks, [count] mitigated
├── High ($100K–$500K ALE): [count] risks, [count] mitigated
├── Medium ($10K–$100K ALE): [count] risks
└── Low (<$10K ALE): [count] risks (for awareness only)
Trend: ↑ Risk exposure vs. Q[n-1] / ↓ Risk exposure vs. Q[n-1]
```
**Compliance Status**
- Framework certifications in scope and current status
- Next audit date
- Any findings from last audit and remediation status
**Incident Summary**
- Security incidents last quarter (count and severity)
- Time to detect / time to respond (vs. targets)
- Any regulatory reporting obligations triggered
**Key Metrics (4–6 max)**
- MFA adoption rate
- Critical patch SLA compliance
- Phishing simulation click rate (trend)
- Vendor assessments completed
**Budget Summary**
- Spend vs. budget
- Headcount
- Next quarter key investments and rationale
### Common Board Questions to Prepare For
- "Have we been breached?" (Know your detection capability, not just your answer)
- "How do we compare to peers?" (Benchmarks from Verizon DBIR, industry ISACs)
- "What's the one thing we should invest in?" (Have a clear answer)
- "If we're acquired, what would security due diligence find?" (Be honest)
- "What keeps you up at night?" (Have a real answer, not a vague one)
---
## 6. Security as Revenue Enabler
### The Sales Angle
For B2B companies, security certifications directly impact revenue:
- Enterprise buyers require SOC 2 as table stakes (increasingly SOC 2 Type II)
- Government and healthcare require ISO 27001 or HIPAA
- Passing security questionnaires faster closes deals faster
- A breach costs 10–30% customer churn; security investment is churn prevention
**How to Measure:**
- Deals blocked by security questionnaire failures (track in CRM)
- Average security questionnaire turnaround time
- Customer security reviews passed vs. failed
- Revenue attributed to new compliance certifications
### The Trust Narrative
Position security certifications in marketing:
- SOC 2 Type II: "Independently audited security controls, verified annually"
- ISO 27001: "Internationally certified information security management"
- HIPAA BAA: "Healthcare data protection to regulatory standards"
These aren't just compliance — they're trust signals that compress the sales cycle.
FILE:scripts/compliance_tracker.py
#!/usr/bin/env python3
"""
CISO Compliance Tracker
========================
Tracks compliance requirements across SOC 2, ISO 27001, HIPAA, and GDPR.
Shows control overlaps, estimates effort and cost, and prioritizes by business value.
Usage:
python compliance_tracker.py # Run with sample data
python compliance_tracker.py --json # JSON output
python compliance_tracker.py --csv output.csv # Export CSV
python compliance_tracker.py --framework soc2 # Show single framework
python compliance_tracker.py --gap-analysis # Show unaddressed requirements
python compliance_tracker.py --roadmap # Show sequenced roadmap
"""
import json
import csv
import sys
import argparse
from datetime import datetime, date
from typing import Optional
# ─── Framework Definitions ───────────────────────────────────────────────────
FRAMEWORKS = {
"soc2": {
"name": "SOC 2 Type II",
"full_name": "AICPA Trust Service Criteria — Security",
"typical_timeline_months": 12,
"typical_cost_usd": 65_000, # Audit + platform
"annual_maintenance_usd": 40_000,
"business_value": "Enterprise sales unblock, US market table stakes",
"mandatory_for": ["B2B SaaS selling to enterprise US companies"],
},
"iso27001": {
"name": "ISO 27001:2022",
"full_name": "Information Security Management System",
"typical_timeline_months": 15,
"typical_cost_usd": 95_000,
"annual_maintenance_usd": 30_000,
"business_value": "EU enterprise sales, global credibility",
"mandatory_for": ["EU enterprise customers", "Government contracts"],
},
"hipaa": {
"name": "HIPAA",
"full_name": "Health Insurance Portability and Accountability Act",
"typical_timeline_months": 7,
"typical_cost_usd": 75_000,
"annual_maintenance_usd": 20_000,
"business_value": "Healthcare customer access, BAA execution",
"mandatory_for": ["Business Associates", "Companies handling PHI"],
},
"gdpr": {
"name": "GDPR",
"full_name": "General Data Protection Regulation (EU) 2016/679",
"typical_timeline_months": 5,
"typical_cost_usd": 45_000,
"annual_maintenance_usd": 15_000,
"business_value": "EU market access, legal compliance",
"mandatory_for": ["EU-based companies", "Any company with EU user data"],
},
}
# ─── Control Domain Library ──────────────────────────────────────────────────
def build_control_domain(
domain_id: str,
name: str,
description: str,
soc2_ref: Optional[str],
iso27001_ref: Optional[str],
hipaa_ref: Optional[str],
gdpr_ref: Optional[str],
effort_days: int, # Estimated implementation effort in person-days
cost_usd: int, # Estimated implementation cost (tooling + time)
implementation_notes: str,
status: str = "Not Started", # Not Started | In Progress | Implemented | Verified
owner: Optional[str] = None,
target_date: Optional[str] = None,
) -> dict:
"""Build a control domain record."""
frameworks_applicable = []
if soc2_ref:
frameworks_applicable.append("soc2")
if iso27001_ref:
frameworks_applicable.append("iso27001")
if hipaa_ref:
frameworks_applicable.append("hipaa")
if gdpr_ref:
frameworks_applicable.append("gdpr")
return {
"domain_id": domain_id,
"name": name,
"description": description,
"references": {
"soc2": soc2_ref,
"iso27001": iso27001_ref,
"hipaa": hipaa_ref,
"gdpr": gdpr_ref,
},
"frameworks_applicable": frameworks_applicable,
"framework_count": len(frameworks_applicable),
"effort_days": effort_days,
"cost_usd": cost_usd,
"implementation_notes": implementation_notes,
"status": status,
"owner": owner,
"target_date": target_date,
}
def load_control_library() -> list[dict]:
"""
Core control domains mapped across SOC 2, ISO 27001, HIPAA, and GDPR.
Each domain represents a logical grouping of controls.
"""
controls = []
controls.append(build_control_domain(
domain_id="IAM-001",
name="Identity and Access Management",
description=(
"Unique user identities, MFA enforcement, SSO, least privilege access, "
"role-based access control, access provisioning and de-provisioning workflows."
),
soc2_ref="CC6.1, CC6.2, CC6.3",
iso27001_ref="A.5.15, A.5.16, A.5.17, A.5.18",
hipaa_ref="§164.312(a)(2)(i), §164.308(a)(3)",
gdpr_ref="Art. 32(1)(b)",
effort_days=15,
cost_usd=25_000, # SSO + MFA tooling
implementation_notes=(
"Deploy IdP (Okta/Azure AD/Google Workspace). Enforce MFA on all applications. "
"Document access provisioning process. Implement quarterly access reviews."
),
status="In Progress",
owner="IT/Security",
))
controls.append(build_control_domain(
domain_id="ENC-001",
name="Encryption at Rest and in Transit",
description=(
"Encryption of sensitive data stored in databases, file systems, and backups. "
"TLS 1.2+ for all data in transit. Key management and rotation."
),
soc2_ref="CC6.7",
iso27001_ref="A.8.24",
hipaa_ref="§164.312(a)(2)(iv), §164.312(e)(2)(ii)",
gdpr_ref="Art. 32(1)(a)",
effort_days=10,
cost_usd=8_000,
implementation_notes=(
"Enable encryption at rest on all databases (RDS, S3, etc.). "
"Configure TLS on all services. Use KMS for key management. "
"Document encryption standards in a security policy."
),
status="Implemented",
owner="Engineering",
))
controls.append(build_control_domain(
domain_id="LOG-001",
name="Audit Logging and Monitoring",
description=(
"Comprehensive logging of user activity, system events, and security events. "
"Log integrity protection. SIEM or log aggregation. Alerting on anomalies."
),
soc2_ref="CC7.2, CC7.3",
iso27001_ref="A.8.15, A.8.16, A.8.17",
hipaa_ref="§164.312(b)",
gdpr_ref="Art. 32(1)(b)",
effort_days=20,
cost_usd=30_000, # SIEM tooling
implementation_notes=(
"Centralize logs from application, infrastructure, and cloud provider. "
"Define log retention (minimum 1 year). Set up alerting for authentication "
"failures, privilege escalation, data export events."
),
status="Not Started",
owner="DevOps/Security",
))
controls.append(build_control_domain(
domain_id="IR-001",
name="Incident Response",
description=(
"Documented incident response plan. Defined severity levels. Escalation procedures. "
"Communication templates. Annual tabletop exercise. Post-incident review process."
),
soc2_ref="CC7.3, CC7.4, CC7.5",
iso27001_ref="A.5.24, A.5.25, A.5.26, A.5.27, A.5.28",
hipaa_ref="§164.308(a)(6)",
gdpr_ref="Art. 33, Art. 34",
effort_days=12,
cost_usd=10_000,
implementation_notes=(
"Write IR plan covering detection, containment, eradication, recovery, communication. "
"Define breach notification timelines (GDPR: 72 hours, HIPAA: 60 days). "
"Run annual tabletop exercise. Retain IR firm on retainer."
),
status="In Progress",
owner="CISO",
))
controls.append(build_control_domain(
domain_id="VM-001",
name="Vulnerability Management and Patching",
description=(
"Regular vulnerability scanning of infrastructure and applications. "
"Defined patch SLAs by severity. Penetration testing program. "
"Dependency vulnerability scanning in CI/CD."
),
soc2_ref="CC7.1",
iso27001_ref="A.8.8",
hipaa_ref="§164.308(a)(1)(ii)(A)",
gdpr_ref="Art. 32(1)(d)",
effort_days=15,
cost_usd=20_000,
implementation_notes=(
"Deploy infrastructure scanner (Tenable, Qualys, AWS Inspector). "
"Add SAST/DAST to CI/CD pipeline. Define patch SLAs: Critical <24h, High <7d, "
"Medium <30d. Conduct annual pentest."
),
status="In Progress",
owner="DevOps/Security",
))
controls.append(build_control_domain(
domain_id="VRISK-001",
name="Vendor and Third-Party Risk Management",
description=(
"Inventory of all third-party vendors with data access. Tiered risk assessment "
"process. Contractual security requirements. Annual reviews for critical vendors."
),
soc2_ref="CC9.2",
iso27001_ref="A.5.19, A.5.20, A.5.21, A.5.22",
hipaa_ref="§164.308(b) Business Associate Agreements",
gdpr_ref="Art. 28 Data Processing Agreements",
effort_days=10,
cost_usd=8_000,
implementation_notes=(
"Build vendor inventory spreadsheet. Tier vendors (Tier 1: PII access, "
"Tier 2: business data, Tier 3: no data). Execute DPAs for all processors (GDPR). "
"Execute BAAs for PHI processors (HIPAA). Annual security questionnaire for Tier 1."
),
status="Not Started",
owner="Legal/Security",
))
controls.append(build_control_domain(
domain_id="RISK-001",
name="Risk Assessment and Treatment",
description=(
"Formal risk assessment methodology. Risk register maintained. "
"Risk treatment decisions documented. Annual risk review cycle."
),
soc2_ref="CC3.1, CC3.2, CC3.3, CC3.4",
iso27001_ref="Clause 6.1.2, 6.1.3",
hipaa_ref="§164.308(a)(1) Security Risk Analysis",
gdpr_ref="Art. 32, Art. 35 DPIA",
effort_days=15,
cost_usd=12_000,
implementation_notes=(
"Document risk methodology (FAIR, NIST, ISO 27005). Maintain risk register. "
"HIPAA: formal security risk analysis required — not optional. "
"GDPR: DPIA required for high-risk processing activities. Annual refresh."
),
status="Not Started",
owner="CISO",
))
controls.append(build_control_domain(
domain_id="TRAIN-001",
name="Security Awareness Training",
description=(
"Annual security awareness training for all employees. "
"Role-specific training for high-risk roles. Phishing simulations. "
"Training completion tracking."
),
soc2_ref="CC1.4",
iso27001_ref="A.6.3, A.6.8",
hipaa_ref="§164.308(a)(5)",
gdpr_ref="Art. 39(1)(b)",
effort_days=5,
cost_usd=8_000,
implementation_notes=(
"Deploy security training platform (KnowBe4, Proofpoint, etc.). "
"Annual training required — track completion (100% target). "
"Quarterly phishing simulations. Role-specific training for devs (secure coding), "
"finance (BEC), support (social engineering)."
),
status="Not Started",
owner="HR/Security",
))
controls.append(build_control_domain(
domain_id="CHGMGMT-001",
name="Change Management",
description=(
"Formal change management process for production changes. "
"Code review requirements. Deployment approvals. Rollback procedures. "
"Change log maintained."
),
soc2_ref="CC8.1",
iso27001_ref="A.8.32",
hipaa_ref="§164.312(c)(1) Integrity controls",
gdpr_ref="Art. 25 Privacy by design",
effort_days=10,
cost_usd=5_000,
implementation_notes=(
"Document change management policy. Require peer review for all production changes. "
"Maintain audit trail in version control. No direct production access — "
"all changes via CI/CD pipeline."
),
status="In Progress",
owner="Engineering",
))
controls.append(build_control_domain(
domain_id="BCP-001",
name="Business Continuity and Disaster Recovery",
description=(
"Business continuity plan. Disaster recovery plan with defined RTO/RPO. "
"Backup procedures with tested restores. Failover capabilities."
),
soc2_ref="A1.1, A1.2, A1.3",
iso27001_ref="A.5.29, A.5.30",
hipaa_ref="§164.308(a)(7) Contingency Plan",
gdpr_ref="Art. 32(1)(c)",
effort_days=12,
cost_usd=15_000,
implementation_notes=(
"Define RTO (<4 hours) and RPO (<1 hour) targets. Configure automated backups. "
"Test restore quarterly — paper backups that aren't tested aren't backups. "
"Document DR runbook. Annual DR exercise."
),
status="In Progress",
owner="DevOps",
))
controls.append(build_control_domain(
domain_id="ASSET-001",
name="Asset Inventory and Classification",
description=(
"Complete inventory of hardware, software, and data assets. "
"Data classification scheme. Ownership assigned to all assets. "
"Regular reconciliation."
),
soc2_ref="CC6.1",
iso27001_ref="A.5.9, A.5.10, A.5.11, A.5.12, A.5.13",
hipaa_ref="§164.310(d) Device and Media Controls",
gdpr_ref="Art. 30 Records of Processing Activities",
effort_days=8,
cost_usd=5_000,
implementation_notes=(
"Build asset register (CMDB or spreadsheet at minimum). "
"Classify data: Public, Internal, Confidential, Restricted. "
"GDPR requires RoPA (Record of Processing Activities) — data map of all PII. "
"ISO 27001 requires SoA referencing asset inventory."
),
status="Not Started",
owner="IT/Security",
))
controls.append(build_control_domain(
domain_id="ENDPOINT-001",
name="Endpoint Security",
description=(
"EDR/antivirus on all managed endpoints. Device management (MDM). "
"Full disk encryption. Patch management. BYOD policy."
),
soc2_ref="CC6.8",
iso27001_ref="A.8.1, A.8.7",
hipaa_ref="§164.310(a)(2)(iv) Workstation security",
gdpr_ref="Art. 32(1)(a)",
effort_days=8,
cost_usd=20_000,
implementation_notes=(
"Deploy EDR (CrowdStrike, SentinelOne, or Microsoft Defender for Business). "
"Enable full disk encryption (FileVault/BitLocker). "
"MDM for device management. BYOD policy documented."
),
status="In Progress",
owner="IT",
))
controls.append(build_control_domain(
domain_id="POLICY-001",
name="Security Policies and Procedures",
description=(
"Documented security policies covering acceptable use, access control, "
"incident response, data classification, vendor management, etc. "
"Annual review cycle. Employee attestation."
),
soc2_ref="CC1.2, CC1.3",
iso27001_ref="A.5.1, A.5.2",
hipaa_ref="§164.308(a)(1) Security Management Process",
gdpr_ref="Art. 24 Responsibility of the controller",
effort_days=15,
cost_usd=10_000,
implementation_notes=(
"Minimum policy set: Information Security Policy, Acceptable Use, "
"Access Control, Incident Response, Data Classification, Password, "
"Change Management, Vendor Management, Business Continuity. "
"Use policy templates from GRC platform (Vanta/Drata)."
),
status="In Progress",
owner="CISO",
))
controls.append(build_control_domain(
domain_id="PRIV-001",
name="Privacy and Data Subject Rights",
description=(
"Privacy policy and notices. Data subject rights fulfilment process "
"(access, erasure, portability). Consent management. Cookie compliance. "
"Privacy by design in product development."
),
soc2_ref=None, # Not a SOC 2 requirement (unless Privacy TSC selected)
iso27001_ref="A.5.34",
hipaa_ref="§164.524 Access, §164.528 Accounting of Disclosures",
gdpr_ref="Art. 13, 14, 15–22 (Rights), Art. 25",
effort_days=20,
cost_usd=15_000,
implementation_notes=(
"GDPR: Update privacy policy, implement DSAR process (30-day SLA), "
"build deletion capability into product. Cookie consent (PECR/ePrivacy). "
"HIPAA: Patient rights for PHI access. "
"Consider OneTrust, Termly, or CookieYes for consent management."
),
status="Not Started",
owner="Legal/Product",
))
controls.append(build_control_domain(
domain_id="NET-001",
name="Network Security and Segmentation",
description=(
"Network segmentation (production vs. development vs. corporate). "
"Firewall rules. Intrusion detection. VPN or ZTNA for remote access."
),
soc2_ref="CC6.6, CC6.7",
iso27001_ref="A.8.20, A.8.21, A.8.22",
hipaa_ref="§164.312(e)(1) Transmission security",
gdpr_ref="Art. 32(1)(a)",
effort_days=12,
cost_usd=18_000,
implementation_notes=(
"Segment production from development. WAF in front of public applications. "
"Replace VPN with ZTNA for remote access (Series B+ consideration). "
"DDoS protection (Cloudflare or AWS Shield)."
),
status="In Progress",
owner="DevOps",
))
controls.append(build_control_domain(
domain_id="PENTEST-001",
name="Penetration Testing",
description=(
"Annual external penetration test by qualified third-party firm. "
"Finding remediation tracking. Results reviewed by leadership."
),
soc2_ref="CC7.1",
iso27001_ref="A.8.8",
hipaa_ref="§164.308(a)(8) Evaluation",
gdpr_ref="Art. 32(1)(d)",
effort_days=5,
cost_usd=25_000,
implementation_notes=(
"Scope: external attack surface, application, API, and optionally social engineering. "
"Budget $15–35K for a reputable firm. Track findings in risk register. "
"Re-test critical findings within 90 days. Share pentest summary with enterprise "
"customers on request (under NDA)."
),
status="Not Started",
owner="CISO",
))
return controls
# ─── Analysis ────────────────────────────────────────────────────────────────
def calculate_framework_coverage(controls: list[dict]) -> dict:
"""Calculate per-framework coverage statistics."""
coverage = {}
for fw in FRAMEWORKS:
applicable = [c for c in controls if fw in c["frameworks_applicable"]]
implemented = [c for c in applicable if c["status"] in ("Implemented", "Verified")]
in_progress = [c for c in applicable if c["status"] == "In Progress"]
not_started = [c for c in applicable if c["status"] == "Not Started"]
total_effort = sum(c["effort_days"] for c in applicable)
remaining_effort = sum(
c["effort_days"] for c in applicable
if c["status"] not in ("Implemented", "Verified")
)
total_cost = sum(c["cost_usd"] for c in applicable)
remaining_cost = sum(
c["cost_usd"] for c in applicable
if c["status"] not in ("Implemented", "Verified")
)
pct_complete = (len(implemented) / len(applicable) * 100) if applicable else 0
coverage[fw] = {
"framework": FRAMEWORKS[fw]["name"],
"total_controls": len(applicable),
"implemented": len(implemented),
"in_progress": len(in_progress),
"not_started": len(not_started),
"pct_complete": pct_complete,
"total_effort_days": total_effort,
"remaining_effort_days": remaining_effort,
"total_cost_usd": total_cost,
"remaining_cost_usd": remaining_cost,
"gap_controls": [c["name"] for c in not_started],
}
return coverage
def find_high_leverage_controls(controls: list[dict]) -> list[dict]:
"""Controls that satisfy the most frameworks — highest ROI to implement."""
multi_fw = [c for c in controls if c["framework_count"] >= 3
and c["status"] not in ("Implemented", "Verified")]
return sorted(multi_fw, key=lambda c: (-c["framework_count"], c["effort_days"]))
def estimate_roadmap(controls: list[dict], target_frameworks: list[str]) -> list[dict]:
"""
Generate an ordered implementation roadmap for target frameworks.
Prioritize: (1) controls blocking most frameworks, (2) quick wins (low effort).
"""
applicable = [c for c in controls
if any(fw in c["frameworks_applicable"] for fw in target_frameworks)
and c["status"] not in ("Implemented", "Verified")]
# Score: (frameworks_covered × 10) - (effort_days) → higher is better
for c in applicable:
fw_overlap = len([fw for fw in target_frameworks if fw in c["frameworks_applicable"]])
c["_priority_score"] = (fw_overlap * 10) - c["effort_days"]
return sorted(applicable, key=lambda c: -c["_priority_score"])
def fmt_dollars(amount: float) -> str:
if amount >= 1_000_000:
return f".1fM"
if amount >= 1_000:
return f".0fK"
return f".0f"
def status_icon(status: str) -> str:
icons = {
"Implemented": "✅",
"Verified": "✅",
"In Progress": "🔄",
"Not Started": "⬜",
"Planned": "📋",
}
return icons.get(status, "❓")
# ─── Display ─────────────────────────────────────────────────────────────────
def print_header():
print("\n" + "=" * 80)
print(" CISO COMPLIANCE TRACKER — Multi-Framework Coverage")
print(f" Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
print("=" * 80)
def print_framework_summary(coverage: dict):
print("\n📋 FRAMEWORK COVERAGE SUMMARY")
print("-" * 80)
header = f"{'Framework':<20} {'Done':<6} {'WIP':<5} {'Gap':<5} {'Complete':<10} {'Remain Cost':<14} {'Remain Days'}"
print(header)
print("-" * 80)
for fw_id, data in coverage.items():
pct = f"{data['pct_complete']:.0f}%"
print(
f"{data['framework']:<20} {data['implemented']:<6} {data['in_progress']:<5} "
f"{data['not_started']:<5} {pct:<10} {fmt_dollars(data['remaining_cost_usd']):<14} "
f"{data['remaining_effort_days']} days"
)
def print_control_table(controls: list[dict], framework_filter: Optional[str] = None):
filtered = controls
if framework_filter:
filtered = [c for c in controls if framework_filter in c["frameworks_applicable"]]
title = f"CONTROL DOMAINS"
if framework_filter:
title += f" — {FRAMEWORKS[framework_filter]['name']}"
print(f"\n🔧 {title}")
print("-" * 90)
header = f"{'ID':<14} {'Control Name':<30} {'Frameworks':<8} {'Effort':<8} {'Cost':<10} {'Status'}"
print(header)
print("-" * 90)
for c in filtered:
fw_badges = "/".join(
fw.upper()[:3] for fw in ["soc2", "iso27001", "hipaa", "gdpr"]
if fw in c["frameworks_applicable"]
)
icon = status_icon(c["status"])
print(
f"{c['domain_id']:<14} {c['name'][:29]:<30} {fw_badges:<8} "
f"{c['effort_days']:>3}d {fmt_dollars(c['cost_usd']):<10} {icon} {c['status']}"
)
def print_gap_analysis(coverage: dict):
print("\n⚠️ GAP ANALYSIS — Controls Not Yet Started")
print("-" * 70)
for fw_id, data in coverage.items():
if data["gap_controls"]:
print(f"\n {data['framework']} — {len(data['gap_controls'])} gaps:")
for gap in data["gap_controls"]:
print(f" • {gap}")
def print_high_leverage(controls: list[dict]):
hl = find_high_leverage_controls(controls)
print(f"\n🎯 HIGH-LEVERAGE CONTROLS — Implement Once, Satisfy Multiple Frameworks")
print("-" * 70)
print(f"{'Control':<30} {'Frameworks':<35} {'Effort':<8} {'Cost'}")
print("-" * 70)
for c in hl:
fw_list = " + ".join(FRAMEWORKS[fw]["name"] for fw in c["frameworks_applicable"])
print(
f"{c['name'][:29]:<30} {fw_list[:34]:<35} "
f"{c['effort_days']:>3}d {fmt_dollars(c['cost_usd'])}"
)
def print_roadmap(controls: list[dict], target_frameworks: list[str]):
ordered = estimate_roadmap(controls, target_frameworks)
fw_names = " + ".join(FRAMEWORKS[fw]["name"] for fw in target_frameworks)
print(f"\n🗺️ IMPLEMENTATION ROADMAP — {fw_names}")
print("-" * 80)
print("Priority order: most framework coverage first, then quick wins")
print()
cumulative_days = 0
cumulative_cost = 0
for i, c in enumerate(ordered, 1):
cumulative_days += c["effort_days"]
cumulative_cost += c["cost_usd"]
fw_badges = ", ".join(
FRAMEWORKS[fw]["name"] for fw in target_frameworks
if fw in c["frameworks_applicable"]
)
print(f" {i:>2}. {c['name']}")
print(f" Frameworks: {fw_badges}")
print(f" Effort: {c['effort_days']} days | Cost: {fmt_dollars(c['cost_usd'])} "
f"| Cumulative: {cumulative_days}d / {fmt_dollars(cumulative_cost)}")
if c.get("owner"):
print(f" Owner: {c['owner']}")
print()
def print_framework_profiles():
print("\n💼 FRAMEWORK PROFILES")
print("-" * 70)
for fw_id, fw in FRAMEWORKS.items():
print(f"\n {fw['name']} ({fw_id.upper()})")
print(f" Timeline: ~{fw['typical_timeline_months']} months")
print(f" First-year cost: {fmt_dollars(fw['typical_cost_usd'])}")
print(f" Annual maintenance: {fmt_dollars(fw['annual_maintenance_usd'])}/yr")
print(f" Business value: {fw['business_value']}")
print(f" Required for: {', '.join(fw['mandatory_for'])}")
def export_csv(controls: list[dict], filepath: str):
fields = [
"domain_id", "name", "frameworks_applicable", "framework_count",
"effort_days", "cost_usd", "status", "owner", "target_date",
"soc2_ref", "iso27001_ref", "hipaa_ref", "gdpr_ref", "implementation_notes"
]
with open(filepath, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
for c in controls:
row = {k: c.get(k, "") for k in fields}
row["frameworks_applicable"] = ", ".join(c["frameworks_applicable"])
row["soc2_ref"] = c["references"].get("soc2", "")
row["iso27001_ref"] = c["references"].get("iso27001", "")
row["hipaa_ref"] = c["references"].get("hipaa", "")
row["gdpr_ref"] = c["references"].get("gdpr", "")
writer.writerow(row)
print(f"✅ Exported {len(controls)} controls to {filepath}")
# ─── Main ────────────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser(
description="CISO Compliance Tracker — Multi-framework coverage and roadmap"
)
parser.add_argument("--json", action="store_true", help="Output JSON")
parser.add_argument("--csv", metavar="FILE", help="Export CSV to file")
parser.add_argument(
"--framework", metavar="FRAMEWORK",
choices=list(FRAMEWORKS.keys()),
help="Filter to single framework (soc2, iso27001, hipaa, gdpr)"
)
parser.add_argument("--gap-analysis", action="store_true", help="Show gap analysis")
parser.add_argument("--roadmap", metavar="FRAMEWORKS",
help="Sequenced roadmap for frameworks e.g. 'soc2,iso27001'")
parser.add_argument("--profiles", action="store_true", help="Show framework profiles")
parser.add_argument("--leverage", action="store_true", help="Show high-leverage controls")
args = parser.parse_args()
controls = load_control_library()
coverage = calculate_framework_coverage(controls)
if args.json:
output = {
"generated": datetime.now().isoformat(),
"frameworks": FRAMEWORKS,
"coverage": coverage,
"controls": controls,
}
print(json.dumps(output, indent=2, default=str))
return
if args.csv:
export_csv(controls, args.csv)
return
print_header()
if args.profiles:
print_framework_profiles()
return
if args.roadmap:
target_fws = [fw.strip() for fw in args.roadmap.split(",") if fw.strip() in FRAMEWORKS]
if not target_fws:
print(f"Unknown frameworks. Valid: {', '.join(FRAMEWORKS.keys())}")
sys.exit(1)
print_framework_summary(coverage)
print_roadmap(controls, target_fws)
return
print_framework_summary(coverage)
print_control_table(controls, args.framework)
if args.gap_analysis:
print_gap_analysis(coverage)
if args.leverage:
print_high_leverage(controls)
if not any([args.framework, args.gap_analysis, args.leverage]):
print_high_leverage(controls)
print_gap_analysis(coverage)
print("\n💡 NEXT STEPS")
print(" --roadmap soc2,iso27001 Priority order for dual-framework")
print(" --framework hipaa HIPAA-only control view")
print(" --gap-analysis What's not started")
print(" --leverage Controls covering most frameworks")
print(" --profiles Framework timelines and costs")
print(" --csv controls.csv Export for stakeholder review")
print()
if __name__ == "__main__":
main()
FILE:scripts/risk_quantifier.py
#!/usr/bin/env python3
"""
CISO Risk Quantifier
====================
Quantifies security risks in business terms using the FAIR model.
Calculates ALE (Annual Loss Expectancy) and prioritizes by expected annual loss.
Usage:
python risk_quantifier.py # Run with sample data
python risk_quantifier.py --json # Output JSON
python risk_quantifier.py --csv output.csv # Export CSV
python risk_quantifier.py --budget 500000 # Show what fits in budget
python risk_quantifier.py --add # Interactive risk entry
"""
import json
import csv
import sys
import os
import argparse
from datetime import datetime
from typing import Optional
# ─── Data Model ─────────────────────────────────────────────────────────────
RISK_CATEGORIES = [
"Data Breach",
"Ransomware / Extortion",
"Insider Threat",
"Third-Party / Supply Chain",
"Application Vulnerability",
"Cloud Misconfiguration",
"Social Engineering",
"Physical Security",
"Business Email Compromise",
"DDoS / Availability",
]
BUSINESS_IMPACT_TYPES = [
"Revenue Loss",
"Regulatory Fine",
"Legal / Litigation",
"Reputational Damage",
"Recovery / Remediation Cost",
"Customer Churn",
"Business Interruption",
]
MITIGATION_STATUSES = ["None", "Planned", "In Progress", "Mitigated", "Accepted"]
def build_risk(
name: str,
category: str,
description: str,
asset_value: float,
exposure_factor: float, # 0.0–1.0: fraction of asset value lost in breach
annual_rate: float, # ARO: expected incidents per year (0.01 = once per 100 years)
mitigation_cost: float,
mitigation_effectiveness: float, # 0.0–1.0: fraction of risk reduced by control
mitigation_status: str,
business_impacts: dict, # {impact_type: dollar_amount}
notes: str = "",
) -> dict:
"""Construct a risk record with calculated metrics."""
sle = asset_value * exposure_factor # Single Loss Expectancy
ale = sle * annual_rate # Annual Loss Expectancy (inherent)
mitigated_ale = ale * (1 - mitigation_effectiveness) # Residual after mitigation
mitigation_roi = ((ale - mitigated_ale - mitigation_cost) / mitigation_cost * 100
if mitigation_cost > 0 else 0)
total_business_impact = sum(business_impacts.values())
return {
"name": name,
"category": category,
"description": description,
"asset_value": asset_value,
"exposure_factor": exposure_factor,
"annual_rate": annual_rate,
"mitigation_cost": mitigation_cost,
"mitigation_effectiveness": mitigation_effectiveness,
"mitigation_status": mitigation_status,
"business_impacts": business_impacts,
"notes": notes,
# Calculated
"sle": sle,
"ale": ale,
"mitigated_ale": mitigated_ale,
"mitigation_roi_pct": mitigation_roi,
"total_business_impact": total_business_impact,
"priority_score": ale, # Primary sort key
}
# ─── Sample Data ─────────────────────────────────────────────────────────────
def load_sample_risks() -> list[dict]:
"""
Sample risk register for a Series B SaaS company with ~$15M ARR,
~50K customer records, B2B enterprise focus.
"""
risks = []
risks.append(build_risk(
name="Customer Database Breach",
category="Data Breach",
description=(
"Unauthorized access to production database containing 50K+ customer records "
"including PII (name, email, company, payment method). Attack vector: SQL injection, "
"compromised credentials, or insider access."
),
asset_value=5_000_000, # Value of customer database (revenue impact + regulatory)
exposure_factor=0.30, # ~30% of asset value lost in a breach event
annual_rate=0.12, # ~12% chance per year (based on Verizon DBIR industry data)
mitigation_cost=45_000, # WAF + DAST + DB activity monitoring annual cost
mitigation_effectiveness=0.80,
mitigation_status="In Progress",
business_impacts={
"Regulatory Fine": 85_000, # GDPR/CCPA exposure
"Legal / Litigation": 150_000, # Class action exposure
"Customer Churn": 300_000, # Lost ARR from breach-triggered churn
"Reputational Damage": 200_000, # Brand impact / deal loss
"Recovery / Remediation Cost": 65_000,
},
notes="SOC 2 Type II controls partially address. Next step: DB activity monitoring.",
))
risks.append(build_risk(
name="Ransomware Attack",
category="Ransomware / Extortion",
description=(
"Ransomware encrypts production systems. Average ransom demand for a "
"Series B company is $350K–$800K. Recovery without ransom payment: 2–6 weeks downtime. "
"Attack vector: phishing email with malicious attachment, RDP exposure."
),
asset_value=3_500_000,
exposure_factor=0.25,
annual_rate=0.15,
mitigation_cost=60_000, # EDR + email security + backup hardening
mitigation_effectiveness=0.85,
mitigation_status="Planned",
business_impacts={
"Business Interruption": 450_000, # 4 weeks downtime × $112K/week revenue
"Recovery / Remediation Cost": 180_000,
"Customer Churn": 125_000,
"Revenue Loss": 75_000,
},
notes="Offline, tested backups reduce recovery time and eliminate ransom pressure.",
))
risks.append(build_risk(
name="Privileged Insider Data Theft",
category="Insider Threat",
description=(
"Disgruntled or financially motivated employee with elevated access exfiltrates "
"customer data, IP, or trade secrets. Detection is typically slow (median: 197 days "
"per IBM Cost of Data Breach Report)."
),
asset_value=2_800_000,
exposure_factor=0.20,
annual_rate=0.08,
mitigation_cost=35_000, # DLP + UEBA + PAM
mitigation_effectiveness=0.65,
mitigation_status="None",
business_impacts={
"Legal / Litigation": 120_000,
"Customer Churn": 90_000,
"Reputational Damage": 75_000,
"Recovery / Remediation Cost": 40_000,
},
notes="No DLP or UEBA currently deployed. Highest detection gap.",
))
risks.append(build_risk(
name="Critical SaaS Vendor Breach (Supply Chain)",
category="Third-Party / Supply Chain",
description=(
"A critical SaaS vendor (e.g., Salesforce, Slack, AWS, GitHub) suffers a breach "
"that compromises data entrusted to them or disrupts your operations. You have "
"limited control but full liability to customers."
),
asset_value=2_200_000,
exposure_factor=0.15,
annual_rate=0.18,
mitigation_cost=20_000, # Vendor risk assessment program
mitigation_effectiveness=0.40, # Limited — you can't control vendor security
mitigation_status="Planned",
business_impacts={
"Business Interruption": 95_000,
"Customer Churn": 75_000,
"Reputational Damage": 50_000,
"Recovery / Remediation Cost": 30_000,
},
notes="Third-party risk is partially transferable via contractual SLAs and cyber insurance.",
))
risks.append(build_risk(
name="Business Email Compromise (BEC)",
category="Business Email Compromise",
description=(
"Attacker impersonates CEO, CFO, or vendor to redirect wire transfers, gift card "
"purchases, or payroll. Median BEC loss: $125K. FBI IC3 reports BEC as #1 "
"cybercrime by financial loss."
),
asset_value=500_000,
exposure_factor=0.40,
annual_rate=0.30,
mitigation_cost=12_000, # Email authentication (DMARC) + training + callback procedures
mitigation_effectiveness=0.90,
mitigation_status="In Progress",
business_impacts={
"Revenue Loss": 125_000, # Direct financial theft (often unrecoverable)
"Recovery / Remediation Cost": 25_000,
"Legal / Litigation": 15_000,
},
notes="DMARC deployed. Need to enforce wire transfer callback procedures.",
))
risks.append(build_risk(
name="Cloud Misconfiguration — S3 / Storage Exposure",
category="Cloud Misconfiguration",
description=(
"Public exposure of S3 buckets, GCS buckets, or Azure Blob storage containing "
"sensitive data. One of the most common causes of data breaches. Often undetected "
"for months. 2023 IBM study: 82% of breaches involved data stored in cloud."
),
asset_value=1_800_000,
exposure_factor=0.20,
annual_rate=0.20,
mitigation_cost=18_000, # CSPM tool + IaC scanning
mitigation_effectiveness=0.90,
mitigation_status="Planned",
business_impacts={
"Regulatory Fine": 60_000,
"Reputational Damage": 120_000,
"Legal / Litigation": 45_000,
"Recovery / Remediation Cost": 35_000,
},
notes="No CSPM currently. High frequency, high detectability, low mitigation cost.",
))
risks.append(build_risk(
name="Credential Stuffing — Customer Accounts",
category="Application Vulnerability",
description=(
"Attackers use leaked credential lists to compromise customer accounts. "
"Account takeover leads to data theft, fraudulent transactions, and support burden. "
"16 billion credentials available on darknet as of 2024."
),
asset_value=1_200_000,
exposure_factor=0.12,
annual_rate=0.40,
mitigation_cost=15_000, # MFA + rate limiting + bot detection
mitigation_effectiveness=0.95,
mitigation_status="In Progress",
business_impacts={
"Customer Churn": 80_000,
"Revenue Loss": 45_000,
"Recovery / Remediation Cost": 19_000,
"Reputational Damage": 30_000,
},
notes="MFA available but optional. Enforcing MFA cuts this risk by ~99%.",
))
risks.append(build_risk(
name="Phishing — Employee Credential Compromise",
category="Social Engineering",
description=(
"Employee clicks phishing link, surrenders credentials. Without MFA, "
"this provides full access to email, SaaS apps, and potentially production. "
"Phishing is the #1 attack vector in the Verizon DBIR."
),
asset_value=1_500_000,
exposure_factor=0.15,
annual_rate=0.35,
mitigation_cost=25_000, # MFA + security awareness training + email security
mitigation_effectiveness=0.92,
mitigation_status="In Progress",
business_impacts={
"Business Interruption": 65_000,
"Customer Churn": 55_000,
"Recovery / Remediation Cost": 45_000,
"Reputational Damage": 60_000,
},
notes="Primary vector for ransomware and BEC. MFA is the single highest-ROI control.",
))
risks.append(build_risk(
name="Application API Vulnerability",
category="Application Vulnerability",
description=(
"Unauthenticated or improperly authorized API endpoint exposes customer data "
"or administrative functions. OWASP API Security Top 10 — broken object-level "
"authorization is the most common API vulnerability."
),
asset_value=2_000_000,
exposure_factor=0.18,
annual_rate=0.15,
mitigation_cost=30_000, # DAST + API gateway + code review
mitigation_effectiveness=0.75,
mitigation_status="Planned",
business_impacts={
"Regulatory Fine": 70_000,
"Customer Churn": 90_000,
"Reputational Damage": 100_000,
"Legal / Litigation": 60_000,
},
notes="Need automated API security testing in CI/CD pipeline.",
))
risks.append(build_risk(
name="DDoS Attack — Production Service",
category="DDoS / Availability",
description=(
"Distributed denial-of-service attack renders production service unavailable. "
"Average DDoS duration: 4–8 hours. Enterprise SLA breach triggers contractual "
"penalties. Increasingly used as extortion or distraction tactic."
),
asset_value=1_000_000,
exposure_factor=0.10,
annual_rate=0.25,
mitigation_cost=15_000, # CDN with DDoS protection (Cloudflare, AWS Shield)
mitigation_effectiveness=0.85,
mitigation_status="Mitigated",
business_impacts={
"Business Interruption": 45_000,
"Customer Churn": 30_000,
"Revenue Loss": 25_000,
},
notes="Cloudflare deployed. Residual risk from very large volumetric attacks.",
))
return risks
# ─── Analysis & Reporting ────────────────────────────────────────────────────
def calculate_portfolio_summary(risks: list[dict]) -> dict:
"""Aggregate portfolio-level metrics."""
total_inherent_ale = sum(r["ale"] for r in risks)
total_mitigated_ale = sum(r["mitigated_ale"] for r in risks)
total_mitigation_cost = sum(r["mitigation_cost"] for r in risks)
risk_reduction = total_inherent_ale - total_mitigated_ale
portfolio_roi = ((risk_reduction - total_mitigation_cost) / total_mitigation_cost * 100
if total_mitigation_cost > 0 else 0)
by_category = {}
for r in risks:
cat = r["category"]
if cat not in by_category:
by_category[cat] = {"count": 0, "total_ale": 0.0}
by_category[cat]["count"] += 1
by_category[cat]["total_ale"] += r["ale"]
by_status = {}
for r in risks:
status = r["mitigation_status"]
by_status[status] = by_status.get(status, 0) + 1
return {
"total_risks": len(risks),
"total_inherent_ale": total_inherent_ale,
"total_mitigated_ale": total_mitigated_ale,
"total_risk_reduction": risk_reduction,
"total_mitigation_cost": total_mitigation_cost,
"portfolio_roi_pct": portfolio_roi,
"by_category": dict(sorted(by_category.items(), key=lambda x: -x[1]["total_ale"])),
"by_mitigation_status": by_status,
}
def prioritize_risks(risks: list[dict], budget: Optional[float] = None) -> list[dict]:
"""Return risks sorted by ALE. If budget given, show what fits."""
sorted_risks = sorted(risks, key=lambda r: -r["ale"])
if budget is None:
return sorted_risks
# Greedy budget allocation by ROI
actionable = [r for r in sorted_risks if r["mitigation_status"] in ("None", "Planned")
and r["mitigation_cost"] > 0]
actionable.sort(key=lambda r: -r["mitigation_roi_pct"])
allocated = []
remaining = budget
for risk in actionable:
if risk["mitigation_cost"] <= remaining:
allocated.append(risk)
remaining -= risk["mitigation_cost"]
return allocated
def fmt_dollars(amount: float) -> str:
"""Format a dollar amount."""
if amount >= 1_000_000:
return f".2fM"
if amount >= 1_000:
return f".0fK"
return f".0f"
def fmt_pct(value: float) -> str:
return f"{value:.1f}%"
def severity_label(ale: float) -> str:
if ale >= 200_000:
return "CRITICAL"
if ale >= 75_000:
return "HIGH"
if ale >= 25_000:
return "MEDIUM"
return "LOW"
def severity_color(label: str) -> str:
"""ANSI color codes."""
colors = {
"CRITICAL": "\033[91m", # Red
"HIGH": "\033[93m", # Yellow
"MEDIUM": "\033[94m", # Blue
"LOW": "\033[92m", # Green
}
return colors.get(label, "") + label + "\033[0m"
# ─── Display ─────────────────────────────────────────────────────────────────
def print_header():
print("\n" + "=" * 80)
print(" CISO RISK QUANTIFIER — Security Risk Portfolio")
print(f" Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
print("=" * 80)
def print_portfolio_summary(summary: dict):
print("\n📊 PORTFOLIO SUMMARY")
print("-" * 60)
print(f" Total risks tracked: {summary['total_risks']}")
print(f" Total inherent ALE: {fmt_dollars(summary['total_inherent_ale'])}/yr")
print(f" Total ALE after mitigations: {fmt_dollars(summary['total_mitigated_ale'])}/yr")
print(f" Risk reduction from controls: {fmt_dollars(summary['total_risk_reduction'])}/yr")
print(f" Total mitigation spend: {fmt_dollars(summary['total_mitigation_cost'])}/yr")
print(f" Portfolio ROI: {fmt_pct(summary['portfolio_roi_pct'])}")
print()
print(" Risk by Category (sorted by ALE):")
for cat, data in summary["by_category"].items():
print(f" {cat:<35} {data['count']} risks ALE: {fmt_dollars(data['total_ale'])}/yr")
print()
print(" Mitigation Status:")
for status, count in summary["by_mitigation_status"].items():
print(f" {status:<20} {count} risks")
def print_risk_table(risks: list[dict], title: str = "RISK REGISTER"):
print(f"\n🎯 {title}")
print("-" * 80)
header = f"{'#':<3} {'Risk Name':<35} {'Severity':<10} {'ALE/yr':<12} {'Mitig Cost':<12} {'ROI':<8} {'Status':<12}"
print(header)
print("-" * 80)
for i, risk in enumerate(risks, 1):
sev = severity_label(risk["ale"])
sev_str = sev.ljust(10)
roi = fmt_pct(risk["mitigation_roi_pct"]) if risk["mitigation_cost"] > 0 else "N/A"
print(
f"{i:<3} {risk['name'][:34]:<35} {sev_str} "
f"{fmt_dollars(risk['ale']):<12} {fmt_dollars(risk['mitigation_cost']):<12} "
f"{roi:<8} {risk['mitigation_status']}"
)
def print_risk_detail(risk: dict, index: int):
sev = severity_label(risk["ale"])
print(f"\n{'─' * 70}")
print(f" #{index} — {risk['name']} [{sev}]")
print(f"{'─' * 70}")
print(f" Category: {risk['category']}")
print(f" Description: {risk['description'][:120]}...")
print()
print(f" RISK CALCULATION:")
print(f" Asset Value: {fmt_dollars(risk['asset_value'])}")
print(f" Exposure Factor: {fmt_pct(risk['exposure_factor'] * 100)}")
print(f" Single Loss Expectancy: {fmt_dollars(risk['sle'])}")
print(f" Annual Rate (ARO): {risk['annual_rate']:.2f}x/year")
print(f" Annual Loss Expectancy: {fmt_dollars(risk['ale'])}/yr ← INHERENT RISK")
print()
print(f" MITIGATION:")
print(f" Mitigation Cost: {fmt_dollars(risk['mitigation_cost'])}/yr")
print(f" Effectiveness: {fmt_pct(risk['mitigation_effectiveness'] * 100)}")
print(f" Residual ALE: {fmt_dollars(risk['mitigated_ale'])}/yr")
print(f" Mitigation ROI: {fmt_pct(risk['mitigation_roi_pct'])}")
print(f" Status: {risk['mitigation_status']}")
print()
print(f" BUSINESS IMPACT BREAKDOWN:")
for impact_type, amount in risk["business_impacts"].items():
print(f" {impact_type:<30} {fmt_dollars(amount)}")
print(f" {'TOTAL':<30} {fmt_dollars(risk['total_business_impact'])}")
if risk["notes"]:
print(f"\n NOTES: {risk['notes']}")
def print_board_summary(risks: list[dict], summary: dict):
"""One-page board-ready summary."""
print("\n" + "═" * 80)
print(" BOARD SECURITY REPORT — Risk Summary")
print("═" * 80)
critical = [r for r in risks if severity_label(r["ale"]) == "CRITICAL"]
high = [r for r in risks if severity_label(r["ale"]) == "HIGH"]
medium = [r for r in risks if severity_label(r["ale"]) == "MEDIUM"]
low = [r for r in risks if severity_label(r["ale"]) == "LOW"]
print(f"\n RISK EXPOSURE SUMMARY")
print(f" ┌─────────────┬────────┬──────────────┐")
print(f" │ Severity │ Count │ Total ALE/yr │")
print(f" ├─────────────┼────────┼──────────────┤")
for label, group in [("Critical", critical), ("High", high), ("Medium", medium), ("Low", low)]:
ale = sum(r["ale"] for r in group)
print(f" │ {label:<11} │ {len(group):<6} │ {fmt_dollars(ale):<12} │")
print(f" └─────────────┴────────┴──────────────┘")
print(f"\n TOTAL INHERENT RISK: {fmt_dollars(summary['total_inherent_ale'])}/yr")
print(f" SECURITY INVESTMENT: {fmt_dollars(summary['total_mitigation_cost'])}/yr")
print(f" RESIDUAL RISK: {fmt_dollars(summary['total_mitigated_ale'])}/yr")
print(f" RISK REDUCTION: {fmt_dollars(summary['total_risk_reduction'])}/yr")
print(f" PORTFOLIO ROI: {fmt_pct(summary['portfolio_roi_pct'])}")
print(f"\n TOP 3 RISKS BY EXPECTED ANNUAL LOSS:")
top3 = sorted(risks, key=lambda r: -r["ale"])[:3]
for i, risk in enumerate(top3, 1):
print(f" {i}. {risk['name']}: {fmt_dollars(risk['ale'])}/yr expected annual loss")
print(f" Mitigation: {fmt_dollars(risk['mitigation_cost'])}/yr | "
f"Status: {risk['mitigation_status']}")
unmitigated = [r for r in risks if r["mitigation_status"] == "None"]
if unmitigated:
print(f"\n ⚠️ UNMITIGATED RISKS ({len(unmitigated)}):")
for r in sorted(unmitigated, key=lambda x: -x["ale"]):
print(f" • {r['name']}: {fmt_dollars(r['ale'])}/yr — Action required")
def export_csv(risks: list[dict], filepath: str):
fields = [
"name", "category", "asset_value", "exposure_factor", "annual_rate",
"sle", "ale", "mitigation_cost", "mitigation_effectiveness",
"mitigated_ale", "mitigation_roi_pct", "mitigation_status", "notes"
]
with open(filepath, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
for risk in risks:
row = {k: risk.get(k, "") for k in fields}
writer.writerow(row)
print(f"✅ Exported {len(risks)} risks to {filepath}")
def export_json(risks: list[dict]) -> str:
return json.dumps(risks, indent=2, default=str)
# ─── Interactive Entry ───────────────────────────────────────────────────────
def interactive_add_risk() -> dict:
"""Interactive CLI for adding a new risk."""
print("\n── ADD NEW RISK ──────────────────────────────────────")
name = input("Risk name: ").strip()
print(f"Category options: {', '.join(RISK_CATEGORIES)}")
category = input("Category: ").strip()
description = input("Description (brief): ").strip()
print("\nAsset valuation:")
asset_value = float(input(" Asset value ($): ").replace(",", "").replace("$", ""))
exposure_factor = float(input(" Exposure factor (0.0–1.0, fraction of value lost): "))
annual_rate = float(input(" Annual rate of occurrence (e.g., 0.10 = once per 10 years): "))
print("\nMitigation:")
mitigation_cost = float(input(" Mitigation cost ($/yr): ").replace(",", "").replace("$", ""))
mitigation_effectiveness = float(input(" Mitigation effectiveness (0.0–1.0): "))
print(f"Status options: {', '.join(MITIGATION_STATUSES)}")
mitigation_status = input(" Status: ").strip()
print("\nBusiness impacts (enter 0 to skip):")
business_impacts = {}
for impact_type in BUSINESS_IMPACT_TYPES:
val = input(f" {impact_type} ($): ").replace(",", "").replace("$", "")
amount = float(val) if val else 0
if amount > 0:
business_impacts[impact_type] = amount
notes = input("\nNotes: ").strip()
return build_risk(
name=name,
category=category,
description=description,
asset_value=asset_value,
exposure_factor=exposure_factor,
annual_rate=annual_rate,
mitigation_cost=mitigation_cost,
mitigation_effectiveness=mitigation_effectiveness,
mitigation_status=mitigation_status,
business_impacts=business_impacts,
notes=notes,
)
# ─── Main ────────────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser(
description="CISO Risk Quantifier — Quantify security risks in business terms"
)
parser.add_argument("--json", action="store_true", help="Output full JSON")
parser.add_argument("--csv", metavar="FILE", help="Export CSV to file")
parser.add_argument("--budget", type=float, metavar="DOLLARS",
help="Show recommended mitigations within budget")
parser.add_argument("--board", action="store_true", help="Show board-ready summary only")
parser.add_argument("--detail", action="store_true", help="Show detailed risk breakdowns")
parser.add_argument("--add", action="store_true", help="Interactively add a risk")
args = parser.parse_args()
risks = load_sample_risks()
if args.add:
new_risk = interactive_add_risk()
risks.append(new_risk)
print(f"\n✅ Added risk: {new_risk['name']} | ALE: {fmt_dollars(new_risk['ale'])}/yr")
# Sort by ALE descending
risks_sorted = sorted(risks, key=lambda r: -r["ale"])
summary = calculate_portfolio_summary(risks_sorted)
if args.json:
output = {
"generated": datetime.now().isoformat(),
"summary": summary,
"risks": risks_sorted,
}
print(json.dumps(output, indent=2, default=str))
return
if args.csv:
export_csv(risks_sorted, args.csv)
return
print_header()
if args.board:
print_board_summary(risks_sorted, summary)
return
print_portfolio_summary(summary)
print_risk_table(risks_sorted)
if args.detail:
for i, risk in enumerate(risks_sorted, 1):
print_risk_detail(risk, i)
if args.budget:
recommended = prioritize_risks(risks_sorted, args.budget)
print(f"\n💰 BUDGET ALLOCATION — ,.0f")
print(f" Recommended mitigations (sorted by ROI):")
if recommended:
for r in recommended:
print(f" • {r['name']}: {fmt_dollars(r['mitigation_cost'])}/yr "
f"| ALE reduction: {fmt_dollars(r['ale'] - r['mitigated_ale'])}/yr "
f"| ROI: {fmt_pct(r['mitigation_roi_pct'])}")
else:
print(" No actionable mitigations fit within budget.")
print_board_summary(risks_sorted, summary)
print("\n💡 NEXT STEPS")
print(" 1. Run `--detail` to see full breakdown of each risk")
print(" 2. Run `--budget 200000` to see what you can mitigate with a given budget")
print(" 3. Run `--board` for a board-ready one-page summary")
print(" 4. Run `--csv risks.csv` to export for stakeholder review")
print(" 5. Run `--add` to interactively add risks to the register")
print()
if __name__ == "__main__":
main()
Chất vấn thận trọng về rủi ro với mọi kế hoạch liên quan dữ liệu, tuân thủ hoặc truy cập hệ thống production.
--- name: "ciso-review" description: "/cs:ciso-review <plan> — Risk-paranoid interrogation of any plan that touches data, compliance, or production access." --- # /cs:ciso-review — CISO Forcing Questions **Command:** `/cs:ciso-review <plan>` The risk-paranoid threat-modeler. Six questions before any production change that touches customer data or compliance scope. ## When to Run - Before deploying any system that touches PII / PHI / cardholder data - Before signing a new vendor with data access - Before a compliance audit (SOC 2, ISO 27001, HIPAA, GDPR) - Before any architecture decision crossing trust boundaries - After any near-miss incident ## The Six CISO Questions ### 1. Threat Model **What's the STRIDE threat model for this system, and which threat is most likely?** - Spoofing, Tampering, Repudiation, Info Disclosure, DoS, Elevation of Privilege. - Pick the top 3 by likelihood × impact. ### 2. Blast Radius **If this is fully compromised, what data is exposed and how many users are affected?** - Worst case in plain English. - Quantify in dollars via FAIR-based ALE. ### 3. Detection **What signals indicate compromise, and how long until they're triggered (MTTD)?** - Logs alone are not detection. - Define the detection rule, the alert, and the on-call. ### 4. Response **Is there an IR runbook for this scenario, and has it been tabletop-tested?** - If no runbook: build one before ship. - If untested: tabletop before ship. ### 5. Regulatory Window **What's the regulator notification window if this scenario occurs?** - GDPR: 72h. HIPAA: 60d. State breach laws vary. - Pre-write the customer comms template. ### 6. Vendor & Supply Chain **Which third-party vendors are in scope, and what's their security posture?** - Subprocessor list current? - DPAs in place? - Last security review per vendor? ## Workflow ```bash python ../../../skills/ciso-advisor/scripts/risk_quantifier.py python ../../../skills/ciso-advisor/scripts/compliance_tracker.py ``` ## Output Format ```markdown # CISO Review: <plan> **Date:** YYYY-MM-DD ## Threat Model - Top threat: <STRIDE category> — <description> - Likelihood: H/M/L | Impact: H/M/L - ALE: $X / year ## Blast Radius - Data exposed (worst case): <description> - Users affected: N - Estimated cost: $X ## Detection - MTTD target: X hours - Current MTTD: X hours - Detection rule: <name> ## Response - IR runbook: ✅ / ❌ - Last tabletop: <date> ## Regulatory - Frameworks in scope: SOC 2 / ISO 27001 / HIPAA / GDPR - Notification window: X hours/days ## Vendors - New vendors added: N - DPAs signed: N / N - Security reviews complete: N / N ## Verdict 🟢 SHIP | 🟡 MITIGATE THEN SHIP | 🔴 BLOCK ``` ## Routing - `/cs:cto-review` — architecture alignment - `/cs:gc-review` — DPA, regulatory implications - `/cs:decide` — log risk acceptance - `/cs:boardroom` — for CRITICAL risks ## Related - Agent: [`cs-ciso-advisor`](../../agents/cs-ciso-advisor.md) - Skill: [`ciso-advisor`](../../../skills/ciso-advisor/SKILL.md) - Compliance: `../../../../ra-qm-team/` --- **Version:** 1.0.0
Lãnh đạo marketing: định vị thương hiệu, mô hình tăng trưởng, phân bổ ngân sách marketing và thiết kế tổ chức.
---
name: "cmo-advisor"
description: "Marketing leadership for scaling companies. Brand positioning, growth model design, marketing budget allocation, and marketing org design. Use when designing brand strategy, selecting growth models (PLG vs sales-led vs community-led), allocating marketing budgets, building marketing teams, or when user mentions CMO, brand strategy, growth model, CAC, LTV, channel mix, or marketing ROI."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: cmo-leadership
updated: 2026-03-05
python-tools: marketing_budget_modeler.py, growth_model_simulator.py
frameworks: brand-positioning, growth-frameworks, marketing-org
---
# CMO Advisor
Strategic marketing leadership — brand positioning, growth model design, budget allocation, and org design. Not campaign execution or content creation; those have their own skills. This is the engine.
## Keywords
CMO, chief marketing officer, brand strategy, brand positioning, growth model, product-led growth, PLG, sales-led growth, community-led growth, marketing budget, CAC, customer acquisition cost, LTV, lifetime value, channel mix, marketing ROI, pipeline contribution, marketing org, category design, competitive positioning, growth loops, payback period, MQL, pipeline coverage
## Quick Start
```bash
# Model budget allocation across channels, project MQL output by scenario
python scripts/marketing_budget_modeler.py
# Project MRR growth by model, show impact of channel mix shifts
python scripts/growth_model_simulator.py
```
**Reference docs (load when needed):**
- `references/brand_positioning.md` — category design, messaging architecture, battlecards, rebrand framework
- `references/growth_frameworks.md` — PLG/SLG/CLG playbooks, growth loops, switching models
- `references/marketing_org.md` — team structure by stage, hiring sequence, agency vs. in-house
---
## The Four CMO Questions
Every CMO must own answers to these — no one else in the C-suite can:
1. **Who are we for?** — ICP, positioning, category
2. **Why do they choose us?** — Differentiation, messaging, brand
3. **How do they find us?** — Growth model, channel mix, demand gen
4. **Is it working?** — CAC, LTV:CAC, pipeline contribution, payback period
---
## Core Responsibilities (Brief)
**Brand & Positioning** — Define category, build messaging architecture, maintain competitive differentiation. Details → `references/brand_positioning.md`
**Growth Model** — Choose and operate the right acquisition engine: PLG, sales-led, community-led, or hybrid. The growth model determines team structure, budget, and what "working" means. Details → `references/growth_frameworks.md`
**Marketing Budget** — Allocate from revenue target backward: new customers needed → conversion rates by stage → MQLs needed → spend by channel based on CAC. Run `marketing_budget_modeler.py` for scenarios.
**Marketing Org** — Structure follows growth model. Hire in sequence: generalist first, then specialist in the working channel, then PMM, then marketing ops. Details → `references/marketing_org.md`
**Channel Mix** — Audit quarterly: MQLs, cost, CAC, payback, trend. Scale what's improving. Cut what's worsening. Don't optimize a channel that isn't in the strategy.
**Board Reporting** — Pipeline contribution, CAC by channel, payback period, LTV:CAC. Not impressions. Not MQLs in isolation.
---
## Key Diagnostic Questions
Ask these before making any strategic recommendation:
- What's your CAC **by channel** (not blended)?
- What's the payback period on your largest channel?
- What's your LTV:CAC ratio?
- What % of pipeline is marketing-sourced vs. sales-sourced?
- Where do your **best customers** (highest LTV, lowest churn) come from?
- What's your MQL → Opportunity conversion rate? (proxy for lead quality)
- Is this brand work or performance marketing? (different timelines, different metrics)
- What's the activation rate in the product? (PLG signal)
- If a prospect doesn't buy, why not? (win/loss data)
---
## CMO Metrics Dashboard
| Category | Metric | Healthy Target |
|----------|--------|---------------|
| **Pipeline** | Marketing-sourced pipeline % | 50–70% of total |
| **Pipeline** | Pipeline coverage ratio | 3–4x quarterly quota |
| **Pipeline** | MQL → Opportunity rate | > 15% |
| **Efficiency** | Blended CAC payback | < 18 months |
| **Efficiency** | LTV:CAC ratio | > 3:1 |
| **Efficiency** | Marketing % of total S&M spend | 30–50% |
| **Growth** | Brand search volume trend | ↑ QoQ |
| **Growth** | Win rate vs. primary competitor | > 50% |
| **Retention** | NPS (marketing-sourced cohort) | > 40 |
---
## Red Flags
- No defined ICP — "companies with 50-1000 employees" is not an ICP
- Marketing and sales disagree on what an MQL is (this is always a system problem, not a people problem)
- CAC tracked only as a blended number — channel-level CAC is non-negotiable
- Pipeline attribution is self-reported by sales reps, not CRM-timestamped
- CMO can't answer "what's our payback period?" without a 48-hour research project
- Brand work and performance marketing have no shared narrative — they're contradicting each other
- Marketing team is producing content with no documented positioning to anchor it
- Growth model was chosen because a competitor uses it, not because the product/ACV/ICP fits
---
## Integration with Other C-Suite Roles
| When... | CMO works with... | To... |
|---------|-------------------|-------|
| Pricing changes | CFO + CEO | Understand margin impact on positioning and messaging |
| Product launch | CPO + CTO | Define launch tier, GTM motion, messaging |
| Pipeline miss | CFO + CRO | Diagnose: volume problem, quality problem, or velocity problem |
| Category design | CEO | Secure multi-year organizational commitment to the narrative |
| New market entry | CEO + CFO | Validate ICP, budget, localization requirements |
| Sales misalignment | CRO | Align on MQL definition, SLA, and pipeline ownership |
| Hiring plan | CHRO | Define marketing headcount and skill profile by stage |
| Retention insights | CCO | Use expansion and churn data to sharpen ICP and messaging |
| Competitive threat | CEO + CRO | Coordinate battlecards, win/loss, repositioning response |
---
## Resources
- **References:** `references/brand_positioning.md`, `references/growth_frameworks.md`, `references/marketing_org.md`
- **Scripts:** `scripts/marketing_budget_modeler.py`, `scripts/growth_model_simulator.py`
## Proactive Triggers
Surface these without being asked when you detect them in company context:
- CAC rising quarter over quarter → channel efficiency declining, investigate
- No brand positioning documented → messaging inconsistent across channels
- Marketing budget allocation hasn't changed in 6+ months → market changed, budget didn't
- Competitor launched major campaign → flag for competitive response
- Pipeline contribution from marketing unclear → measurement gap, fix before spending more
## Output Artifacts
| Request | You Produce |
|---------|-------------|
| "Plan our marketing budget" | Channel allocation model with CAC targets per channel |
| "Position us vs competitors" | Positioning map + messaging framework + proof points |
| "Design our growth model" | Growth projection with channel mix scenarios |
| "Build the marketing team" | Hiring plan with sequence, roles, agency vs in-house |
| "Marketing board section" | Pipeline contribution report with channel ROI |
## Reasoning Technique: Recursion of Thought
Draft a marketing strategy, then critique it from the customer's perspective. Refine based on the critique. Repeat until the strategy survives scrutiny.
## Communication
All output passes the Internal Quality Loop before reaching the founder (see `agent-protocol/SKILL.md`).
- Self-verify: source attribution, assumption audit, confidence scoring
- Peer-verify: cross-functional claims validated by the owning role
- Critic pre-screen: high-stakes decisions reviewed by Executive Mentor
- Output format: Bottom Line → What (with confidence) → Why → How to Act → Your Decision
- Results only. Every finding tagged: 🟢 verified, 🟡 medium, 🔴 assumed.
## Context Integration
- **Always** read `company-context.md` before responding (if it exists)
- **During board meetings:** Use only your own analysis in Phase 2 (no cross-pollination)
- **Invocation:** You can request input from other roles: `[INVOKE:role|question]`
FILE:references/brand_positioning.md
# Brand Positioning Reference
Practical frameworks for defining, communicating, and defending your market position. Not theory — applied tools for CMOs who need to get this right.
---
## 1. Category Design Frameworks
### The Category Design Principle
Every product exists in a category — either one you define or one someone else defined. If you're not designing your category, your competitors are designing it for you, and they'll design it to exclude you.
**Category design is not renaming an existing category.** It's declaring that the existing category no longer solves the problem adequately, and that a new category — which you happen to lead — is required.
### The Three-Act Category Design Narrative
**Act 1: Name the problem**
Identify a problem that's real, growing, and underserved. Not a problem you invented — a problem your best customers articulate before they've heard your pitch.
> "Enterprise software teams are deploying faster than ever, but their security reviews still take 3 weeks — because security was built for a world where deployments happen monthly, not hourly."
**Act 2: Define the new category**
Name the category in terms of the outcome, not the feature. The category name should describe what customers achieve, not what the product does.
> "Continuous security" — not "automated security scanning" or "DevSecOps platform."
**Act 3: Position yourself as the category leader**
You can't just claim leadership — you need proof: customers, analysts, community, content, events. Leadership is built, not declared.
> "Snyk is building the continuous security category. 1.2M developers have adopted Snyk. Gartner lists us as a Cool Vendor in AppSec."
### When Category Design Works
| Condition | Explanation |
|-----------|-------------|
| Market timing | The problem is growing but the existing category is inadequate |
| CEO commitment | Category design is a 3-5 year initiative, not a marketing campaign |
| Analyst alignment | Gartner, Forrester, or G2 need to recognize your category |
| Community | Practitioners adopt the vocabulary before buyers do |
| Content moat | You publish the defining content for the category before competitors |
### Category Design Pitfalls
- **Naming the category after yourself:** "The [Your Company] Category" is not a category. It's a vanity.
- **Categories that don't solve analyst definitions:** If Gartner doesn't have a Magic Quadrant for your category, you're fighting uphill.
- **Jargon without adoption:** If your category name requires a two-paragraph explanation, it won't stick.
- **Starting a category war you can't win:** If an incumbent can copy your category name and launch in 90 days, you don't have a defensible category.
### The Lightning Strike Strategy
Category design requires concentrated, coordinated effort — not slow drip. Execute these simultaneously:
1. **Major piece of research or data** (the "State of X" report)
2. **Category-defining event** (host it, don't just attend)
3. **Analyst briefing** (educate Gartner/Forrester on the category before they define it themselves)
4. **Book or manifesto** (long-form content that becomes the category Bible)
5. **Community formation** (a Slack group, a conference, a certification that practitioners want)
Do all five within a 3-month window. This creates gravity around your category claim.
---
## 2. Messaging Architecture
### The Messaging Hierarchy
Every piece of content — from a tweet to a 60-page whitepaper — should trace back to this hierarchy. When it doesn't, you have messaging drift.
```
Level 1: Brand Promise
"[Company] [verb] [outcome] for [audience]"
→ Doesn't change. This is the north star.
Level 2: Positioning Statement (internal)
For [target customer] who [has this problem],
[Company] is the [market category] that [differentiated capability]
unlike [alternatives], [Company] [proof of differentiation].
Level 3: Value Propositions (3-4 max, one per key outcome)
Each VP: headline (5-8 words) + 2-3 sentence explanation + proof point
Level 4: Proof Points
Data, case studies, certifications, analyst recognition — evidence for each VP
Level 5: Channel Adaptations
Website copy, sales deck, ad copy, email — same hierarchy, different format
```
### Writing a Positioning Statement
The Geoffrey Moore / April Dunford format is still the best framework:
**Template:**
```
For [specific target customer]
who [has this specific, painful problem],
[Company name] is the [market category]
that [key differentiated capability].
Unlike [primary alternatives],
[Company] [proof of differentiation — something measurable or unique].
```
**Bad example (too generic):**
> For B2B companies who want to grow faster, Acme is the marketing platform that helps you get more leads. Unlike other platforms, Acme is easy to use and powerful.
**Good example (specific and falsifiable):**
> For DevOps teams in regulated industries who spend 20% of their sprint cycles on compliance reviews, Acme is the compliance automation platform that embeds regulatory checks directly into the CI/CD pipeline. Unlike manual compliance tools that create a separate review queue, Acme's policy-as-code approach reduces compliance-related cycle time by 60% without slowing deployments.
**Test your positioning statement:**
1. Can a competitor say the exact same thing? (If yes, it's not differentiated)
2. Does it describe what you do or what the customer gets? (Should be the latter)
3. Would your best customer say "yes, that's exactly my problem"? (If not, wrong ICP)
4. Is it falsifiable? (Claims you can't prove are liabilities)
### Value Proposition Development
**Structure for each VP:**
| Element | Description | Example |
|---------|-------------|---------|
| Outcome headline | What changes for the customer (5-8 words) | "Ship features 3x faster" |
| The problem | Why this matters now (1 sentence) | "Compliance reviews block 40% of releases in regulated industries" |
| Our approach | How we solve it differently (1-2 sentences) | "Policy-as-code embeds checks in the pipeline instead of adding a gate at the end" |
| Proof | Evidence this is real (1 sentence + data point) | "Customers reduce compliance cycle time by 60% in the first 90 days" |
**3-VP Architecture is the standard:**
- VP1: Core outcome (what most customers primarily buy for)
- VP2: Secondary benefit (makes the decision easier or stickier)
- VP3: Differentiator (what tips competitive decisions in your favor)
### Proof Point Hierarchy
Not all proof is equal. When you make a claim, match the strength of your proof to the importance of the claim.
| Proof Type | Strength | Best Used For |
|------------|---------|--------------|
| Third-party data (analyst report, research) | Highest | Category claims, market size |
| Customer ROI data with name | High | Value propositions |
| Customer quote with name and company | Medium-high | Specific pain points and outcomes |
| Aggregated customer data ("customers report…") | Medium | Directional claims |
| Internal testing or benchmark | Medium-low | Product capability claims |
| "Designed to…" or "built for…" | Low | Product direction only |
| "We believe…" or "we think…" | Lowest | Vision statements only |
**Proof point development process:**
1. Write the claim you want to make
2. Identify the strongest available proof
3. If proof is weak, either soften the claim or invest in getting better proof
4. Never publish a claim without knowing what happens when a skeptic asks "prove it"
---
## 3. Competitive Positioning Maps
### The Two-Axis Map
Choose two dimensions that:
1. Both matter to your target buyer
2. Create clear differentiation between you and competitors
3. You can credibly defend
**Choosing the axes:**
- Axis 1 should show a dimension where you win and most competitors cluster on the wrong side
- Axis 2 should show a dimension buyers care about deeply (ease, speed, breadth, price, compliance, etc.)
**What to avoid:**
- "Quality" vs. "Price" — too generic, every company claims the top-left
- Dimensions your competitors can match in one release cycle
- Dimensions that only your product team understands, not buyers
### Competitive Analysis Template
For each major competitor:
**Company:** _______________
| Dimension | What They Claim | What Customers Actually Experience | Gap |
|-----------|----------------|-----------------------------------|-----|
| Positioning | | | |
| Primary differentiator | | | |
| Pricing | | | |
| Ideal customer | | | |
| Weakness (win/loss data) | | | |
| What they say about you | | | |
**Sources for competitive intelligence:**
- Win/loss interviews (primary source — nothing beats this)
- G2/Capterra reviews (what customers say publicly)
- Glassdoor (tells you about internal culture and focus)
- LinkedIn job postings (what they're building next)
- Their pricing page changes (what they're competing on)
- Conference talks from their product and sales leaders
### Battlecard Format
One page per competitor. Used by sales, not marketing.
```
COMPETING AGAINST: [Competitor Name]
WHY CUSTOMERS CONSIDER THEM:
(2-3 bullets — be honest about their appeal)
OUR DIFFERENTIATION:
(2-3 bullets — factual, not marketing language)
THE LANDMINE QUESTION:
(One question that exposes their weakness. The answer should make the buyer uncomfortable choosing them.)
Example: "How long does your typical implementation take? And what's your SLA if it runs over?"
OUR PROOF POINTS IN THIS COMPARISON:
- [Customer name] switched from [competitor] after [specific reason], saw [specific result]
- [Data point that directly contradicts competitor's primary claim]
THEIR LIKELY COUNTER-MOVES:
(What will they say about us? How do we respond?)
WHEN TO WALK AWAY:
(If the prospect values X more than Y, we are not the right fit — say so)
```
---
## 4. Brand Voice Development
### What Brand Voice Is (and Isn't)
**Brand voice is NOT:**
- A list of adjectives ("we are professional, innovative, and customer-focused")
- The tone you use in formal communications
- The font and color palette (that's visual identity)
**Brand voice IS:**
- How the company sounds across every written touchpoint
- Consistent enough to be recognizable, flexible enough to be human
- Grounded in what your best customers actually value
### The Voice Attribute Framework
Define 3-4 voice attributes. For each:
1. **What it means** (in one sentence)
2. **What it sounds like** (one example)
3. **What it doesn't mean** (the common mistake that goes wrong)
**Example:**
| Attribute | Means | Sounds like | Doesn't mean |
|-----------|-------|------------|--------------|
| Direct | We say what we mean without hedging | "Your compliance review takes 3 weeks. It shouldn't." | Blunt, rude, or dismissive |
| Expert | We speak from depth, not from trend | "Here's why most security gates fail at scale, and what actually works." | Jargon-heavy or condescending |
| Honest | We acknowledge what we don't do | "We're not the best fit if you need a one-size-fits-all platform." | Self-deprecating or uncertain |
| Human | Real people write for real people | "Deploying on a Friday? Here's what we'd check first." | Casual, unprofessional |
### Voice Consistency Testing
Take a random sample of 10 recent pieces of content:
- Website homepage and pricing page
- 3 blog posts from different authors
- 5 outbound emails from sales
- 3 social posts
- 1 press release
Score each on: Does this sound like us? (1-5)
Average < 3: You have a brand voice problem. The cause is usually no documented guidelines, or guidelines that exist but aren't enforced.
### Voice in Different Contexts
The attribute stays the same. The tone adjusts.
| Context | Tone adjustment | Example of "Direct" |
|---------|----------------|---------------------|
| Homepage | Confident | "Compliance reviews don't have to slow you down." |
| Technical docs | Precise | "Set the policy threshold to 0.95 to enforce mandatory approval." |
| Error messages | Helpful | "That didn't work. Here's the most common reason why, and how to fix it." |
| Support | Empathetic | "That's frustrating. Here's what happened and what we're doing about it." |
| Sales outreach | Respectful | "Most teams in your space have this problem. Worth 20 minutes to explore?" |
---
## 5. Rebrand Decision Framework
### When Rebrands Succeed vs. Fail
**Successful rebrands:**
- Driven by a genuine strategic shift (new category, new ICP, new market)
- Have internal alignment before external launch
- Are accompanied by product and messaging changes — not just visual
- Have a 6-12 month transition plan for existing customers
**Failed rebrands:**
- Driven by internal boredom with the old brand
- Executed as a "refresh" without repositioning the value proposition
- Lack leadership conviction (executives still describe the company in the old terms)
- Launch with a new logo but same product, same messaging, same ICP
### The Rebrand Decision Matrix
Answer each question. More "yes" answers = more likely rebrand is warranted.
| Question | Yes | No |
|----------|-----|-----|
| Has our ICP changed significantly in the last 18 months? | Rebrand | Stay |
| Are we entering a new market where the current brand creates friction? | Rebrand | Stay |
| Does the brand name have negative associations in the market? | Rebrand | Stay |
| Has an acquisition changed our core identity? | Rebrand | Stay |
| Is the current brand actively hurting sales conversations? (evidence required) | Rebrand | Stay |
| Are we bored with the brand? | Stay | — |
| Did leadership change? | Stay | — |
| Are competitors rebranding? | Stay | — |
Score: 3+ "Rebrand" answers with evidence = worth a serious evaluation.
### Rebrand Risk Assessment
**Name change** is the highest-risk rebrand element. Before committing:
- Legal: trademark availability in all target markets
- SEO: 18-24 months to recover domain authority after a domain change
- Customer: existing customers need to update all integrations, contracts, documentation
- Analyst: re-education of Gartner, Forrester, G2 category definitions
- Employee: company identity shift is a culture event, not just an HR task
**Minimum viable rebrand (lower risk):**
1. New positioning and messaging (always worth doing if positioning is wrong)
2. Visual identity refresh (keep the name, update the look)
3. Tagline change (the cheapest, lowest-risk brand change)
**Full rebrand (high risk, sometimes necessary):**
1. New company name and domain
2. New visual identity
3. New positioning and messaging
4. New category narrative
### Rebrand Execution Checklist
**Pre-launch (90 days):**
- [ ] Finalize positioning before finalizing design (in that order)
- [ ] Legal trademark clearance in all target markets
- [ ] Domain secured (with redirects planned)
- [ ] Internal alignment: every leader can describe the new positioning in one sentence
- [ ] Customer comms plan (existing customers, especially enterprise, need advance notice)
- [ ] Analyst briefings scheduled (Gartner, Forrester — brief them before launch)
- [ ] PR plan finalized
**Launch (day 1):**
- [ ] Website flipped
- [ ] Social profiles updated
- [ ] Email signatures updated company-wide
- [ ] Sales deck updated
- [ ] Press release published
- [ ] Existing customers notified (email from CEO or CMO, not marketing automation)
**Post-launch (90 days):**
- [ ] SEO monitoring (watch for ranking drops on key terms)
- [ ] Win rate monitoring (did conversion change?)
- [ ] Employee feedback (are they using the new messaging correctly?)
- [ ] Partner/channel update (resellers, integrations, directories)
- [ ] Analyst follow-up (did they update their reports?)
---
## Quick Reference: Brand Positioning Diagnostic
Use this as an audit against your current positioning:
| Check | Pass | Fail |
|-------|------|------|
| Can every sales rep state the positioning in one sentence without looking it up? | ✓ | Positioning isn't working |
| Is the ICP specific enough to disqualify companies? | ✓ | ICP is too broad |
| Does the homepage lead with customer outcome, not product features? | ✓ | Copy needs rewrite |
| Can you name 3 companies you're NOT a good fit for? | ✓ | Positioning is unfocused |
| Do win/loss interviews confirm the stated differentiator? | ✓ | Differentiator is assumed, not proven |
| Is the category name used by analysts or industry media? | ✓ | Category design needed |
| Does every piece of content trace back to a VP from the hierarchy? | ✓ | Messaging drift — need guidelines |
FILE:references/growth_frameworks.md
# Growth Frameworks Reference
Playbooks for PLG, sales-led, community-led, and hybrid growth models. Includes growth loops, funnel design, and guidance on when and how to switch models.
---
## 1. Product-Led Growth (PLG) Playbook
### What PLG Actually Is
PLG means the product is the primary distribution mechanism. Not "we have a free trial." Not "our product is self-serve." PLG means the product creates acquisition, retention, and expansion — and does so at a scale and cost no sales team can match.
**The minimum requirements for PLG to work:**
1. **Fast time-to-value:** Users must get a meaningful outcome within one session (ideally < 30 minutes)
2. **Low friction to start:** No sales call, no implementation project, no credit card required (for top of funnel)
3. **Built-in virality or network effects:** Usage creates exposure or value that draws in other users
4. **Self-serve monetization or expansion path:** Freemium → paid, or individual → team → company
If any of these is missing, you don't have PLG — you have a website with a free trial.
### PLG Funnel: The Four Stages
**Stage 1: Acquisition**
The user discovers and signs up for the product without talking to sales.
Key channels:
- Organic search (SEO targeting jobs-to-be-done searches)
- Product hunt launches
- Referral and invite loops (users share the product with colleagues)
- Developer communities and open-source contributions
Metric: Visitor-to-signup rate
Benchmark: 2-8% for B2B SaaS (varies heavily by product complexity)
**Stage 2: Activation**
The user reaches the "aha moment" — the point where the product delivers its core value for the first time.
Finding the aha moment:
- Look at the behaviors that differentiate users who stay from users who churn in the first 30 days
- The aha moment is not creating an account. It's completing the first outcome.
- For Slack: sending a message in a real channel
- For Dropbox: adding a file from a second device
- For HubSpot: publishing a form that captures a real lead
Metric: Activation rate (% of signups who complete the aha moment action within 7 days)
Benchmark: 25-40% is strong. < 15% means the onboarding is broken.
**Stage 3: Retention**
Users return to the product and build habitual use.
Retention analysis:
- Cohort retention curves (by signup week/month)
- Day 1, Day 7, Day 30, Day 90 retention rates
- Feature adoption by retained vs. churned users (which features predict retention?)
Metric: D30 retention rate (% of users still active 30 days after signup)
Benchmark: > 40% D30 retention is strong for B2B products
**Stage 4: Revenue**
Self-serve conversion from free to paid, or expansion from individual to team.
PQL (Product-Qualified Lead) signals:
- Reached a usage limit (invites, storage, seats)
- Used a premium feature in trial mode
- Team size on the account reached a threshold
- High-frequency usage above a defined threshold
Metric: PQL conversion rate (% of PQLs who convert to paid within 30 days)
Benchmark: 15-30% for well-designed PLG products
### PLG Expansion Model
PLG growth compounds through account expansion:
```
Individual user discovers product
→ Gets value, invites teammates
→ Team adopts product
→ Becomes department-wide
→ Finance/IT gets involved
→ Enterprise contract
```
This is "bottom-up" enterprise: individual adoption precedes company-wide purchase. It's also the most defensible moat — when every engineer in the company uses your product individually, procurement cancellation is very hard.
**Expansion levers:**
- Seat-based pricing (more users = more revenue, aligned with value)
- Usage-based pricing (more usage = more value = more revenue)
- Feature gating (team/enterprise features visible but gated, creating pull to upgrade)
- Admin discovery (usage reports surface to managers who didn't know they had a product champion)
### PLG Diagnostic
| Question | Healthy | Unhealthy |
|----------|---------|-----------|
| Time-to-value | < 30 minutes | > 2 hours |
| Activation rate | > 30% | < 15% |
| D30 retention | > 40% | < 20% |
| PQL conversion | > 15% | < 5% |
| NPS from self-serve users | > 40 | < 20 |
| Viral coefficient | > 0.3 | < 0.1 |
### PLG Team Structure
```
Head of Growth (often VP Product or VP Marketing)
├── Growth PM (owns activation and retention loops in product)
├── Growth Engineer (2-3 engineers dedicated to growth experiments)
├── Data Analyst (experimentation, funnel analysis, cohort reports)
└── Growth Marketer (acquisition, SEO, referral programs)
```
The growth team sits between product and marketing. This is intentional — they own the product loops that drive acquisition and retention.
---
## 2. Sales-Led Growth (SLG) Model
### The SLG System
In SLG, marketing's job is to fill the sales pipeline. Sales converts it. The system only works if marketing and sales agree on definitions, SLAs, and shared metrics.
**The SLG funnel:**
```
Awareness (Impressions, reach, brand search)
↓
Lead (Name + contact info captured)
↓
MQL — Marketing Qualified Lead (meets ICP criteria, intent signal detected)
↓ [Marketing → Sales handoff]
SAL — Sales Accepted Lead (sales reviews and accepts the lead)
↓
SQL — Sales Qualified Lead (sales confirms budget, authority, need, timeline)
↓
Opportunity (Formal deal in pipeline, has a close date)
↓
Closed-Won
```
**The MQL definition problem:**
Most marketing-sales friction traces to an unclear MQL definition. The MQL should be:
- ICP-matched (company size, industry, role)
- Intent-signaled (visited pricing page, attended webinar, downloaded high-intent content)
- Not just email address + "subscribed to newsletter"
**A concrete MQL definition:**
> Company 50-500 employees, B2B SaaS, role is VP Engineering or CTO or CISO, AND has performed 2+ of: attended webinar, visited pricing page, requested demo, downloaded security report, attended event.
This definition makes the MQL useful. If you can't score it in your CRM without human judgment, it's not a definition — it's a guideline.
### SLG Conversion Rate Benchmarks
| Stage | Average B2B SaaS | Top Quartile |
|-------|-----------------|--------------|
| Lead → MQL | 5-15% | > 20% |
| MQL → SAL | 50-70% | > 75% |
| SAL → SQL | 30-50% | > 60% |
| SQL → Opportunity | 60-80% | > 85% |
| Opportunity → Closed-Won | 20-30% | > 40% |
**End-to-end:** Lead → Closed-Won: 1-5% (wide range by ACV and ICP quality)
### Pipeline Coverage Mechanics
A healthy SLG pipeline has 3-4x coverage against quota.
If a sales rep has a $500K quarterly quota:
- They need $1.5M-$2M in active pipeline
- Pipeline must be distributed across stages (not all "prospecting")
- Stage distribution benchmark: 30% early, 40% mid, 30% late
Insufficient coverage (< 3x) is a lagging indicator of a miss — by the time coverage is low, it's too late to recover in the same quarter. Coverage should be tracked weekly.
### SLG Demand Generation Channels
**High-intent channels (bottom of funnel):**
- Paid search on buying-intent keywords (e.g., "[competitor] alternative", "best [category] software")
- Review site presence (G2, Capterra) — buyers use these before vendor websites
- Outbound SDR targeting specific accounts (ABM)
**Medium-intent channels (middle of funnel):**
- Webinars and virtual events (capture active learners)
- Gated content (guides, benchmarks, templates — ICP-specific)
- Retargeting to website visitors
**Awareness channels (top of funnel):**
- Content and SEO (captures people learning about the problem)
- Podcast sponsorships, industry media
- Conference sponsorship and speaking
- Paid social (LinkedIn for B2B)
### ABM (Account-Based Marketing) in SLG
ABM flips the funnel: instead of generating leads and filtering for good ones, you start with target accounts and run coordinated campaigns against them.
**Tiers:**
- **Tier 1 (1:1):** 5-20 strategic accounts, fully customized campaigns, dedicated SDR+AE pairs, executive outreach
- **Tier 2 (1:few):** 50-200 accounts, programmatic personalization, SDR sequences, targeted events
- **Tier 3 (1:many):** 500+ accounts, standard campaigns with light personalization
ABM requires tight sales/marketing alignment. If sales doesn't work the accounts marketing targets, ABM produces zero results.
---
## 3. Community-Led Growth (CLG)
### The CLG Thesis
Community-led growth works when:
1. Your buyers want to learn from peers, not vendors
2. There's a strong practitioner identity (developers, data teams, security, FinOps)
3. Your category is complex enough that buyers need education before purchasing
4. You can commit to building genuine community, not a marketing channel in disguise
**The fundamental rule of CLG:** The community must deliver value to members whether or not they ever buy your product. If the only purpose of the community is to sell to members, the community will die.
### CLG Stages
**Stage 1: Find the community**
The community often exists before you build it. Find where your practitioners already gather:
- Slack groups, Discord servers
- Subreddits and LinkedIn groups
- Conference hallways
- Open-source repositories
Before building, participate. Earn trust. Understand the conversations.
**Stage 2: Become the knowledge hub**
Establish your company as the best source of information on the category problem:
- Publish the benchmark study everyone references
- Host the conference that defines the industry
- Create the certification practitioners want on their resume
- Open-source the tools the community needs
**Stage 3: Build the platform**
Create a dedicated community space (Slack, Discord, forum):
- Community must be practitioner-first, not vendor-first
- Community managers who genuinely care about member value
- Content from members, not just from your company
- Events that build member relationships, not just product demos
**Stage 4: Convert community to customers**
Community members who become customers do so because they trust you, not because you sold them. Conversion paths:
- Community members see peer success with your product
- Product-qualified signals from community members who trial the product
- Direct outreach from sales to active community members (with permission and context)
- Enterprise deals from companies whose employees are active in the community
### CLG Metrics
| Metric | Definition | Health Signal |
|--------|-----------|--------------|
| Monthly active members | Members who post, comment, or engage | > 15% of total members |
| Community-sourced pipeline | $ pipeline where community was first touch | Track and trend |
| Community-influenced pipeline | $ pipeline with any community touchpoint | > 30% of total pipeline |
| NPS of community members vs. non-members | Loyalty difference | Community members should score 20+ pts higher |
| Member-generated content % | % of content posted by non-employees | > 60% is healthy community |
| Time from community join to product trial | | Shortens as community matures |
### CLG Anti-Patterns
- **Community as a newsletter:** If members can't interact with each other, it's not a community — it's a list.
- **Product launches in the community:** Nothing kills community trust faster than using it for sales announcements.
- **Community without a community manager:** Communities left to run themselves become ghost towns or become toxic.
- **Measuring community by member count:** Ghost members are noise. Active engagement is signal.
---
## 4. Hybrid Growth Models
### PLG + SLG ("Product-Led Sales" or PLS)
The most common hybrid at growth stage. PLG handles SMB self-serve; sales closes enterprise.
**The PQL-to-sales handoff:**
Define the triggers that move a product-qualified lead to a sales-assisted motion:
- Company has > X users (e.g., 10+ users on a team account)
- Usage exceeds Y threshold in 30 days
- Account is a named target in the ABM list
- User explicitly requested a demo or upgrade assistance
**The risk:** Sales team ignores PLG pipeline because deal size is smaller. Fix: separate quotas and commission structures for self-serve expansion vs. new enterprise logos.
**The opportunity:** PLG creates pre-qualified champions inside accounts. Sales doesn't have to create interest — they convert it. Win rates in PLS motions are typically 30-50% higher than cold outbound.
### SLG + CLG
Community builds brand and generates inbound pipeline for sales.
This hybrid works when:
- Sales cycles are long (6-18 months)
- Buyers do extensive research before engaging with vendors
- The community validates your credibility before sales conversations begin
**The integration:**
- Community team feeds content insights to demand gen
- Event attendees become high-priority SDR sequences
- Active community members get dedicated AE outreach with community context
- Win/loss analysis includes community touchpoints
### PLG + CLG
The developer/open-source hybrid. PLG handles product adoption; community handles advocacy and content.
**Examples:** HashiCorp (Terraform community + enterprise sales), Elastic (open-source + community + commercial), Tailscale (developer community + self-serve + enterprise).
**How it compounds:**
```
Community member learns from community content
→ Discovers open-source or free tier
→ Gets value in first session
→ Shares experience in community
→ New members discover product through community content
```
---
## 5. Growth Loops vs. Funnels
### The Difference
**A funnel** is linear. It requires constant input at the top to produce output at the bottom. If you stop feeding it, it stops producing.
**A growth loop** is cyclical. Output from one stage becomes input to the next. The system compounds.
### Common Growth Loops
**Viral loop:**
```
User gets value → Invites colleague → Colleague signs up →
Colleague invites another colleague → ...
```
Viral coefficient (K) = (Average invites per user) × (Conversion rate of invites)
- K > 1: Exponential growth (rare)
- K 0.5-1: Strong viral assist
- K < 0.3: Viral is not a meaningful growth driver
**Content SEO loop:**
```
Publish content on [topic] → Ranks in search →
Drives signups → Users share content → Builds backlinks →
Better rankings → More content is possible
```
This loop takes 12-24 months to activate but is extraordinarily defensible once running.
**UGC (User-Generated Content) loop:**
```
Users share their work publicly (templates, analyses, portfolios) →
Others discover the work → They find the product →
They create and share their own work → ...
```
Figma, Notion, Airtable, Canva — all run this loop.
**Data network effect loop:**
```
More users → More data → Better product →
More users attracted → ...
```
LinkedIn, Waze, Duolingo — accuracy or relevance improves as the user base grows.
**Integration loop:**
```
Product integrates with X → X's users discover your product →
More integrations possible → More discovery surfaces → ...
```
Zapier, Slack apps, Salesforce AppExchange — being in the ecosystem creates distribution.
### Building a Growth Loop
**Step 1: Map the current funnel**
Where do customers come from? What are the conversion steps?
**Step 2: Find the output**
What does a successful customer produce?
- Invite emails
- Shared content
- Public work visible to others
- Reviews or testimonials
**Step 3: Design the loop**
How does that output become tomorrow's input to acquisition?
- If they share → is there a landing page that captures the new visitor?
- If they invite → is the invite experience friction-free?
- If they create content → does it rank in search or appear in relevant communities?
**Step 4: Measure loop velocity**
For each loop, measure:
- Cycle time: How long does one full cycle take?
- Conversion at each step: Where does the loop break down?
- Loop coefficient: How many new users does one existing user generate?
---
## 6. When to Switch Growth Models
### The Warning Signs
**PLG-to-SLG triggers:**
- Enterprise accounts are signing up via PLG but aren't expanding without human intervention
- Average deal sizes in enterprise are 10-20x SMB, and you're leaving revenue on the table
- Product adoption in enterprise requires configuration or integration that needs support
- PLG accounts churn at higher rates than sales-assisted accounts
**SLG-to-PLG/PLS triggers:**
- CAC is increasing year-over-year as competition for sales talent intensifies
- Smaller competitors are winning deals with self-serve
- Customers are asking "can I just try this myself?"
- ACV is declining as the market matures and products commoditize
- Sales team efficiency (revenue per sales rep) is declining
**Adding CLG to existing motion:**
- Sales cycles are long and trust is the primary barrier
- SEO and content are generating traffic but low conversion (awareness without trust)
- Competitors are building community and you're not present
- Customer success teams report that customers who participate in user groups retain better
### The Transition Playbook
**Phase 1: Prove it before scaling (months 1-6)**
Don't restructure the team to support the new model before proving it works.
- Run a pilot: 3-5 SDRs testing PLG signals as outreach triggers (for PLG → PLS)
- Or: Launch a beta community with 100 core customers (for adding CLG)
- Measure the metrics of the new model, compare to current model
**Phase 2: Parallel running (months 6-12)**
Run both models simultaneously. Don't kill the current model while building the new one.
- Set clear boundaries on which accounts go to which motion
- Build dedicated teams for each model (don't ask the same people to do both)
- Define success metrics for the new model independently
**Phase 3: Rebalance (months 12-18)**
Once the new model proves its unit economics:
- Shift headcount and budget to the more efficient model
- Keep the old model for the segments where it still works
- Document what the new model requires to sustain itself
**The anti-pattern:** Announcing a model shift without proof, restructuring the team, and discovering after 12 months that the new model doesn't work. By then, the old model's momentum is gone and you've burned a year.
### Growth Model Maturity Matrix
| Dimension | PLG | SLG | CLG |
|-----------|-----|-----|-----|
| Time to first results | 3-6 months | 1-3 months | 12-18 months |
| Requires up-front product investment | High | Low | Medium |
| Scales without linear headcount | Yes | No | Yes |
| Predictable pipeline | Low (early) | High | Low (early) |
| CAC trend over time | Decreases | Flat/increases | Decreases |
| Works for ACV > $50K | Only with SLG assist | Yes | Yes |
| Works for ACV < $5K | Yes | No | Only with PLG |
| Defensibility once established | High | Low | Very high |
FILE:references/marketing_org.md
# Marketing Org Reference
Team structure, hiring sequence, agency decisions, marketing ops, and cross-functional alignment — by company stage.
---
## 1. Marketing Team Structure by Stage
### Pre-Seed / Seed (< $1M ARR, 1–10 people)
Don't hire a marketing team yet. The founders are the marketing team.
What to do instead:
- Founders write content, do sales calls, go to events
- The goal is learning the ICP and finding the channel that works, not scaling anything
- One contractor or agency for specific output (design, SEO audit) is fine
First marketing hire trigger: You have a repeatable sales motion and need to scale it.
---
### Series A ($1M–$5M ARR, 10–30 people)
**Org:**
```
Founding Marketer (Head of Marketing or VP Marketing)
```
One person. Generalist. Capable of writing, running ads, setting up HubSpot, producing a report. Their job is to find what works.
**What they own:**
- Content and SEO foundation
- Paid channel experiments
- Sales enablement basics (1-pager, deck, email sequences)
- Event presence (1-2 conferences)
- Marketing attribution setup (get this right early)
**What they don't own yet:**
- Brand redesign
- Analyst relations
- Partner marketing
- Field marketing team
**CMO vs. VP Marketing at this stage:** VP Marketing. An experienced operator who can build and execute. A CMO's strategic value isn't fully leveraged until there's a team to lead and a budget to allocate.
---
### Series B ($5M–$20M ARR, 30–80 people)
**PLG-first org:**
```
VP Marketing
├── Growth Marketing (acquisition loops, activation, PLG analytics)
├── Product Marketing (positioning, launch, sales enablement)
└── Content & SEO (organic engine)
```
**SLG-first org:**
```
VP Marketing
├── Demand Generation (pipeline creation, paid, digital)
├── Product Marketing (positioning, competitive intel, enablement)
├── Field Marketing (events, regional, ABM)
└── Marketing Operations (CRM, attribution, reporting)
```
**Community-led org:**
```
VP Marketing
├── Community & Developer Relations
├── Content & SEO
└── Product Marketing
```
**At this stage:** Marketing ops becomes critical. Without it, attribution is guesswork and the sales team blames marketing for bad leads.
---
### Series C ($20M–$75M ARR, 80–200 people)
```
CMO
├── Demand Generation
│ ├── Paid Media
│ ├── SEO & Content
│ └── Marketing Operations
├── Product Marketing
│ ├── Core PMMs (by product line or segment)
│ └── Competitive Intelligence
├── Field Marketing
│ ├── Events
│ └── Regional / ABM
└── Brand & Communications
├── Brand Design
└── PR / Analyst Relations
```
**At this stage:**
- The CMO is a board-level communicator, not a campaign manager
- Each function has a dedicated leader (director or VP level)
- Marketing ops owns the attribution model and reports to CMO directly
- Analyst relations becomes important (Gartner, Forrester, G2 category positioning)
---
### Growth Stage ($75M+ ARR)
Marketing becomes a portfolio of specialized functions. Each major channel has a team. Brand is a serious investment. Analyst relations is a dedicated role. International marketing teams form.
The CMO's job shifts from building the machine to:
- Setting marketing strategy across a complex portfolio
- Representing marketing at the board level
- Owning brand and category leadership
- Cross-functional leadership with CRO, CPO, CEO
---
## 2. Hiring Sequence
### Who to Hire First
**The generalist content + demand gen marketer.**
Must-haves:
- Can write (blog posts, emails, landing pages — not just briefs)
- Can run paid campaigns (Google, LinkedIn — not just "I've managed agencies")
- Can operate a marketing automation platform (HubSpot, Marketo)
- Comfortable with data (can build a funnel report without asking an analyst)
This person builds the foundation. They're not a specialist yet — they're testing channels and building the process.
Avoid: Hiring a brand designer first. Or a community manager. Or a social media manager. These are specialties that compound on a foundation that doesn't exist yet.
### Who to Hire Second
**A specialist in the channel that's working.**
If organic search is your top lead source → hire an SEO/content lead.
If events are driving pipeline → hire a field marketer.
If outbound is working → hire an SDR manager or demand gen specialist.
Don't hire a generalist #2. By now you know what's working. Depth beats breadth.
### Who to Hire Third
**Product marketing.**
Why third and not first? Because PMM output (positioning, sales enablement, launch) is most valuable when there's an audience to position to and a sales team to enable. Before that, the founding marketer does "good enough" PMM work.
PMM hire profile: Has done positioning work before, has run a product launch, has built sales decks that sales actually uses, comfortable with win/loss analysis.
PMM:PM ratio benchmark: 1 PMM per 2–3 PMs. If you have 6 PMs and 1 PMM, you have a messaging and enablement problem.
### Who to Hire Fourth
**Marketing operations.**
This is consistently hired too late. By the time most companies hire marketing ops, attribution is broken, leads are being lost in handoffs, and the CRM data is unreliable. Hire marketing ops before you think you need it.
Marketing ops profile: HubSpot/Marketo certified, SQL capable, understands multi-touch attribution, has integrated CRM + sales engagement tools before.
### Hiring Decision Triggers
| Hire | Trigger |
|------|---------|
| Generalist marketer #1 | Sales motion is repeatable, need to scale lead generation |
| Specialist #2 | One channel is clearly outperforming — double down |
| Product marketer | Sales team is losing deals to positioning confusion or competitor gaps |
| Marketing ops | Running 3+ campaigns simultaneously with manual tracking |
| Field marketer | Events are in the strategy and attendance > 2 conferences/quarter |
| Head of Marketing / VP | Team is 3+ people and needs an org owner |
| CMO | Company is Series B/C and marketing needs board-level representation |
---
## 3. Agency vs. In-House
### Framework
Keep in-house what compounds. Outsource what's episodic or specialized.
| Function | Agency | In-House | Notes |
|----------|--------|----------|-------|
| Brand design | Early stage | Series B+ | Agency fine until redesigns become frequent |
| Paid media | < $50K/month spend | > $50K/month | Agency margin eats returns at scale |
| SEO strategy | Audit only | Ongoing execution | Strategy once, execution continuously |
| Content production | Overflow only | Core writers | Your voice must be yours |
| PR / comms | Almost always | $100M+ companies | Specialists required for media relationships |
| Marketing ops / CRM | Never | Always | This is your data infrastructure |
| Analyst relations | Initial strategy | Ongoing | Relationship-based — needs dedicated owner |
| Video / creative production | Always | Rarely | Episodic, specialized equipment |
### Agency Red Flags
- They want to own your ad accounts. (Always keep ownership. No exceptions.)
- SLA is "5 business days for creative requests." For a performance channel, that's too slow.
- Reporting is impressions, CPM, and "brand lift." Where's the pipeline?
- They can't tell you your CAC from their channel.
- They won't share the actual data — only their dashboard.
- Your account manager changes every 6 months.
### Agency Evaluation Criteria
1. **Proof of work in your category** — ask for 3 case studies with actual CAC and pipeline data
2. **Who actually does the work** — senior pitch team ≠ junior execution team
3. **Account ownership** — all accounts, pixels, analytics must be in your name
4. **Reporting cadence** — weekly data, monthly strategy, quarterly business review
5. **Exit terms** — how do you offboard without losing your data, accounts, and history?
---
## 4. Marketing Ops and Tech Stack
### The Minimum Viable Stack
| Layer | Tool | Purpose |
|-------|------|---------|
| CRM | HubSpot / Salesforce | Contact database, pipeline, source of truth |
| Marketing automation | HubSpot / Marketo / ActiveCampaign | Email, nurture, lead scoring |
| Analytics | Google Analytics 4 + Segment | Traffic, behavior, event tracking |
| Attribution | HubSpot / Attributer.io / Dreamdata | Multi-touch pipeline attribution |
| Paid | Google Ads + LinkedIn Ads | Performance channels |
| SEO | Ahrefs / Semrush | Keyword research, rank tracking |
| Chat/conversion | Intercom / Drift | In-product + website conversion |
**The integration that breaks most:** CRM ↔ Marketing automation ↔ Sales engagement. When these aren't synced properly, leads are lost, attribution is wrong, and marketing and sales fight about pipeline. Fix this first.
### Marketing Ops Ownership
Marketing ops must own:
- CRM data quality (field standardization, deduplication, routing)
- Lead scoring model (and quarterly review against conversion data)
- Attribution model (with documented assumptions)
- Campaign tracking (UTM governance — no UTM = no attribution)
- Tech stack evaluation and contracts
Marketing ops must NOT own:
- Strategy (they enable it, not set it)
- Content production
- Campaign creative
---
## 5. Cross-Functional Alignment
### Marketing + Sales
The most important cross-functional relationship in a SLG company. Where it breaks:
| Problem | Root Cause | Fix |
|---------|-----------|-----|
| "Marketing sends us bad leads" | MQL definition is unclear or wrong | Define MQL jointly, score against conversion data |
| "Sales doesn't follow up on leads" | No SLA, no consequence | Define SLA (e.g., 24-hour response), track in CRM |
| "Marketing doesn't understand what customers care about" | No win/loss sharing | Weekly call: sales shares 3 deal insights, marketing shares 3 content results |
| "We don't know what's working" | Attribution is broken | Marketing ops fixes attribution before next budget cycle |
**The SLA agreement (document this):**
- Marketing commits: X MQLs/week meeting defined criteria, 48-hour SLA from form fill to SDR outreach
- Sales commits: All MQLs contacted within 24 hours, disposition logged in CRM within 5 days
### Marketing + Product
Where it breaks and how to fix it:
| Problem | Fix |
|---------|-----|
| PMM learns about launches 2 weeks before ship | PMM joins the product planning process at the roadmap stage, not the sprint stage |
| Feature launches with no messaging | Launch tiers: Tier 1 (major, full launch), Tier 2 (minor, release notes + 1 post), Tier 3 (internal only) |
| Product doesn't use customer insights from marketing | Monthly session: PMM shares win/loss themes, competitive intel, ICP data |
| No feedback loop on messaging in-product | PMM owns in-product copy review, not just external comms |
### Marketing + Customer Success
Customer success is marketing's best source of truth:
- **ICP validation:** Which customers are expanding? Which are churning? This refines who you target.
- **Proof points:** CS-sourced case studies and testimonials outperform vendor-written content 3:1 in conversion.
- **Messaging test:** If CS is answering the same question 20 times, marketing hasn't explained it clearly enough.
- **Referral programs:** CS owns the relationship; marketing owns the mechanics. Design them together.
Cadence: Monthly meeting between CMO and VP/Head of CS. Agenda: retention trends, expansion patterns, at-risk customers, NPS themes.
FILE:scripts/growth_model_simulator.py
#!/usr/bin/env python3
"""
Growth Model Simulator
----------------------
Projects MRR growth across different growth models (PLG, sales-led, community-led,
hybrid) and shows the impact of channel mix changes on growth trajectory.
Usage:
python growth_model_simulator.py
Inputs (edit INPUTS section):
- Starting MRR and churn rate
- Current channel mix (% of new MRR from each source)
- Conversion rates per model
- Growth rate assumptions per channel
Outputs:
- 12-month MRR projection by growth model
- Channel mix impact analysis (what happens if you shift mix)
- Break-even months for each model
- Side-by-side comparison table
"""
from __future__ import annotations
import math
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple
# ---------------------------------------------------------------------------
# Data models
# ---------------------------------------------------------------------------
@dataclass
class ChannelSource:
name: str
pct_of_new_mrr: float # Current share of new MRR (0.0–1.0)
monthly_growth_rate: float # How fast this channel grows month-over-month
cac: float # CAC in dollars
payback_months: float # Months to recover CAC
@dataclass
class GrowthModel:
name: str
description: str
channel_mix: Dict[str, float] # channel name → % of new MRR
new_mrr_monthly_base: float # Starting new MRR/month from this model
monthly_acceleration: float # Acceleration factor (compounding)
avg_ltv_cac: float # Expected LTV:CAC at scale
months_to_steady_state: int # Months before model hits its natural growth rate
notes: List[str] = field(default_factory=list)
@dataclass
class MonthSnapshot:
month: int
mrr: float
new_mrr: float
churned_mrr: float
expansion_mrr: float
net_new_mrr: float
cumulative_cac_spend: float
@dataclass
class ModelProjection:
model: GrowthModel
snapshots: List[MonthSnapshot]
break_even_month: Optional[int] # Month when cumulative revenue > cumulative CAC
# ---------------------------------------------------------------------------
# INPUTS — edit these
# ---------------------------------------------------------------------------
STARTING_MRR = 85_000 # Current MRR ($)
MONTHLY_CHURN_RATE = 0.012 # Monthly churn rate (1.2% = ~14% annual)
EXPANSION_RATE = 0.008 # Monthly expansion MRR as % of existing MRR
GROSS_MARGIN = 0.75
SIMULATION_MONTHS = 18
# Channel sources (used to model mix shift scenarios)
CHANNELS: List[ChannelSource] = [
ChannelSource("Organic/SEO", pct_of_new_mrr=0.28, monthly_growth_rate=0.04, cac=1_800, payback_months=9),
ChannelSource("PLG Self-Serve", pct_of_new_mrr=0.15, monthly_growth_rate=0.08, cac=900, payback_months=5),
ChannelSource("Outbound SDR", pct_of_new_mrr=0.25, monthly_growth_rate=0.02, cac=5_100, payback_months=21),
ChannelSource("Paid Search", pct_of_new_mrr=0.15, monthly_growth_rate=0.01, cac=6_200, payback_months=26),
ChannelSource("Events/Field", pct_of_new_mrr=0.08, monthly_growth_rate=0.01, cac=9_800, payback_months=41),
ChannelSource("Partner/Channel", pct_of_new_mrr=0.09, monthly_growth_rate=0.05, cac=3_400, payback_months=14),
]
# Growth models to simulate
GROWTH_MODELS: List[GrowthModel] = [
GrowthModel(
name="Current Mix",
description="Baseline — maintain current channel allocation",
channel_mix={"Organic/SEO": 0.28, "PLG Self-Serve": 0.15, "Outbound SDR": 0.25,
"Paid Search": 0.15, "Events/Field": 0.08, "Partner/Channel": 0.09},
new_mrr_monthly_base=12_000,
monthly_acceleration=0.025,
avg_ltv_cac=3.2,
months_to_steady_state=3,
notes=["Baseline. No changes to channel mix."],
),
GrowthModel(
name="PLG-First",
description="Shift budget toward PLG self-serve and organic; reduce paid and outbound",
channel_mix={"Organic/SEO": 0.35, "PLG Self-Serve": 0.35, "Outbound SDR": 0.10,
"Paid Search": 0.08, "Events/Field": 0.04, "Partner/Channel": 0.08},
new_mrr_monthly_base=9_500, # Slower start — PLG takes time to activate
monthly_acceleration=0.048, # But compounds faster
avg_ltv_cac=5.8,
months_to_steady_state=6, # PLG loops take time to build
notes=[
"Lower new MRR in months 1-6 while PLG loops activate.",
"Acceleration compounds strongly after month 6.",
"Requires product investment in activation/onboarding.",
"Best fit if time-to-value < 30 min and viral coefficient > 0.3.",
],
),
GrowthModel(
name="Sales-Led Scale",
description="Double down on outbound SDR and field; optimize for enterprise ACV",
channel_mix={"Organic/SEO": 0.20, "PLG Self-Serve": 0.05, "Outbound SDR": 0.40,
"Paid Search": 0.15, "Events/Field": 0.15, "Partner/Channel": 0.05},
new_mrr_monthly_base=15_000, # Higher new MRR from enterprise ACV
monthly_acceleration=0.018, # Linear growth — headcount-constrained
avg_ltv_cac=2.8,
months_to_steady_state=2,
notes=[
"Fastest short-term new MRR if ACV > $30K.",
"Growth is linear — adds headcount to add pipeline.",
"CAC and payback worsen as SDR market tightens.",
"Requires sales capacity increase to sustain.",
],
),
GrowthModel(
name="Community-Led",
description="Invest in community and content; reduce paid; long-term brand play",
channel_mix={"Organic/SEO": 0.45, "PLG Self-Serve": 0.15, "Outbound SDR": 0.15,
"Paid Search": 0.05, "Events/Field": 0.10, "Partner/Channel": 0.10},
new_mrr_monthly_base=7_000, # Slowest start
monthly_acceleration=0.038,
avg_ltv_cac=4.5,
months_to_steady_state=9, # Community takes longest to activate
notes=[
"Lowest new MRR in months 1-9.",
"Community trust drives lower CAC and higher retention at scale.",
"Best for categories where buyers seek peer validation.",
"Requires dedicated community manager from day one.",
],
),
GrowthModel(
name="Hybrid PLS",
description="PLG self-serve for SMB + sales-assisted for enterprise (Product-Led Sales)",
channel_mix={"Organic/SEO": 0.30, "PLG Self-Serve": 0.28, "Outbound SDR": 0.22,
"Paid Search": 0.08, "Events/Field": 0.06, "Partner/Channel": 0.06},
new_mrr_monthly_base=11_000,
monthly_acceleration=0.035,
avg_ltv_cac=4.1,
months_to_steady_state=4,
notes=[
"PLG handles SMB; sales closes enterprise with PQL signals.",
"Requires clear PQL definition and SDR/PLG handoff process.",
"Best if you have a product with both bottom-up and top-down adoption.",
],
),
]
# ---------------------------------------------------------------------------
# Simulation engine
# ---------------------------------------------------------------------------
def simulate_model(model: GrowthModel, months: int) -> ModelProjection:
snapshots: List[MonthSnapshot] = []
mrr = STARTING_MRR
cumulative_cac = 0.0
cumulative_revenue = 0.0
break_even_month = None
for m in range(1, months + 1):
# Ramp up — new_mrr accelerates each month
if m <= model.months_to_steady_state:
# Ramp phase: linear ramp from 60% to 100% of base
ramp_factor = 0.6 + 0.4 * (m / model.months_to_steady_state)
else:
# Steady state: compound acceleration
months_past_ramp = m - model.months_to_steady_state
ramp_factor = 1.0 + model.monthly_acceleration * months_past_ramp
new_mrr = model.new_mrr_monthly_base * ramp_factor
churned_mrr = mrr * MONTHLY_CHURN_RATE
expansion_mrr = mrr * EXPANSION_RATE
net_new_mrr = new_mrr - churned_mrr + expansion_mrr
mrr = mrr + net_new_mrr
# CAC spend approximation: new_mrr / (avg_deal_mrr) * blended_cac
# Use weighted CAC from channel mix
weighted_cac = _weighted_cac(model.channel_mix)
avg_deal_mrr = 1_500 # Assumption: $1,500 average deal MRR
deals_this_month = new_mrr / avg_deal_mrr
cac_spend = deals_this_month * weighted_cac
cumulative_cac += cac_spend
cumulative_revenue += mrr * GROSS_MARGIN
if break_even_month is None and cumulative_revenue >= cumulative_cac:
break_even_month = m
snapshots.append(MonthSnapshot(
month=m,
mrr=mrr,
new_mrr=new_mrr,
churned_mrr=churned_mrr,
expansion_mrr=expansion_mrr,
net_new_mrr=net_new_mrr,
cumulative_cac_spend=cumulative_cac,
))
return ModelProjection(
model=model,
snapshots=snapshots,
break_even_month=break_even_month,
)
def _weighted_cac(channel_mix: Dict[str, float]) -> float:
channel_cac = {ch.name: ch.cac for ch in CHANNELS}
total = sum(
channel_mix.get(name, 0) * cac
for name, cac in channel_cac.items()
)
weight_sum = sum(channel_mix.values())
return total / weight_sum if weight_sum > 0 else 5_000
# ---------------------------------------------------------------------------
# Reporting
# ---------------------------------------------------------------------------
def fmt_mrr(n: float) -> str:
if n >= 1_000_000:
return f".3fM"
return f".1fK"
def fmt_currency(n: float) -> str:
if n >= 1_000_000:
return f".2fM"
if n >= 1_000:
return f".1fK"
return f".0f"
def print_header(title: str) -> None:
width = 78
print("\n" + "=" * width)
print(f" {title}")
print("=" * width)
def print_channel_overview() -> None:
print_header("Current Channel Mix")
print(f" Starting MRR: {fmt_mrr(STARTING_MRR)} | Monthly churn: {MONTHLY_CHURN_RATE:.1%} | Expansion: {EXPANSION_RATE:.1%}/mo")
print()
print(f" {'Channel':<22} {'% MRR':>7} {'CAC':>8} {'Payback':>9} {'Growth/mo':>10}")
print(" " + "-" * 60)
for ch in sorted(CHANNELS, key=lambda c: c.pct_of_new_mrr, reverse=True):
print(
f" {ch.name:<22} {ch.pct_of_new_mrr:>6.0%} "
f"{fmt_currency(ch.cac):>8} {ch.payback_months:>7.0f}mo "
f"{ch.monthly_growth_rate:>9.1%}"
)
def print_model_detail(proj: ModelProjection) -> None:
model = proj.model
print_header(f"Model: {model.name}")
print(f" {model.description}")
if model.notes:
print()
for note in model.notes:
print(f" • {note}")
print()
# Print monthly snapshot (every 3 months + final)
milestones = set(range(3, SIMULATION_MONTHS + 1, 3)) | {SIMULATION_MONTHS}
print(f" {'Month':<7} {'MRR':>10} {'New MRR':>9} {'Churned':>9} {'Expand':>8} {'Net New':>9}")
print(" " + "-" * 56)
for snap in proj.snapshots:
if snap.month in milestones:
print(
f" {snap.month:<7} {fmt_mrr(snap.mrr):>10} "
f"{fmt_mrr(snap.new_mrr):>9} {fmt_mrr(snap.churned_mrr):>9} "
f"{fmt_mrr(snap.expansion_mrr):>8} {fmt_mrr(snap.net_new_mrr):>9}"
)
final = proj.snapshots[-1]
growth_x = final.mrr / STARTING_MRR
arr_final = final.mrr * 12
weighted_cac = _weighted_cac(model.channel_mix)
be = f"Month {proj.break_even_month}" if proj.break_even_month else f"> {SIMULATION_MONTHS}mo"
print()
print(f" Final MRR ({SIMULATION_MONTHS}mo): {fmt_mrr(final.mrr)}")
print(f" Final ARR: {fmt_currency(arr_final)}")
print(f" Growth multiple: {growth_x:.1f}x from starting MRR")
print(f" Weighted blended CAC: {fmt_currency(weighted_cac)}")
print(f" Expected LTV:CAC: {model.avg_ltv_cac:.1f}x")
print(f" Months to steady state:{model.months_to_steady_state}")
print(f" CAC break-even: {be}")
def print_comparison_table(projections: List[ModelProjection]) -> None:
print_header(f"Growth Model Comparison — Month {SIMULATION_MONTHS} Outcomes")
header = (
f" {'Model':<20} {'MRR (final)':>12} {'ARR (final)':>12} "
f"{'Growth':>7} {'LTV:CAC':>8} {'Break-even':>11}"
)
print(header)
print(" " + "-" * 74)
for proj in sorted(projections, key=lambda p: p.snapshots[-1].mrr, reverse=True):
final = proj.snapshots[-1]
growth_x = final.mrr / STARTING_MRR
arr_final = final.mrr * 12
be = f"Mo {proj.break_even_month}" if proj.break_even_month else f">{SIMULATION_MONTHS}mo"
print(
f" {proj.model.name:<20} {fmt_mrr(final.mrr):>12} "
f"{fmt_currency(arr_final):>12} {growth_x:>6.1f}x "
f"{proj.model.avg_ltv_cac:>7.1f}x {be:>11}"
)
def print_channel_mix_impact(projections: List[ModelProjection]) -> None:
print_header("Channel Mix Impact Analysis")
print(" How shifting channel mix changes growth trajectory:\n")
baseline = next((p for p in projections if p.model.name == "Current Mix"), None)
if not baseline:
return
baseline_final_mrr = baseline.snapshots[-1].mrr
for proj in projections:
if proj.model.name == "Current Mix":
continue
final_mrr = proj.snapshots[-1].mrr
delta = final_mrr - baseline_final_mrr
delta_pct = (delta / baseline_final_mrr) * 100
arrow = "↑" if delta > 0 else "↓"
m6_mrr = proj.snapshots[5].mrr if len(proj.snapshots) >= 6 else 0
m6_baseline = baseline.snapshots[5].mrr if len(baseline.snapshots) >= 6 else 0
m6_delta = m6_mrr - m6_baseline
m6_pct = (m6_delta / m6_baseline) * 100 if m6_baseline else 0
m6_arrow = "↑" if m6_delta > 0 else "↓"
print(f" {proj.model.name}:")
print(f" Month 6: {m6_arrow} {abs(m6_pct):.1f}% vs. current ({fmt_mrr(m6_delta)} {'more' if m6_delta > 0 else 'less'} MRR)")
print(f" Month {SIMULATION_MONTHS}: {arrow} {abs(delta_pct):.1f}% vs. current ({fmt_mrr(delta)} {'more' if delta > 0 else 'less'} MRR)")
if proj.model.months_to_steady_state > 4:
print(f" ⚠ Model takes {proj.model.months_to_steady_state} months to reach steady state — short-term dip expected.")
print()
def print_decision_guide(projections: List[ModelProjection]) -> None:
print_header("Decision Guide")
print(" Choose your growth model based on your constraints:\n")
guides = [
("ACV < $5K and fast time-to-value", "PLG-First"),
("ACV > $25K and complex buying process", "Sales-Led Scale"),
("Strong practitioner community exists", "Community-Led"),
("Both SMB self-serve and enterprise buyers", "Hybrid PLS"),
("Uncertain — keep optionality", "Current Mix"),
]
for condition, model_name in guides:
proj = next((p for p in projections if p.model.name == model_name), None)
if proj:
final_mrr = proj.snapshots[-1].mrr
print(f" If: {condition}")
print(f" → Use {model_name} → {fmt_mrr(final_mrr)} MRR at month {SIMULATION_MONTHS}")
print()
print(" Key question before switching models:")
print(" 'Do we have 12-18 months of runway to prove the new model")
print(" while the current model continues in parallel?'")
print(" If no → optimize current model. Don't switch.")
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
def main() -> None:
print_channel_overview()
projections = [simulate_model(model, SIMULATION_MONTHS) for model in GROWTH_MODELS]
for proj in projections:
print_model_detail(proj)
print_comparison_table(projections)
print_channel_mix_impact(projections)
print_decision_guide(projections)
print("\n" + "=" * 78)
print(" Notes:")
print(f" Starting MRR: {fmt_mrr(STARTING_MRR)}")
print(f" Simulation: {SIMULATION_MONTHS} months")
print(f" Churn: {MONTHLY_CHURN_RATE:.1%}/mo ({MONTHLY_CHURN_RATE*12:.0%} annualized)")
print(f" Expansion: {EXPANSION_RATE:.1%}/mo of existing MRR")
print(f" Gross margin: {GROSS_MARGIN:.0%}")
print(" Acceleration rates are estimates — validate against your actuals.")
print("=" * 78 + "\n")
if __name__ == "__main__":
main()
FILE:scripts/marketing_budget_modeler.py
#!/usr/bin/env python3
"""
Marketing Budget Modeler
------------------------
Allocates marketing budget across channels based on CAC efficiency and
target MQL volume. Models conservative / moderate / aggressive scenarios.
Usage:
python marketing_budget_modeler.py
Inputs (edit INPUTS section below or extend with argparse):
- Annual revenue target (new ARR)
- Average selling price (ASP)
- Conversion rates by funnel stage
- Historical CAC per channel
- Channel capacity constraints (max MQLs the channel can realistically produce)
Outputs:
- Required MQL volume by channel
- Budget allocation per channel per scenario
- LTV:CAC and payback period per channel
- Summary table across scenarios
"""
from __future__ import annotations
import math
from dataclasses import dataclass, field
from typing import Dict, List, Tuple
# ---------------------------------------------------------------------------
# Data models
# ---------------------------------------------------------------------------
@dataclass
class Channel:
name: str
cac: float # Customer acquisition cost ($)
max_mqls_per_month: int # Realistic capacity ceiling (MQLs/month)
mql_to_close_rate: float # Combined MQL → closed-won rate (0.0–1.0)
payback_months: float # Based on ARPU × gross margin
ltv: float # Lifetime value ($)
trend: str = "stable" # "improving" | "stable" | "declining"
@dataclass
class FunnelRates:
mql_to_sal: float # MQL → Sales Accepted Lead
sal_to_sql: float # SAL → Sales Qualified Lead
sql_to_opp: float # SQL → Opportunity
opp_to_close: float # Opportunity → Closed-Won
@property
def mql_to_close(self) -> float:
return self.mql_to_sal * self.sal_to_sql * self.sql_to_opp * self.opp_to_close
@dataclass
class ScenarioResult:
name: str
total_budget: float
channel_budgets: Dict[str, float]
channel_mqls: Dict[str, int]
projected_customers: int
projected_arr: float
blended_cac: float
notes: List[str] = field(default_factory=list)
# ---------------------------------------------------------------------------
# INPUTS — edit these
# ---------------------------------------------------------------------------
TARGET_NEW_ARR = 3_000_000 # New ARR to generate this year ($)
ASP_ANNUAL = 18_000 # Average annual contract value ($)
GROSS_MARGIN = 0.75 # Product gross margin (%)
ARPU_MONTHLY = ASP_ANNUAL / 12 # Monthly revenue per account
FUNNEL = FunnelRates(
mql_to_sal=0.65,
sal_to_sql=0.45,
sql_to_opp=0.75,
opp_to_close=0.27,
)
# LTV = ARPU_monthly × gross_margin / monthly_churn_rate
MONTHLY_CHURN = 0.012 # ~14% annual churn
LTV = (ARPU_MONTHLY * GROSS_MARGIN) / MONTHLY_CHURN
CHANNELS: List[Channel] = [
Channel(
name="Organic SEO",
cac=1_800,
max_mqls_per_month=80,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(1_800 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="improving",
),
Channel(
name="Paid Search",
cac=6_200,
max_mqls_per_month=60,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(6_200 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="stable",
),
Channel(
name="Paid Social (LinkedIn)",
cac=8_500,
max_mqls_per_month=35,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(8_500 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="declining",
),
Channel(
name="Outbound SDR",
cac=5_100,
max_mqls_per_month=50,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(5_100 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="stable",
),
Channel(
name="Events / Field",
cac=9_800,
max_mqls_per_month=25,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(9_800 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="stable",
),
Channel(
name="Partner / Channel",
cac=3_400,
max_mqls_per_month=30,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(3_400 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="improving",
),
Channel(
name="Content / Inbound",
cac=2_600,
max_mqls_per_month=45,
mql_to_close_rate=FUNNEL.mql_to_close,
payback_months=(2_600 / (ARPU_MONTHLY * GROSS_MARGIN)),
ltv=LTV,
trend="improving",
),
]
# ---------------------------------------------------------------------------
# Core calculations
# ---------------------------------------------------------------------------
def customers_needed(target_arr: float, asp: float) -> int:
return math.ceil(target_arr / asp)
def mqls_needed_total(customers: int, mql_to_close: float) -> int:
return math.ceil(customers / mql_to_close)
def ltv_to_cac(ltv: float, cac: float) -> float:
return ltv / cac if cac > 0 else 0.0
def score_channel(ch: Channel) -> float:
"""
Score a channel for budget priority.
Higher = more efficient. Used to rank allocation order.
Factors: LTV:CAC ratio, trend multiplier, capacity.
"""
ratio = ltv_to_cac(ch.ltv, ch.cac)
trend_mult = {"improving": 1.2, "stable": 1.0, "declining": 0.7}.get(ch.trend, 1.0)
return ratio * trend_mult
def allocate_mqls(
channels: List[Channel],
total_mqls_needed: int,
budget_multiplier: float = 1.0,
) -> Tuple[Dict[str, int], Dict[str, float]]:
"""
Allocate MQL targets across channels in priority order (best LTV:CAC first).
budget_multiplier: 0.7 = conservative, 1.0 = moderate, 1.3 = aggressive.
Returns (channel → MQLs, channel → budget).
"""
ranked = sorted(channels, key=score_channel, reverse=True)
remaining = total_mqls_needed
channel_mqls: Dict[str, int] = {}
channel_budget: Dict[str, float] = {}
for ch in ranked:
if remaining <= 0:
channel_mqls[ch.name] = 0
channel_budget[ch.name] = 0.0
continue
# Apply capacity ceiling scaled by multiplier (aggressive = push capacity)
capacity = int(ch.max_mqls_per_month * 12 * budget_multiplier)
allocated = min(remaining, capacity)
channel_mqls[ch.name] = allocated
channel_budget[ch.name] = allocated * ch.cac
remaining -= allocated
return channel_mqls, channel_budget
def build_scenario(
name: str,
channels: List[Channel],
total_mqls: int,
multiplier: float,
notes: List[str],
) -> ScenarioResult:
channel_mqls, channel_budget = allocate_mqls(channels, total_mqls, multiplier)
total_budget = sum(channel_budget.values())
total_mqls_allocated = sum(channel_mqls.values())
projected_customers = math.floor(total_mqls_allocated * FUNNEL.mql_to_close)
projected_arr = projected_customers * ASP_ANNUAL
# Blended CAC = total budget / customers acquired
blended_cac = total_budget / projected_customers if projected_customers > 0 else 0.0
return ScenarioResult(
name=name,
total_budget=total_budget,
channel_budgets=channel_budget,
channel_mqls=channel_mqls,
projected_customers=projected_customers,
projected_arr=projected_arr,
blended_cac=blended_cac,
notes=notes,
)
# ---------------------------------------------------------------------------
# Reporting
# ---------------------------------------------------------------------------
def fmt_currency(n: float) -> str:
if n >= 1_000_000:
return f".2fM"
if n >= 1_000:
return f".1fK"
return f".0f"
def fmt_ratio(n: float) -> str:
return f"{n:.1f}x"
def print_header(title: str) -> None:
width = 72
print("\n" + "=" * width)
print(f" {title}")
print("=" * width)
def print_channel_table(channels: List[Channel]) -> None:
print_header("Channel Analysis — Current State")
header = f"{'Channel':<25} {'CAC':>8} {'Payback':>9} {'LTV:CAC':>8} {'Cap/mo':>7} {'Trend':>10}"
print(header)
print("-" * 72)
for ch in sorted(channels, key=score_channel, reverse=True):
ratio = ltv_to_cac(ch.ltv, ch.cac)
flag = ""
if ratio < 1:
flag = " ⚠ LOSS"
elif ratio >= 6:
flag = " ★ STRONG"
elif ratio >= 3:
flag = " ✓"
print(
f"{ch.name:<25} {fmt_currency(ch.cac):>8} "
f"{ch.payback_months:>7.1f}mo {fmt_ratio(ratio):>8} "
f"{ch.max_mqls_per_month:>7} {ch.trend:>10}{flag}"
)
def print_funnel_summary(customers: int, mqls: int) -> None:
print_header("Funnel Requirements")
print(f" Target new ARR: {fmt_currency(TARGET_NEW_ARR)}")
print(f" Average selling price: {fmt_currency(ASP_ANNUAL)}")
print(f" New customers needed: {customers}")
print(f" Funnel MQL→Close rate: {FUNNEL.mql_to_close:.1%}")
print(f" Total MQLs needed: {mqls}")
print(f"\n Funnel stage rates:")
print(f" MQL → SAL: {FUNNEL.mql_to_sal:.0%}")
print(f" SAL → SQL: {FUNNEL.mql_to_sal * FUNNEL.sal_to_sql:.0%}")
print(f" SQL → Opportunity: {FUNNEL.mql_to_sal * FUNNEL.sal_to_sql * FUNNEL.sql_to_opp:.0%}")
print(f" Opportunity → Close: {FUNNEL.mql_to_close:.0%}")
print(f"\n LTV (estimated): {fmt_currency(LTV)}")
print(f" Monthly churn: {MONTHLY_CHURN:.1%} ({MONTHLY_CHURN*12:.0%} annualized)")
def print_scenario(result: ScenarioResult, channels: List[Channel]) -> None:
print_header(f"Scenario: {result.name}")
print(f" Total marketing budget: {fmt_currency(result.total_budget)}")
print(f" Projected customers: {result.projected_customers}")
print(f" Projected new ARR: {fmt_currency(result.projected_arr)}")
print(f" Blended CAC: {fmt_currency(result.blended_cac)}")
blended_ltv_cac = LTV / result.blended_cac if result.blended_cac > 0 else 0
blended_payback = result.blended_cac / (ARPU_MONTHLY * GROSS_MARGIN)
print(f" Blended LTV:CAC: {fmt_ratio(blended_ltv_cac)}", end="")
if blended_ltv_cac < 1:
print(" ⚠ BELOW BREAK-EVEN")
elif blended_ltv_cac < 3:
print(" △ MARGINAL")
elif blended_ltv_cac >= 3:
print(" ✓ HEALTHY")
else:
print()
print(f" Blended payback: {blended_payback:.1f} months")
if result.notes:
print(f"\n Notes:")
for note in result.notes:
print(f" • {note}")
print(f"\n {'Channel':<25} {'MQLs':>6} {'Budget':>10} {'% of Budget':>12} {'LTV:CAC':>8}")
print(" " + "-" * 65)
for ch in sorted(channels, key=score_channel, reverse=True):
mqls = result.channel_mqls.get(ch.name, 0)
budget = result.channel_budgets.get(ch.name, 0.0)
pct = (budget / result.total_budget * 100) if result.total_budget > 0 else 0
ratio = ltv_to_cac(ch.ltv, ch.cac)
print(
f" {ch.name:<25} {mqls:>6} {fmt_currency(budget):>10} "
f"{pct:>11.1f}% {fmt_ratio(ratio):>8}"
)
def print_scenario_comparison(scenarios: List[ScenarioResult]) -> None:
print_header("Scenario Comparison")
header = f"{'Scenario':<18} {'Budget':>10} {'Customers':>10} {'ARR':>10} {'Blended CAC':>12} {'LTV:CAC':>8} {'Payback':>9}"
print(header)
print("-" * 82)
for s in scenarios:
blended_ltv_cac = LTV / s.blended_cac if s.blended_cac > 0 else 0
blended_payback = s.blended_cac / (ARPU_MONTHLY * GROSS_MARGIN)
print(
f"{s.name:<18} {fmt_currency(s.total_budget):>10} "
f"{s.projected_customers:>10} {fmt_currency(s.projected_arr):>10} "
f"{fmt_currency(s.blended_cac):>12} {fmt_ratio(blended_ltv_cac):>8} "
f"{blended_payback:>7.1f}mo"
)
def print_recommendations(channels: List[Channel]) -> None:
print_header("Channel Recommendations")
scale = [ch for ch in channels if score_channel(ch) >= 1.5 and ch.trend in ("improving", "stable")]
hold = [ch for ch in channels if 0.8 <= score_channel(ch) < 1.5 or (ch.trend == "stable" and ltv_to_cac(ch.ltv, ch.cac) >= 3)]
cut = [ch for ch in channels if ltv_to_cac(ch.ltv, ch.cac) < 2 or ch.trend == "declining"]
# Deduplicate
hold = [ch for ch in hold if ch not in scale]
cut = [ch for ch in cut if ch not in scale and ch not in hold]
if scale:
print(" SCALE (strong LTV:CAC, improving or stable trend):")
for ch in scale:
print(f" + {ch.name} [LTV:CAC {fmt_ratio(ltv_to_cac(ch.ltv, ch.cac))}, payback {ch.payback_months:.0f}mo]")
if hold:
print(" HOLD (monitor — adequate but not outstanding):")
for ch in hold:
print(f" = {ch.name} [LTV:CAC {fmt_ratio(ltv_to_cac(ch.ltv, ch.cac))}, trend: {ch.trend}]")
if cut:
print(" CUT or REDUCE (poor LTV:CAC or declining):")
for ch in cut:
print(f" - {ch.name} [LTV:CAC {fmt_ratio(ltv_to_cac(ch.ltv, ch.cac))}, trend: {ch.trend}]")
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
def main() -> None:
customers = customers_needed(TARGET_NEW_ARR, ASP_ANNUAL)
total_mqls = mqls_needed_total(customers, FUNNEL.mql_to_close)
print_channel_table(CHANNELS)
print_funnel_summary(customers, total_mqls)
scenarios = [
build_scenario(
name="Conservative",
channels=CHANNELS,
total_mqls=total_mqls,
multiplier=0.7,
notes=[
"Prioritizes lowest CAC channels only.",
"May not reach MQL target — expect ~70% of goal.",
"Best for capital-constrained orgs or short runway.",
],
),
build_scenario(
name="Moderate",
channels=CHANNELS,
total_mqls=total_mqls,
multiplier=1.0,
notes=[
"Balanced allocation — efficiency-first but full MQL target.",
"Recommended baseline. Revisit Q2 based on actuals.",
],
),
build_scenario(
name="Aggressive",
channels=CHANNELS,
total_mqls=total_mqls,
multiplier=1.4,
notes=[
"Pushes all channels toward capacity ceiling.",
"Higher spend on lower-efficiency channels to hit volume.",
"Requires > 18-month runway to justify payback period.",
],
),
]
for scenario in scenarios:
print_scenario(scenario, CHANNELS)
print_scenario_comparison(scenarios)
print_recommendations(CHANNELS)
print("\n" + "=" * 72)
print(" Key questions before finalizing budget:")
print(" 1. What is the payback period the CFO/board will accept?")
print(" 2. Is CAC for declining-trend channels actually recoverable?")
print(" 3. Does the moderate scenario require sales headcount increase?")
print(" 4. Which channels have capacity to absorb 20% more spend?")
print("=" * 72 + "\n")
if __name__ == "__main__":
main()
Phân tích codebase và tạo tài liệu hướng dẫn cho kỹ sư, tech lead và cộng tác viên mới.
---
name: "codebase-onboarding"
description: "Analyze a codebase and generate onboarding documentation for engineers, tech leads, and contractors. Fast fact-gathering and repeatable onboarding outputs. Use when onboarding a new engineer, writing architecture-overview docs for a new project, or producing tech-lead briefings for unfamiliar repos."
---
# Codebase Onboarding
**Tier:** POWERFUL
**Category:** Engineering
**Domain:** Documentation / Developer Experience
---
## Overview
Analyze a codebase and generate onboarding documentation for engineers, tech leads, and contractors. This skill is optimized for fast fact-gathering and repeatable onboarding outputs.
## Core Capabilities
- Architecture and stack discovery from repository signals
- Key file and config inventory for new contributors
- Local setup and common-task guidance generation
- Audience-aware documentation framing
- Debugging and contribution checklist scaffolding
---
## When to Use
- Onboarding a new team member or contractor
- Rebuilding stale project docs after large refactors
- Preparing internal handoff documentation
- Creating a standardized onboarding packet for services
---
## Quick Start
```bash
# 1) Gather codebase facts
python3 scripts/codebase_analyzer.py /path/to/repo
# 2) Export machine-readable output
python3 scripts/codebase_analyzer.py /path/to/repo --json
# 3) Use the template to draft onboarding docs
# See references/onboarding-template.md
```
---
## Recommended Workflow
1. Run `scripts/codebase_analyzer.py` against the target repository.
2. Capture key signals: file counts, detected languages, config files, top-level structure.
3. Fill the onboarding template in `references/onboarding-template.md`.
4. Tailor output depth by audience:
- Junior: setup + guardrails
- Senior: architecture + operational concerns
- Contractor: scoped ownership + integration boundaries
---
## Onboarding Document Template
Detailed template and section examples live in:
- `references/onboarding-template.md`
- `references/output-format-templates.md`
---
## Common Pitfalls
- Writing docs without validating setup commands on a clean environment
- Mixing architecture deep-dives into contractor-oriented docs
- Omitting troubleshooting and verification steps
- Letting onboarding docs drift from current repo state
## Best Practices
1. Keep setup instructions executable and time-bounded.
2. Document the "why" for key architectural decisions.
3. Update docs in the same PR as behavior changes.
4. Treat onboarding docs as living operational assets, not one-time deliverables.
FILE:references/onboarding-template.md
# Onboarding Document Template
## README.md - Full Template
```markdown
# [Project Name]
> One-sentence description of what this does and who uses it.
[](https://github.com/org/repo/actions/workflows/ci.yml)
[](https://codecov.io/gh/org/repo)
## What is this?
[2-3 sentences: problem it solves, who uses it, current state]
**Live:** https://myapp.com
**Staging:** https://staging.myapp.com
**Docs:** https://docs.myapp.com
---
## Quick Start
### Prerequisites
| Tool | Version | Install |
|------|---------|---------|
| Node.js | 20+ | `nvm install 20` |
| pnpm | 8+ | `npm i -g pnpm` |
| Docker | 24+ | [docker.com](https://docker.com) |
| PostgreSQL | 16+ | via Docker (see below) |
### Setup (5 minutes)
```bash
git clone https://github.com/org/repo
cd repo
pnpm install
docker compose up -d
cp .env.example .env
pnpm db:migrate
pnpm db:seed
pnpm dev
pnpm test
```
### Verify it works
- [ ] App loads on localhost
- [ ] Health endpoint returns ok
- [ ] Tests pass
---
## Architecture
### System Overview
```
Browser / Mobile
|
v
[Next.js App] <- [Auth]
|
+-> [PostgreSQL]
+-> [Redis]
+-> [S3]
```
### Tech Stack
| Layer | Technology | Why |
|-------|-----------|-----|
| Frontend | Next.js | SSR + routing |
| Styling | Tailwind + shadcn/ui | Rapid UI |
| API | Route handlers | Co-location |
| Database | PostgreSQL | Relational |
| Queue | BullMQ + Redis | Background jobs |
---
## Key Files
| Path | Purpose |
|------|---------|
| `app/` | Pages and route handlers |
| `src/db/` | Schema and migrations |
| `src/lib/` | Shared utilities |
| `tests/` | Test suites and helpers |
| `.env.example` | Required variables |
---
## Common Developer Tasks
### Add a new API endpoint
```bash
touch app/api/my-resource/route.ts
touch tests/api/my-resource.test.ts
```
### Run a database migration
```bash
pnpm db:generate
pnpm db:migrate
```
### Add a background job
```bash
# Create worker module and enqueue path
```
---
## Debugging Guide
### Common Errors
- Missing environment variable
- Database connectivity failure
- Expired auth token
- Generic 500 in local dev
### Useful SQL Queries
- Slow query checks
- Connection status
- Table bloat checks
### Log Locations
| Environment | Logs |
|-------------|------|
| Local dev | local terminal |
| Production | platform logs |
| Worker | worker process logs |
---
## Contribution Guidelines
### Branch Strategy
- `main` protected
- feature/fix branches with ticket IDs
### PR Requirements
- CI green
- Tests updated
- Why documented
- Self-review completed
### Commit Convention
- `feat(scope): ...`
- `fix(scope): ...`
- `docs: ...`
---
## Audience-Specific Notes
### Junior Developers
- Start with core auth/data modules
- Follow tests as executable examples
### Senior Engineers
- Read ADRs and scaling notes first
- Validate performance/security assumptions early
### Contractors
- Stay within scoped feature boundaries
- Use wrappers for external integrations
```
## Usage Notes
- Keep onboarding setup under 10 minutes where possible.
- Include executable verification checks after each setup phase.
- Prefer links to canonical docs instead of duplicating long content.
- Update this template when stack conventions or tooling change.
FILE:references/output-format-templates.md
# codebase-onboarding reference
## Output Formats
### Notion Export
```javascript
// Use Notion API to create onboarding page
const { Client } = require('@notionhq/client')
const notion = new Client({ auth: process.env.NOTION_TOKEN })
const blocks = markdownToNotionBlocks(onboardingMarkdown) // use notion-to-md
await notion.pages.create({
parent: { page_id: ONBOARDING_PARENT_PAGE_ID },
properties: { title: { title: [{ text: { content: 'Engineer Onboarding — MyApp' } }] } },
children: blocks,
})
```
### Confluence Export
```bash
# Using confluence-cli or REST API
curl -X POST \
-H "Content-Type: application/json" \
-u "user@example.com:$CONFLUENCE_TOKEN" \
"https://yourorg.atlassian.net/wiki/rest/api/content" \
-d '{
"type": "page",
"title": "Codebase Onboarding",
"space": {"key": "ENG"},
"body": {
"storage": {
"value": "<p>Generated content...</p>",
"representation": "storage"
}
}
}'
```
---
FILE:scripts/codebase_analyzer.py
#!/usr/bin/env python3
"""Generate a compact onboarding summary for a codebase (stdlib only)."""
from __future__ import annotations
import argparse
import json
import os
from collections import Counter
from pathlib import Path
from typing import Dict, Iterable, List
IGNORED_DIRS = {
".git",
"node_modules",
".next",
"dist",
"build",
"coverage",
"venv",
".venv",
"__pycache__",
}
EXT_TO_LANG = {
".py": "Python",
".ts": "TypeScript",
".tsx": "TypeScript",
".js": "JavaScript",
".jsx": "JavaScript",
".go": "Go",
".rs": "Rust",
".java": "Java",
".kt": "Kotlin",
".rb": "Ruby",
".php": "PHP",
".cs": "C#",
".c": "C",
".cpp": "C++",
".h": "C/C++",
".swift": "Swift",
".sql": "SQL",
".sh": "Shell",
}
KEY_CONFIG_FILES = [
"package.json",
"pnpm-workspace.yaml",
"turbo.json",
"nx.json",
"lerna.json",
"tsconfig.json",
"next.config.js",
"next.config.mjs",
"pyproject.toml",
"requirements.txt",
"go.mod",
"Cargo.toml",
"docker-compose.yml",
"Dockerfile",
".github/workflows",
]
def iter_files(root: Path) -> Iterable[Path]:
for dirpath, dirnames, filenames in os.walk(root):
dirnames[:] = [d for d in dirnames if d not in IGNORED_DIRS]
for name in filenames:
path = Path(dirpath) / name
if path.is_file():
yield path
def detect_languages(paths: Iterable[Path]) -> Dict[str, int]:
counts: Counter[str] = Counter()
for path in paths:
lang = EXT_TO_LANG.get(path.suffix.lower())
if lang:
counts[lang] += 1
return dict(sorted(counts.items(), key=lambda item: (-item[1], item[0])))
def find_key_configs(root: Path) -> List[str]:
found: List[str] = []
for rel in KEY_CONFIG_FILES:
if (root / rel).exists():
found.append(rel)
return found
def top_level_structure(root: Path, max_depth: int) -> List[str]:
lines: List[str] = []
for dirpath, dirnames, filenames in os.walk(root):
rel = Path(dirpath).relative_to(root)
depth = 0 if str(rel) == "." else len(rel.parts)
if depth > max_depth:
dirnames[:] = []
continue
if any(part in IGNORED_DIRS for part in rel.parts):
dirnames[:] = []
continue
indent = " " * depth
if str(rel) != ".":
lines.append(f"{indent}{rel.name}/")
visible_files = [f for f in sorted(filenames) if not f.startswith(".")]
for filename in visible_files[:10]:
lines.append(f"{indent} {filename}")
dirnames[:] = sorted([d for d in dirnames if d not in IGNORED_DIRS])
return lines
def build_report(root: Path, max_depth: int) -> Dict[str, object]:
files = list(iter_files(root))
languages = detect_languages(files)
total_files = len(files)
file_count_by_ext: Counter[str] = Counter(p.suffix.lower() or "<no-ext>" for p in files)
largest = sorted(
((str(p.relative_to(root)), p.stat().st_size) for p in files),
key=lambda item: item[1],
reverse=True,
)[:20]
return {
"root": str(root),
"file_count": total_files,
"languages": languages,
"key_config_files": find_key_configs(root),
"top_extensions": dict(file_count_by_ext.most_common(12)),
"largest_files": largest,
"directory_structure": top_level_structure(root, max_depth),
}
def format_size(num_bytes: int) -> str:
units = ["B", "KB", "MB", "GB"]
value = float(num_bytes)
for unit in units:
if value < 1024 or unit == units[-1]:
return f"{value:.1f}{unit}"
value /= 1024
return f"{num_bytes}B"
def print_text(report: Dict[str, object]) -> None:
print("Codebase Onboarding Summary")
print(f"Root: {report['root']}")
print(f"Total files: {report['file_count']}")
print("")
print("Languages detected")
if report["languages"]:
for lang, count in report["languages"].items():
print(f"- {lang}: {count}")
else:
print("- No recognized source file extensions")
print("")
print("Key config files")
configs = report["key_config_files"]
if configs:
for cfg in configs:
print(f"- {cfg}")
else:
print("- None found from default checklist")
print("")
print("Largest files")
for rel, size in report["largest_files"][:10]:
print(f"- {rel}: {format_size(size)}")
print("")
print("Directory structure")
for line in report["directory_structure"][:200]:
print(line)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Scan a repository and generate onboarding summary facts.")
parser.add_argument("path", help="Path to project directory")
parser.add_argument("--max-depth", type=int, default=2, help="Max depth for structure output (default: 2)")
parser.add_argument("--json", action="store_true", help="Print JSON output")
return parser.parse_args()
def main() -> int:
args = parse_args()
root = Path(args.path).expanduser().resolve()
if not root.exists() or not root.is_dir():
raise SystemExit(f"Path is not a directory: {root}")
report = build_report(root, max_depth=max(1, args.max_depth))
if args.json:
print(json.dumps(report, indent=2))
else:
print_text(report)
return 0
if __name__ == "__main__":
raise SystemExit(main())
Phân tích ngược codebase frontend để tạo tài liệu yêu cầu sản phẩm (PRD).
---
name: code-to-prd
description: Reverse-engineer a frontend codebase into a PRD. Usage: /code-to-prd [path]
---
# /code-to-prd
Reverse-engineer a frontend codebase into a complete Product Requirements Document.
## Usage
```bash
/code-to-prd # Analyze current project
/code-to-prd ./src # Analyze specific directory
/code-to-prd /path/to/project # Analyze external project
```
## What It Does
1. **Scan** — Run `codebase_analyzer.py` to detect framework, routes, APIs, enums, and project structure
2. **Scaffold** — Run `prd_scaffolder.py` to create `prd/` directory with README.md, per-page stubs, and appendix files
3. **Analyze** — Walk through each page following the Phase 2 workflow: fields, interactions, API dependencies, page relationships
4. **Generate** — Produce the final PRD with all pages, enum dictionary, API inventory, and page relationship map
## Steps
### Step 1: Analyze
Determine the project path (default: current directory). Run the frontend analyzer:
```bash
python3 {skill_path}/scripts/codebase_analyzer.py {project_path} -o .code-to-prd-analysis.json
```
Display a summary of findings: framework, page count, API count, enum count.
### Step 2: Scaffold
Generate the PRD directory skeleton:
```bash
python3 {skill_path}/scripts/prd_scaffolder.py .code-to-prd-analysis.json -o prd/
```
### Step 3: Fill
For each page in the inventory, follow the SKILL.md Phase 2 workflow:
- Read the page's component files
- Document fields, interactions, API dependencies, page relationships
- Fill in the corresponding `prd/pages/` stub
Work in batches of 3-5 pages for large projects (>15 pages). Ask the user to confirm after each batch.
### Step 4: Finalize
Complete the appendix files:
- `prd/appendix/enum-dictionary.md` — all enums and status codes found
- `prd/appendix/api-inventory.md` — consolidated API reference
- `prd/appendix/page-relationships.md` — navigation and data coupling map
Clean up the temporary analysis file:
```bash
rm .code-to-prd-analysis.json
```
## Output
A `prd/` directory containing:
- `README.md` — system overview, module map, page inventory
- `pages/*.md` — one file per page with fields, interactions, APIs
- `appendix/*.md` — enum dictionary, API inventory, page relationships
## Skill Reference
- `product-team/code-to-prd/SKILL.md`
- `product-team/code-to-prd/scripts/codebase_analyzer.py`
- `product-team/code-to-prd/scripts/prd_scaffolder.py`
- `product-team/code-to-prd/references/prd-quality-checklist.md`
Tạo tệp CodeTour hướng dẫn từng bước, liên kết tới tệp và dòng mã thật cho từng nhóm đối tượng.
---
name: "code-tour"
description: "Use when the user asks to create a CodeTour .tour file — persona-targeted, step-by-step walkthroughs that link to real files and line numbers. Trigger for: create a tour, onboarding tour, architecture tour, PR review tour, explain how X works, vibe check, RCA tour, contributor guide, or any structured code walkthrough request."
---
# Code Tour
Create **CodeTour** files — persona-targeted, step-by-step walkthroughs of a codebase that link directly to files and line numbers. CodeTour files live in `.tours/` and work with the [VS Code CodeTour extension](https://github.com/microsoft/codetour).
## Overview
A great tour is a **narrative** — a story told to a specific person about what matters, why it matters, and what to do next. Only create `.tour` JSON files. Never modify source code.
## When to Use This Skill
- User asks to create a code tour, onboarding tour, or architecture walkthrough
- User says "tour for this PR", "explain how X works", "vibe check", "RCA tour"
- User wants a contributor guide, security review, or bug investigation walkthrough
- Any request for a structured walkthrough with file/line anchors
## Core Workflow
### 1. Discover the repo
Before asking anything, explore the codebase:
In parallel: list root directory, read README, check config files.
Then: identify language(s), framework(s), project purpose. Map folder structure 1-2 levels deep. Find entry points — every path in the tour must be real.
If the repo has fewer than 5 source files, create a quick-depth tour regardless of persona — there's not enough to warrant a deep one.
### 2. Infer the intent
One message should be enough. Infer persona, depth, and focus silently.
| User says | Persona | Depth |
|-----------|---------|-------|
| "tour for this PR" | pr-reviewer | standard |
| "why did X break" / "RCA" | rca-investigator | standard |
| "onboarding" / "new joiner" | new-joiner | standard |
| "quick tour" / "vibe check" | vibecoder | quick |
| "architecture" | architect | deep |
| "security" / "auth review" | security-reviewer | standard |
| (no qualifier) | new-joiner | standard |
When intent is ambiguous, default to **new-joiner** persona at **standard** depth — it's the most generally useful.
### 3. Read actual files
**Every file path and line number must be verified.** A tour pointing to the wrong line is worse than no tour.
### 4. Write the tour
Save to `.tours/<persona>-<focus>.tour`.
```json
{
"$schema": "https://aka.ms/codetour-schema",
"title": "Descriptive Title — Persona / Goal",
"description": "Who this is for and what they'll understand after.",
"ref": "<current-branch-or-commit>",
"steps": []
}
```
### Step types
| Type | When to use | Example |
|------|-------------|---------|
| **Content** | Intro/closing only (max 2) | `{ "title": "Welcome", "description": "..." }` |
| **Directory** | Orient to a module | `{ "directory": "src/services", "title": "..." }` |
| **File + line** | The workhorse | `{ "file": "src/auth.ts", "line": 42, "title": "..." }` |
| **Selection** | Highlight a code block | `{ "file": "...", "selection": {...}, "title": "..." }` |
| **Pattern** | Regex match (volatile files) | `{ "file": "...", "pattern": "class App", "title": "..." }` |
| **URI** | Link to PR, issue, doc | `{ "uri": "https://...", "title": "..." }` |
### Step count
| Depth | Steps | Use for |
|-------|-------|---------|
| Quick | 5-8 | Vibecoder, fast exploration |
| Standard | 9-13 | Most personas |
| Deep | 14-18 | Architect, RCA |
### Writing descriptions — SMIG formula
- **S — Situation**: What is the reader looking at?
- **M — Mechanism**: How does this code work?
- **I — Implication**: Why does this matter for this persona?
- **G — Gotcha**: What would a smart person get wrong?
### 5. Validate
- [ ] Every `file` path relative to repo root (no leading `/` or `./`)
- [ ] Every `file` confirmed to exist
- [ ] Every `line` verified by reading the file
- [ ] First step has `file` or `directory` anchor
- [ ] At most 2 content-only steps
- [ ] `nextTour` matches another tour's `title` exactly if set
## Personas
| Persona | Goal | Must cover |
|---------|------|------------|
| **Vibecoder** | Get the vibe fast | Entry point, main modules. Max 8 steps. |
| **New joiner** | Structured ramp-up | Directories, setup, business context |
| **Bug fixer** | Root cause fast | Trigger -> fault points -> tests |
| **RCA investigator** | Why did it fail | Causality chain, observability anchors |
| **Feature explainer** | End-to-end | UI -> API -> backend -> storage |
| **PR reviewer** | Review correctly | Change story, invariants, risky areas |
| **Architect** | Shape and rationale | Boundaries, tradeoffs, extension points |
| **Security reviewer** | Trust boundaries | Auth flow, validation, secret handling |
| **Refactorer** | Safe restructuring | Seams, hidden deps, extraction order |
| **External contributor** | Contribute safely | Safe areas, conventions, landmines |
## Narrative Arc
1. **Orientation** — `file` or `directory` step (never content-only first step — blank in VS Code)
2. **High-level map** — 1-3 directory steps showing major modules
3. **Core path** — file/line steps, the heart of the tour
4. **Closing** — what the reader can now do, suggested follow-ups
## Anti-Patterns
| Anti-pattern | Fix |
|---|---|
| **File listing** — "this file contains the models" | Tell a story. Each step depends on the previous. |
| **Generic descriptions** | Name the specific pattern unique to this codebase. |
| **Line number guessing** | Never write a line you didn't verify by reading. |
| **Too many steps** for quick depth | Actually cut steps. |
| **Hallucinated files** | If it doesn't exist, skip the step. |
| **Recap closing** — "we covered X, Y, Z" | Tell the reader what they can now *do*. |
| **Content-only first step** | Anchor step 1 to a file or directory. |
## Cross-References
- Related: `engineering/codebase-onboarding` — for broader onboarding beyond tours
- Related: `engineering/pr-review-expert` — for automated PR review workflows
- CodeTour extension: [microsoft/codetour](https://github.com/microsoft/codetour)
- Real-world tours: [coder/code-server](https://github.com/coder/code-server/blob/main/.tours/contributing.tour)
Khung vận hành công ty: chọn hệ điều hành (EOS, OKR...), sơ đồ trách nhiệm, scorecard, nhịp họp và mục tiêu 90 ngày.
---
name: "company-os"
description: "The meta-framework for how a company runs — the connective tissue between all C-suite roles. Covers operating system selection (EOS, Scaling Up, OKR-native, hybrid), accountability charts, scorecards, meeting pulse, issue resolution, and 90-day rocks. Use when setting up company operations, selecting a management framework, designing meeting rhythms, building accountability systems, implementing OKRs, or when user mentions EOS, Scaling Up, operating system, L10 meetings, rocks, scorecard, accountability chart, or quarterly planning."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: company-operations
updated: 2026-03-05
frameworks: os-comparison, implementation-guide
---
# Company Operating System
The operating system is the collection of tools, rhythms, and agreements that determine how the company functions. Every company has one — most just don't know what it is. Making it explicit makes it improvable.
## Keywords
operating system, EOS, Entrepreneurial Operating System, Scaling Up, Rockefeller Habits, OKR, Holacracy, L10 meeting, rocks, scorecard, accountability chart, issues list, IDS, meeting pulse, quarterly planning, weekly scorecard, management framework, company rhythm, traction, Gino Wickman, Verne Harnish
## Why This Matters
Most operational dysfunction isn't a people problem — it's a system problem. When:
- The same issues recur every week: no issue resolution system
- Meetings feel pointless: no structured meeting pulse
- Nobody knows who owns what: no accountability chart
- Quarterly goals slip: rocks aren't real commitments
Fix the system. The people will operate better inside it.
## The Six Core Components
Every effective operating system has these six, regardless of which framework you choose:
### 1. Accountability Chart
Not an org chart. An accountability chart answers: "Who owns this outcome?"
**Key distinction:** One person owns each function. Multiple people may work in it. Ownership means the buck stops with one person.
**Structure:**
```
CEO
├── Sales (CRO/VP Sales)
│ ├── Inbound pipeline
│ └── Outbound pipeline
├── Product & Engineering (CTO/CPO)
│ ├── Product roadmap
│ └── Engineering delivery
├── Operations (COO)
│ ├── Customer success
│ └── Finance & Legal
└── People (CHRO/VP People)
├── Recruiting
└── People operations
```
**Rules:**
- No shared ownership. "Alice and Bob both own it" means nobody owns it.
- One person can own multiple seats at early stages. That's fine. Just be explicit.
- Revisit quarterly as you scale. Ownership shifts as the company grows.
**Build it in a workshop:**
1. List all functions the company performs
2. Assign one owner per function — no exceptions
3. Identify gaps (functions nobody owns) and overlaps (functions two people think they own)
4. Publish it. Update it when something changes.
### 2. Scorecard
Weekly metrics that tell you if the company is on track. Not monthly. Not quarterly. Weekly.
**Rules:**
- 5–15 metrics maximum. More than 15 and nothing gets attention.
- Each metric has an owner and a weekly target (not a range — a number).
- Red/yellow/green status. Not paragraphs.
- The scorecard is discussed at the leadership team weekly meeting. Only red metrics get discussion time.
**Example scorecard structure:**
| Metric | Owner | Target | This Week | Status |
|--------|-------|--------|-----------|--------|
| New MRR | CRO | €50K | €43K | 🔴 |
| Churn | CS Lead | < 1% | 0.8% | 🟢 |
| Active users | CPO | 2,000 | 2,150 | 🟢 |
| Deployments | CTO | 3/week | 3 | 🟢 |
| Open critical bugs | CTO | 0 | 2 | 🔴 |
| Runway | CFO | > 18mo | 16mo | 🟡 |
**Anti-pattern:** Measuring everything. If you track 40 KPIs, you're watching, not managing.
### 3. Meeting Pulse
The meeting rhythm that drives the company. Not optional — the pulse is what keeps the company alive.
**The full rhythm:**
| Meeting | Frequency | Duration | Who | Purpose |
|---------|-----------|----------|-----|---------|
| Daily standup | Daily | 15 min | Each team | Blockers only |
| L10 / Leadership sync | Weekly | 90 min | Leadership team | Scorecard + issues |
| Department review | Monthly | 60 min | Dept + leadership | OKR progress |
| Quarterly planning | Quarterly | 1–2 days | Leadership | Set rocks, review strategy |
| Annual planning | Annual | 2–3 days | Leadership | 1-year + 3-year vision |
**The L10 meeting (Weekly Leadership Sync):**
Named for the goal of each meeting being a 10/10. Fixed agenda:
1. Good news (5 min) — personal + business
2. Scorecard review (5 min) — flag red items only
3. Rock review (5 min) — on/off track for each rock
4. Customer/employee headlines (5 min)
5. Issues list (60 min) — IDS (see below)
6. To-dos review (5 min) — last week's commitments
7. Conclude (5 min) — rate the meeting 1–10, what would make it a 10 next time
### 4. Issue Resolution (IDS)
The core problem-solving loop. Maximum 15 minutes per issue.
**IDS: Identify, Discuss, Solve**
- **Identify:** What is the actual issue? (Not the symptom — the root cause) State it in one sentence.
- **Discuss:** Relevant facts + perspectives. Time-boxed. When discussion starts repeating, stop.
- **Solve:** One owner. One action. One due date. Written on the to-do list.
**Anti-patterns:**
- "Let's take this offline" — most things taken offline never get resolved
- Discussing without deciding — a great discussion with no action item is wasted time
- Revisiting decided issues — once solved, it leaves the list. Reopen only with new information.
**The Issues List:** A running, prioritized list of all unresolved issues. Owned by the leadership team. Reviewed and pruned weekly. If an issue has been on the list for 3+ meetings and hasn't been discussed, it's either not a real issue or it's too scary to address — both deserve attention.
### 5. Rocks (90-Day Priorities)
Rocks are the 3–7 most important things each person must accomplish in the next 90 days. They're not the job description — they're the things that move the company forward.
**Why 90 days?** Long enough for meaningful progress. Short enough to stay real.
**Rock rules:**
- Each person: 3–7 rocks maximum. More than 7 and none get done.
- Company-level rocks (shared priorities): 3–7 for the leadership team
- Each rock is binary: done or not done. No "60% complete."
- Set at the quarterly planning session. Reviewed weekly (on/off track).
**Bad rock:** "Improve our sales process"
**Good rock:** "Implement Salesforce CRM with full pipeline stages and weekly reporting by March 31"
**Rock vs. to-do:** A to-do takes one action. A rock takes 90 days of consistent work.
### 6. Communication Cadence
Who gets what information, when, and how.
| Audience | What | When | Format |
|----------|------|------|--------|
| All employees | Company update | Monthly | Written + Q&A |
| All employees | Quarterly results + next priorities | Quarterly | All-hands |
| Leadership team | Scorecard | Weekly | Dashboard |
| Board | Company performance | Monthly | Board memo |
| Investors | Key metrics + narrative | Monthly or quarterly | Investor update |
| Customers | Product updates | Per release | Release notes |
**Default rule:** If you're deciding whether to share something internally, share it. The cost of under-communication always exceeds the cost of over-communication inside a company.
---
## Operating System Selection
See `references/os-comparison.md` for full comparison. Quick guide:
| If you are... | Consider... |
|---------------|-------------|
| 10–250 person company, founder-led, operational chaos | EOS / Traction |
| Ambitious growth company, need rigorous strategy cascade | Scaling Up |
| Tech company, engineering culture, hypothesis-driven | OKR-native |
| Decentralized, flat, high autonomy | Holacracy (only if you're patient) |
| None of the above quite fit | Custom hybrid |
---
## Implementation Roadmap
Don't implement everything at once. See `references/implementation-guide.md` for the full 90-day plan.
**Quick start (first 30 days):**
1. Build the accountability chart (1 workshop, 2 hours)
2. Define 5–10 weekly scorecard metrics (leadership team alignment, 1 hour)
3. Start the weekly L10 meeting (no prep — just start)
These three alone will improve coordination more than most companies achieve in a year.
---
## Common Failure Modes
**Partial implementation:** "We do OKRs but skip the weekly check-in." Half an operating system is worse than none — it creates theater without accountability.
**Meeting fatigue:** Adding the full rhythm on top of existing meetings. Start by replacing meetings, not adding them.
**Metric overload:** Starting with 30 KPIs because "they all matter." Start with 5. Add when the cadence is established.
**Rock inflation:** Setting 12 rocks per person because "everything is a priority." When everything is a priority, nothing is. Hard limit: 7.
**Leader non-compliance:** Leadership team skips the L10 or doesn't follow IDS. The operating system mirrors the respect leadership gives it. If leaders don't take it seriously, nobody will.
**Annual planning without quarterly review:** Setting annual goals and checking in at year-end. Quarterly is the minimum review cycle for any meaningful goal.
---
## Integration with C-Suite
The company OS is the connective tissue. Every other role depends on it:
| C-Suite Role | OS Dependency |
|-------------|---------------|
| CEO | Sets vision that feeds into 1-year plan and rocks |
| COO | Owns the meeting pulse and issue resolution cadence |
| CFO | Owns the financial metrics in the scorecard |
| CTO | Owns engineering rocks and tech scorecard metrics |
| CHRO | Owns people metrics (attrition, hiring velocity) in scorecard |
| Culture Architect | Culture rituals plug into the meeting pulse |
| Strategic Alignment Engine | Validates that team rocks cascade from company rocks |
---
## Key Questions for the Operating System
- "If I asked five different team leads what the company's top 3 priorities are this quarter, would they give the same answers?"
- "What was the most important issue raised in last week's leadership meeting? Was it resolved or is it still open?"
- "Name a metric that would tell us by Friday whether this week was a good week. Do we track it?"
- "Who owns customer churn? Can you name that person without hesitation?"
- "When was the last time we updated the accountability chart?"
## Detailed References
- `references/os-comparison.md` — EOS vs Scaling Up vs OKRs vs Holacracy vs hybrid
- `references/implementation-guide.md` — 90-day implementation plan
FILE:references/implementation-guide.md
# Company Operating System — 90-Day Implementation Guide
Don't implement everything at once. The fastest path to failure is trying to launch the full operating system in week one. Build incrementally. Let the team experience wins before adding complexity.
---
## Before You Start
### Prerequisites
**Leadership alignment (non-negotiable):**
Every member of the leadership team must understand why you're doing this and commit to running the system. One holdout destroys the whole model. If the CFO skips the L10 meetings, the system won't work.
**Current state audit:**
- What meetings currently exist? Which can be replaced?
- Who owns which functions today? (Even informally)
- What metrics are being tracked? (Even inconsistently)
**Assign an OS owner:**
One person is responsible for the implementation and ongoing maintenance of the operating system. Usually the COO or CEO (at smaller companies). This is not a committee job.
---
## Week 1–2: Accountability Chart + Scorecard
### Accountability Chart Workshop (Week 1)
**Duration:** 2–3 hours, full leadership team
**Step 1 — List all functions (30 min)**
On a whiteboard, list every function the company performs:
- Sales (inbound, outbound, partnerships)
- Marketing (content, paid, brand)
- Product (roadmap, design, research)
- Engineering (frontend, backend, devops)
- Customer success (onboarding, support, retention)
- Finance (accounting, FP&A, legal)
- People (recruiting, HR, culture)
- Operations (processes, tools, facilities)
**Step 2 — Assign owners (45 min)**
For each function: "Who is the one person ultimately accountable?" Write their name.
Rules: One name only. No joint ownership. One person can own multiple functions at small scale.
**Step 3 — Identify gaps and overlaps (30 min)**
- **Gaps:** Functions with no owner → Who should own them? Or do we need a hire?
- **Overlaps:** Two people said they own the same thing → Resolve now, not later.
**Step 4 — Publish and socialize (Week 2)**
Share with the full company. Explain what an accountability chart is and isn't.
"This is about clarity, not hierarchy. It tells everyone who to go to for each function."
**Output:** A documented accountability chart. Use a simple tool (Miro, Google Slides, Ninety.io).
---
### Scorecard Design (Week 2)
**Duration:** 90 minutes, leadership team
**Step 1 — List candidate metrics (30 min)**
Each leader lists 3–5 metrics they already track or wish they tracked. No filtering yet.
**Step 2 — Filter to 5–15 (30 min)**
Criteria: Is it measurable weekly? Does it tell us if the company is healthy? Does one person own it?
Drop: metrics that are monthly only, metrics without a clear owner, metrics that measure activity not outcomes.
**Step 3 — Set weekly targets (20 min)**
For each metric: what's the weekly target? Not a range — a number. Red/yellow/green thresholds.
**Step 4 — Assign owners (10 min)**
Every metric has one owner who is responsible for reporting it weekly.
**Output:** A scorecard document. 5–15 metrics, owner, target, weekly tracking column.
**First scorecard run:** Week 2 or 3. It won't be perfect. That's fine.
---
## Week 3–4: Meeting Pulse (Start With L10)
Don't start all the meetings at once. Start with the weekly L10. Replace existing leadership syncs.
### L10 Meeting Setup
**Schedule:** Same day, same time, every week. Non-negotiable attendance.
**Duration:** 90 minutes. No more, no less.
**Facilitator:** Rotate or assign to COO/CEO. The facilitator keeps time and follows the agenda.
**Fixed agenda:**
1. **Good news** (5 min) — One personal, one business from each person. No skipping.
2. **Scorecard review** (5 min) — Traffic light only. Red items go to the issues list.
3. **Rock review** (5 min) — Each person: "on track" or "off track." No justification needed at this step.
4. **Customer/employee headlines** (5 min) — One sentence each. No reports.
5. **Issues** (60 min) — IDS process. Prioritize the top 3–5 issues. Solve them.
6. **To-do review** (5 min) — Review last week's commitments (done/not done). No excuses, just data.
7. **Conclude** (5 min) — Rate the meeting 1–10. What would make next week better?
**First L10 meeting:**
It will feel awkward. Run through the agenda anyway. The team needs the repetition to internalize it. By week 4, it should feel natural.
### Issues List Setup
Create a shared document (Notion, Google Docs, or dedicated tool):
- Issue title
- Priority (High / Medium / Low)
- Status (Open / In progress / Solved)
- Owner (once assigned)
- Due date
At the first L10, generate the issues list by asking: "What's getting in our way right now?" Expect 10–20 items on the first pass.
---
## Week 5–8: Rocks and Quarterly Planning
### Quarterly Planning Session (end of Week 5 or start of Week 6)
**Duration:** 4–8 hours (or 2 × 4-hour days for larger teams)
**Who:** Full leadership team
**Session structure:**
**Part 1: Review previous quarter (60–90 min)**
- What rocks were completed? What were dropped?
- What did we learn?
- What changed in the market or company?
**Part 2: Confirm or update company direction (60 min)**
- Is the 1-year goal still valid?
- Any major strategy shifts needed?
- Update the V/TO or OPSP if using EOS or Scaling Up.
**Part 3: Set company rocks (90 min)**
- Brainstorm: What are the 3–7 most important things to accomplish this quarter?
- Prioritize. Be ruthless. 3 rocks done > 7 rocks started.
- Each rock: clear owner, clear definition of done, 90-day timeline.
**Part 4: Set individual rocks (60 min)**
- Each leader sets their 3–7 rocks (aligned with company rocks where possible)
- Share with group: dependencies? Conflicts? Overloaded people?
**Part 5: Communicate (Week 6)**
- Share company rocks with the full organization within 1 week
- Each team sets their own rocks, cascaded from company rocks (3–5 per team)
**Rock template:**
```
Rock: [What you'll accomplish]
Owner: [One person]
Due date: [Specific date within the quarter]
Definition of done: [How we'll know it's complete]
Dependencies: [What else needs to happen first]
```
---
## Week 9–12: Issue Resolution Mastery + Communication Cadence
By now the L10 should be running smoothly. Weeks 9–12 focus on deepening IDS skills and establishing the broader communication cadence.
### IDS Practice
The issue resolution process often degrades in weeks 5–8. Common problems:
- Issues discussed but never solved (no clear action item)
- Same issues recurring (root cause not addressed)
- Too many issues, not enough resolution (prioritization failing)
**IDS calibration exercise (Week 9):**
In the next L10, after each issue is "solved," ask:
- "Is this actually solved, or are we postponing it?"
- "What's the specific action? Who owns it? When is it due?"
- "Is this the real issue, or a symptom of something deeper?"
### Communication Cadence Setup
Build out the full communication calendar:
| Communication | Frequency | Owner | Format | Tool |
|---------------|-----------|-------|--------|------|
| Company all-hands | Monthly | CEO | Update + Q&A | Video call |
| Quarterly planning results | Quarterly | CEO/COO | Written + live | Notion + all-hands |
| Board update | Monthly | CEO + CFO | Board memo | Doc |
| Investor update | Monthly | CEO + CFO | Email | Template |
| Department L10s | Weekly | Dept lead | L10 format | In-person / Zoom |
| Daily standups | Daily | Team leads | 15 min | Team call |
**Company all-hands template:**
1. State of the company (financial health, key metrics) — 10 min
2. Quarterly rocks: what we committed to, where we stand — 10 min
3. Wins and recognitions — 5 min
4. What's coming next quarter — 10 min
5. Q&A — 15–25 min
---
## Post-90 Days: Refinement and Optimization
### Month 4 retrospective
After the first full quarter, run a retrospective on the operating system itself:
- What's working? What isn't?
- Which meetings should continue as-is? Which need adjustment?
- Is the scorecard measuring the right things?
- Are rocks the right size and specificity?
- What should we add next?
### Scorecard evolution
By month 4, you'll know which metrics matter most. Add 2–3 that are missing. Remove metrics that nobody uses for decisions.
### L10 health check
Rate your L10 meetings over the first quarter:
- Average rating < 7: The agenda isn't being followed or issues aren't being resolved. Diagnose.
- Average rating 7–8: Normal. Keep building discipline.
- Average rating > 8: The team is engaged. Start extending the system to department level.
### Department L10s (Month 4+)
Once leadership L10 is running well, cascade the meeting structure:
- Each department runs their own weekly L10
- Department rocks cascade from company rocks
- Issues that cross departments are escalated to leadership L10
### Year 1 annual planning
End of year 1: run a full-day annual planning session.
- Review the year: what did we accomplish? What did we miss? What did we learn?
- Update 3-year vision (has it changed?)
- Set next year's annual goals
- Set Q1 rocks
- Celebrate. Seriously — mark the milestone.
---
## Implementation Anti-Patterns
**Skipping the accountability chart:** Without ownership clarity, every other system breaks down. Do this first.
**Building a perfect scorecard before starting:** Start with 5 imperfect metrics. Improve over time.
**Not replacing existing meetings:** Adding L10 on top of 3 existing meetings creates meeting overload. Cancel the redundant ones.
**Leader non-participation:** If one leader consistently skips or is disengaged, the system won't work. Address this directly — it's a culture issue, not a calendar issue.
**Changing the L10 agenda:** The agenda works because of repetition. Resist the urge to customize it for the first 6 months.
**Rocks without accountability:** If nobody checks rocks at the L10 ("on track / off track"), they become wish lists. The weekly review is what makes them real.
FILE:references/os-comparison.md
# Operating System Comparison
Side-by-side analysis of the major company operating frameworks.
---
## Overview
| Framework | Origin | Best fit | Implementation time | Cost |
|-----------|--------|----------|---------------------|------|
| EOS | Gino Wickman, 2007 | 10–250 employees, founder-led | 2–3 years full adoption | Free (DIY) to $25K+/year (implementer) |
| Scaling Up | Verne Harnish, 2002 | Growth-stage, strategic focus | 1–2 years | Free (DIY) to $15K+/year (coach) |
| OKR-native | Andy Grove / Google | Tech companies, product orgs | 3–6 months | Free |
| Holacracy | Brian Robertson, 2007 | Flat, autonomous organizations | 2–4 years | $5K–$50K+ (certification) |
| Custom hybrid | You | When the above don't fit exactly | Ongoing | Whatever you invest |
---
## 1. EOS — Entrepreneurial Operating System
**Book:** *Traction* by Gino Wickman
### Core principles
EOS is built on Six Components:
1. **Vision** — Where are you going? (V/TO: Vision/Traction Organizer)
2. **People** — Right people, right seats
3. **Data** — Scorecard with weekly metrics
4. **Issues** — Surface and resolve with IDS
5. **Process** — Document core processes
6. **Traction** — Rocks + meeting pulse (L10)
### Signature tools
- **V/TO (Vision/Traction Organizer):** 2-page strategy doc. Core values, core focus, 10-year target, 3-year picture, 1-year plan, quarterly rocks, issues.
- **Accountability Chart:** Who owns what function (not org chart)
- **L10 meeting:** Weekly 90-minute leadership sync (Level 10 = aim for 10/10)
- **Rocks:** 90-day priority commitments (3–7 per person)
- **IDS:** Identify, Discuss, Solve (issue resolution, max 15 min per issue)
### Strengths
- **Operationally focused.** If your problem is execution chaos, EOS addresses it directly.
- **Accessible.** The book is practical. You can DIY it without a coach.
- **Community.** Large network of implementers, tools (Ninety.io, EOS Worldwide), and practitioners.
- **Simple enough to actually use.** No complex methodology. Most teams are functional within 6 months.
### Limitations
- **Strategic depth is shallow.** The V/TO is good for direction but doesn't replace real strategy work.
- **Doesn't scale beyond ~250.** Designed for entrepreneurial companies. Gets cumbersome at enterprise scale.
- **Assumes a cohesive leadership team.** If trust is broken at the top, EOS won't fix it.
- **Facilitator dependency.** Many companies benefit from an EOS Implementer (external coach), which adds cost.
### Best fit
- 10–150 person companies
- Founder-led, operational dysfunction
- Teams that can't stay on the same page
- Companies with recurring issues that never get resolved
- First real "operating system" for a company that's been running on vibes
### Not ideal if
- You need sophisticated strategic planning
- You're > 250 people and already have ops infrastructure
- Your team resists structured methodology
---
## 2. Scaling Up (Rockefeller Habits 2.0)
**Book:** *Scaling Up* by Verne Harnish
### Core principles
Built on four Decisions:
1. **People** — Core values, talent management, Topgrading
2. **Strategy** — One-Page Strategic Plan (OPSP), 7 Strata of Strategy
3. **Execution** — Priorities (rocks), meeting rhythm, critical numbers
4. **Cash** — Power of One, Cash Acceleration Strategies (CAS)
### Signature tools
- **One-Page Strategic Plan (OPSP):** Annual and quarterly goals on one page. More strategic than EOS's V/TO.
- **7 Strata of Strategy:** Competitive positioning, core customer, brand promise, X-factor (10x advantage), profit per X, BHAG, critical numbers.
- **Meeting rhythm:** Daily (5–15 min), weekly, monthly, quarterly, annual — with specific templates.
- **Critical number:** One metric that, if improved, fixes everything else.
- **Cash acceleration:** CAS system for improving working capital and cash conversion cycle.
### Strengths
- **Stronger strategic framework than EOS.** The 7 strata and OPSP force real strategic thinking.
- **Cash focus.** Unique among frameworks — explicitly addresses cash flow management.
- **Scales further.** Better suited for 100–1000 person companies than EOS.
- **Works for ambitious growth companies.** Designed for companies that want to scale significantly.
### Limitations
- **More complex than EOS.** Harder to DIY. Benefits heavily from a certified Scaling Up coach.
- **Overwhelming at first.** The full framework has many components. Teams often implement partially.
- **Less prescriptive on meetings.** EOS's L10 is very specific. Scaling Up's meeting rhythm requires more customization.
### Best fit
- Series A to Series C companies
- Companies with strong growth ambition
- Leadership teams that want strategic rigor, not just operational clarity
- Companies already past initial chaos, ready for more sophisticated frameworks
### Not ideal if
- You're pre-product-market-fit
- You need quick operational wins
- Your team doesn't have the bandwidth for the learning curve
---
## 3. OKR-Native (Google Style)
**Books:** *Measure What Matters* by John Doerr; *Radical Focus* by Christina Wodtke
### Core principles
OKRs = Objectives + Key Results
- **Objectives:** Qualitative, inspiring direction. "What are we trying to achieve?"
- **Key Results:** Quantitative, measurable outcomes. "How will we know we achieved it?"
- **Not tasks.** KRs measure outcomes, not activities.
**Cascade:** Company OKRs → Department OKRs → Team OKRs → Individual OKRs
**Cadence:** Quarterly OKR cycles. Weekly check-ins. Annual reflection.
**Scoring:** 0.0–1.0. Target is 0.7. Consistently hitting 1.0 = OKRs aren't ambitious enough.
### Strengths
- **Aligns the whole company.** When done well, every team can trace their work to company-level objectives.
- **Encourages ambition.** Moonshot OKRs are explicit. "Roofshot" vs "moonshot" OKRs.
- **Widely understood in tech.** Many hires will already know OKRs.
- **No framework cost.** No implementer required. Tooling is free or cheap (Linear, Notion, Lattice).
### Limitations
- **Hard to do well.** Most companies run "OKR theater" — tasks dressed up as key results.
- **Missing the HOW.** OKRs define what to achieve but not how to operate. You still need meeting rhythm, accountability structure, and issue resolution.
- **Misalignment risk.** If not cascaded properly, teams run disconnected OKRs that feel like alignment but aren't.
- **No operational backbone.** OKRs are a goal-setting system, not a full operating system.
### Best fit
- Tech companies with strong product/engineering culture
- Companies where hypothesis-driven work is already the norm
- Organizations that value autonomy and bottom-up goal setting
- As the goal-setting layer inside a broader operating system
### Not ideal if
- Teams lack discipline to hold each other accountable
- You need more than just goal alignment (issue resolution, meeting structure)
- Leaders don't model OKR behavior themselves
---
## 4. Holacracy
**Book:** *Holacracy* by Brian Robertson
### Core principles
Holacracy replaces the traditional management hierarchy with a system of distributed authority.
- **Circles:** Semi-autonomous units with defined purposes (like teams, but self-governing)
- **Roles:** People fill roles (not job descriptions). One person can hold multiple roles in different circles.
- **Governance meetings:** Roles and accountabilities are defined and evolved by the circle, not management
- **Tactical meetings:** Operational coordination within circles
- **The Constitution:** A legal document that all members ratify, replacing traditional management authority
### Strengths
- **Maximum autonomy.** People closest to the work define how it gets done.
- **Removes management as a bottleneck.** Decisions happen at the circle level.
- **Adapts to complexity.** Circle structure evolves organically as the work changes.
### Limitations
- **Enormous learning curve.** 2–4 years to full adoption. Many companies abandon it.
- **High meeting overhead.** Governance meetings add significant time.
- **Doesn't eliminate politics.** Just moves them to governance meetings.
- **Requires full commitment.** Partial Holacracy doesn't work. You either do it or you don't.
- **Not for crisis mode.** When speed matters, distributed governance slows you down.
### When it works
- Organizations with deep belief in autonomy and self-management
- Non-profit or mission-driven organizations where consensus matters
- Companies with patient leadership willing to invest years in implementation
### When it doesn't work
- Startups needing speed and clarity
- Companies with strong founder personalities who struggle to relinquish control
- Organizations that need to move fast or course-correct frequently
---
## 5. Custom Hybrid
### When to build a hybrid
None of the above frameworks fits perfectly because:
- EOS lacks strategic depth
- Scaling Up is complex to implement
- OKRs don't provide operational backbone
- Holacracy is too slow to implement
The solution: take the best components of each.
### Common hybrid patterns
**EOS backbone + OKR goal-setting:**
- EOS provides: accountability chart, L10 meeting, IDS, meeting pulse
- OKRs provide: goal-setting with ambition, cascade, and alignment checks
- Works well for: tech companies that want operational rigor with flexibility
**Scaling Up strategy + EOS execution:**
- Scaling Up provides: OPSP, 7 strata, cash management
- EOS provides: L10, rocks, IDS
- Works well for: ambitious growth companies that want both strategy and execution discipline
**OKRs + custom meeting rhythm:**
- OKRs provide: goal cascade
- Custom meetings: weekly team syncs, monthly department reviews, quarterly all-hands
- Works well for: companies that already have strong culture but need goal alignment
### Hybrid design principles
1. **Pick one goal-setting system.** Don't mix OKRs and Rocks — they're both 90-day priority systems and will create confusion.
2. **Be explicit about what you're taking from where.** "We use EOS for meetings and Scaling Up for strategy" is a clear hybrid. "We do a bit of everything" is chaos.
3. **Document your version.** Your operating system should have a name and a one-page description of what it includes.
4. **Evolve intentionally.** Change one component at a time. Don't overhaul the whole system when one part isn't working.
---
## Framework Selection Decision Tree
```
Is your company < 50 people and in operational chaos?
YES → Start with EOS. It's the simplest path to order.
NO → Continue.
Does strategic positioning and cash flow need significant work?
YES → Consider Scaling Up.
NO → Continue.
Is your company tech-native with strong product/engineering culture?
YES → OKR-native with a custom meeting rhythm.
NO → Continue.
Do you have 2+ years and full leadership commitment to radical organizational change?
YES → Consider Holacracy (with caution).
NO → Build a custom hybrid from EOS + OKRs.
```
Theo dõi đối thủ có hệ thống, phục vụ định vị marketing, battlecard bán hàng và quyết định lộ trình sản phẩm.
---
name: "competitive-intel"
description: "Systematic competitor tracking that feeds CMO positioning, CRO battlecards, and CPO roadmap decisions. Use when analyzing competitors, building sales battlecards, tracking market moves, positioning against alternatives, or when user mentions competitive intelligence, competitive analysis, competitor research, battlecards, win/loss, or market positioning."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: competitive-strategy
updated: 2026-03-05
frameworks: ci-playbook, battlecard-template
---
# Competitive Intelligence
Systematic competitor tracking. Not obsession — intelligence that drives real decisions.
## Keywords
competitive intelligence, competitor analysis, battlecard, win/loss analysis, competitive positioning, competitive tracking, market intelligence, competitor research, SWOT, competitive map, feature gap analysis, competitive strategy
## Quick Start
```
/ci:landscape — Map your competitive space (direct, indirect, future)
/ci:battlecard [name] — Build a sales battlecard for a specific competitor
/ci:winloss — Analyze recent wins and losses by reason
/ci:update [name] — Track what a competitor did recently
/ci:map — Build competitive positioning map
```
## Framework: 5-Layer Intelligence System
### Layer 1: Competitor Identification
**Direct competitors:** Same ICP, same problem, comparable solution, similar price point.
**Indirect competitors:** Same budget, different solution (including "do nothing" and "build in-house").
**Future competitors:** Well-funded startups in adjacent space; large incumbents with stated roadmap overlap.
**The 2x2 Threat Matrix:**
| | Same ICP | Different ICP |
|---|---|---|
| **Same problem** | Direct threat | Adjacent (watch) |
| **Different problem** | Displacement risk | Ignore for now |
Update this quarterly. Who's moved quadrants?
### Layer 2: Tracking Dimensions
Track these 8 dimensions per competitor:
| Dimension | Sources | Cadence |
|-----------|---------|---------|
| **Product moves** | Changelog, G2/Capterra reviews, Twitter/LinkedIn | Monthly |
| **Pricing changes** | Pricing page, sales call intel, customer feedback | Triggered |
| **Funding** | Crunchbase, TechCrunch, LinkedIn | Triggered |
| **Hiring signals** | LinkedIn job postings, Indeed | Monthly |
| **Partnerships** | Press releases, co-marketing | Triggered |
| **Customer wins** | Case studies, review sites, LinkedIn | Monthly |
| **Customer losses** | Win/loss interviews, churned accounts | Ongoing |
| **Messaging shifts** | Homepage, ads (Facebook/Google Ad Library) | Quarterly |
### Layer 3: Analysis Frameworks
**SWOT per Competitor:**
- Strengths: What do they do well? Where do they win?
- Weaknesses: Where do they lose? What do customers complain about?
- Opportunities: What could they do that would threaten you?
- Threats: What's their existential risk?
**Competitive Positioning Map (2 axis):**
Choose axes that matter for your buyers:
- Common: Price vs Feature Depth; Enterprise-ready vs SMB-ready; Easy to implement vs Configurable
- Pick axes that show YOUR differentiation clearly
**Feature Gap Analysis:**
| Feature | You | Competitor A | Competitor B | Gap status |
|---------|-----|-------------|-------------|------------|
| [Feature] | ✅ | ✅ | ❌ | Your advantage |
| [Feature] | ❌ | ✅ | ✅ | Gap — roadmap? |
| [Feature] | ✅ | ❌ | ❌ | Moat |
| [Feature] | ❌ | ❌ | ✅ | Competitor B only |
### Layer 4: Output Formats
**For Sales (CRO):** Battlecards — one page per competitor, designed for pre-call prep.
See `templates/battlecard-template.md`
**For Marketing (CMO):** Positioning update — message shifts, new differentiators, claims to stop or start making.
**For Product (CPO):** Feature gap summary — what customers ask for that we don't have, what competitors ship, what to reprioritize.
**For CEO/Board:** Monthly competitive summary — 1-page: who moved, what it means, recommended responses.
### Layer 5: Intelligence Cadence
**Monthly (scheduled):**
- Review all tier-1 competitors (direct threats, top 3)
- Update battlecards with new intel
- Publish 1-page summary to leadership
**Triggered (event-based):**
- Competitor raises funding → assess implications within 48 hours
- Competitor launches major feature → product + sales response within 1 week
- Competitor poaches key customer → win/loss interview within 2 weeks
- Competitor changes pricing → analyze and respond within 1 week
**Quarterly:**
- Full competitive landscape review
- Update positioning map
- Refresh ICP competitive threat assessment
- Add/remove companies from tracking list
---
## Win/Loss Analysis
This is the highest-signal competitive data you have. Most companies do it too rarely.
**When to interview:**
- Every lost deal >$50K ACV
- Every churn >6 months tenure
- Every competitive win (learn why — it may not be what you think)
**Who conducts it:**
- NOT the AE who worked the deal (too close, prospect won't be candid)
- Customer success, product team, or external researcher
**Question structure:**
1. "Walk me through your evaluation process"
2. "Who else were you considering?"
3. "What were the top 3 criteria in your decision?"
4. "Where did [our product] fall short?"
5. "What was the deciding factor?"
6. "What would have changed your decision?"
**Aggregate findings monthly:**
- Win reasons (rank by frequency)
- Loss reasons (rank by frequency)
- Competitor win rates (by competitor, by segment)
- Patterns over time
---
## The Balance: Intelligence Without Obsession
**Signs you're over-tracking competitors:**
- Roadmap decisions are primarily driven by "they just shipped X"
- Team morale drops when competitors fundraise
- You're shipping features you don't believe in to match their checklist
- Pricing discussions always start with "well, they charge X"
**Signs you're under-tracking:**
- Your AEs get blindsided on calls
- Prospects know more about competitors than your team does
- You missed a major product launch until customers told you
- Your positioning hasn't changed in 12+ months despite market moves
**The right posture:**
- Know competitors well enough to win against them
- Don't let them set your agenda
- Your roadmap is led by customer problems, informed by competitive gaps
---
## Distributing Intelligence
| Audience | Format | Cadence | Owner |
|----------|--------|---------|-------|
| AEs + SDRs | Updated battlecards in CRM | Monthly + triggered | CRO |
| Product | Feature gap analysis | Quarterly | CPO |
| Marketing | Positioning brief | Quarterly | CMO |
| Leadership | 1-page competitive summary | Monthly | CEO/COO |
| Board | Competitive landscape slide | Quarterly | CEO |
**One source of truth:** All competitive intel lives in one place (Notion, Confluence, Salesforce). Avoid Slack-only distribution — it disappears.
---
## Red Flags in Competitive Intelligence
| Signal | What it means |
|--------|---------------|
| Competitor's win rate >50% in your core segment | Fundamental positioning problem, not sales problem |
| Same objection from 5+ deals: "competitor has X" | Feature gap that's real, not just optics |
| Competitor hired 10 engineers in your domain | Major product investment incoming |
| Competitor raised >$20M and targets your ICP | 12-month runway for them to compete hard |
| Prospects evaluate you to justify competitor decision | You're the "check box" — fix perception or segment |
## Integration with C-Suite Roles
| Intelligence Type | Feeds To | Output Format |
|------------------|----------|---------------|
| Product moves | CPO | Roadmap input, feature gap analysis |
| Pricing changes | CRO, CFO | Pricing response recommendations |
| Funding rounds | CEO, CFO | Strategic positioning update |
| Hiring signals | CHRO, CTO | Talent market intelligence |
| Customer wins/losses | CRO, CMO | Battlecard updates, positioning shifts |
| Marketing campaigns | CMO | Counter-positioning, channel intelligence |
## References
- `references/ci-playbook.md` — OSINT sources, win/loss framework, positioning map construction
- `templates/battlecard-template.md` — sales battlecard template
FILE:references/ci-playbook.md
# Competitive Intelligence Playbook
## OSINT Sources for Competitor Tracking
### Free, Reliable Sources
**Company & Product:**
- **Their website** — pricing page (archive.org for history), product changelog, careers page
- **G2 / Capterra / Trustpilot** — customer reviews; filter by recency; read 1-star reviews carefully
- **LinkedIn** — job postings signal roadmap; company page for headcount trend; employees for leaks
- **GitHub** — open source activity; what they're building; engineering team size; tech stack
- **Crunchbase / PitchBook** (free tier) — funding history, investors, team changes
- **BuiltWith** — tech stack they use; signals about infrastructure maturity
**Messaging & Positioning:**
- **Facebook Ad Library** — see their current ad copy and creative; what messages they're testing
- **Google Keyword Planner** — which keywords they're bidding on
- **SEMrush / Ahrefs** (free trial or limited) — their organic keywords, backlink profile
- **Wayback Machine** — homepage evolution over time; when positioning shifted
- **Their blog** — content strategy reveals priorities and ICP assumptions
**News & Events:**
- **TechCrunch, VentureBeat** — funding announcements, major launches
- **Twitter/X / LinkedIn** — CEO + founders; direct signals about strategy
- **Podcast appearances** — founders talk more openly on podcasts than press releases
- **Job descriptions** — "Senior Engineer - Payments" means they're building payments
### Paid (Worth It for Tier-1 Competitors)
- **G2 Buyer Intent** — which prospects are researching your competitor right now
- **Bombora** — intent data for account-level research signals
- **PitchBook** — funding, investors, valuation estimates
- **Klue / Crayon / Kompyte** — dedicated CI platforms that aggregate automatically
### Primary Research (Best Signal)
- **Win/loss interviews** — the single highest-signal source (see below)
- **Talk to churned customers** — why did they switch? To whom?
- **Talk to their customers** — LinkedIn outreach; honest conversations
- **Industry events** — competitor presentations reveal roadmap; talk to attendees
- **Former employees** — LinkedIn; respectful outreach; no NDA violations
---
## Competitive Battlecard Format
A battlecard is a 1-page (or single screen) document for sales reps to reference before and during calls.
**Design principles:**
- Written for a rep with 2 minutes to prep, not a product manager
- Action-oriented: tells reps what to SAY, not just what to know
- Updated monthly at minimum; never more than 90 days old
### Battlecard Structure
```
COMPETITOR: [Name]
Last updated: [Date] | Owner: [Name]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
THE 30-SECOND SUMMARY
[One paragraph. Who they are, who they sell to, why they win.]
THEIR STRENGTHS (know these — don't dismiss them)
• [Strength 1] — what customers actually love about them
• [Strength 2]
• [Strength 3]
THEIR REAL WEAKNESSES (from win/loss data, not assumptions)
• [Weakness 1] — source: [customer quote / win/loss theme]
• [Weakness 2]
• [Weakness 3]
OUR DIFFERENTIATED ADVANTAGES
• [Advantage 1] — proof point: [metric/customer/case study]
• [Advantage 2] — proof point:
• [Advantage 3] — proof point:
COMMON OBJECTIONS + RESPONSES
"They have [feature] and you don't."
→ [Response. Acknowledge, reframe, redirect.]
"They're cheaper."
→ [Response with ROI angle or TCO comparison.]
"They're more established / bigger."
→ [Response. Size isn't always advantage; use to your benefit.]
TRAP-SETTING QUESTIONS (ask these early to shift the eval criteria)
• "How important is [your differentiator] to your team?"
• "Have you looked at [pain point they create]?"
• "What happens to your workflow when [their known limitation occurs]?"
WHEN WE WIN
• [Segment or scenario where we almost always beat them]
• [Use case where we're clearly stronger]
WHEN WE LOSE (be honest)
• [Scenario where they're genuinely better — don't fight these battles]
• [Segment where they have structural advantages]
DO NOT SAY
• Don't claim [X] — it's not true and they'll call it out
• Don't say [Y] — prospect will already know it and it sounds desperate
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
---
## Win/Loss Analysis Framework
### Why Most Companies Do This Wrong
- They survey instead of interview (surveys get polite answers)
- The AE conducts it (too emotionally invested; prospect won't be candid)
- They do it 6 months after the decision (memory fades)
- They look for confirmation of what they believe
### The Right Process
**Timing:** Within 30 days of deal closed/lost/churned.
**Interviewer:** Customer success, product, or external researcher. Never the AE.
**Duration:** 30 minutes (budget 45).
**Incentive:** $100 gift card gets you 80% acceptance. Worth it.
**Interview Guide:**
*Opening:*
"I'm [name] from [company]. I'm not in sales — I'm trying to understand what drove your decision so we can improve. There's nothing you can say that will change the outcome. I just want honest feedback."
*Core questions:*
1. "Can you walk me through your evaluation process from the beginning?"
2. "Who were the key stakeholders involved in the decision?"
3. "What were the 3 most important criteria you were evaluating against?"
4. "Which vendors did you seriously consider?"
5. "Where did [company] fall short of your expectations?" (For losses)
OR "What tipped the decision in [company]'s favor?" (For wins)
6. "Was price a factor? How significant?"
7. "What would have had to be different for you to choose [us / the other option]?"
8. "Any advice for our team on how we handled the process?"
**Data aggregation:**
- Tag every response: [criterion], [competitor mentioned], [product gap], [sales process], [price], [trust/credibility]
- Monthly rollup: top 5 win reasons, top 5 loss reasons, competitor win rate
- Share with: CEO, CRO, CPO, CMO — not just sales
---
## Competitive Positioning Map Construction
A positioning map shows where you sit relative to competitors on 2 dimensions that BUYERS care about.
### Step 1: Choose Your Axes
- Pick dimensions that actually drive purchase decisions in your segment
- At least one axis should be where you win
- Avoid generic axes ("feature-rich vs. simple" tells you nothing)
**Good axis pairs:**
- Implementation time (days vs. months) × Customization depth
- Price point × Enterprise readiness
- Automation level × Human-in-the-loop control
- Time-to-value × Total cost of ownership
**Bad axes:**
- Quality (too vague)
- "Innovation" (unmeasurable)
- Any axis where all competitors cluster in the same spot
### Step 2: Place Competitors Objectively
- Use customer quotes and win/loss data to justify placement
- Don't place competitors where you WANT them — where they ACTUALLY are
- If you're unsure, ask 5 customers to place them
### Step 3: Find and Name Your White Space
- Where is there a position no competitor holds?
- Is that white space there because it's valuable (opportunity) or worthless (avoid)?
- Can you credibly occupy it?
### Step 4: Test Your Positioning
- Show the map to 5 prospects: "Does this match your perception?"
- Show it to 5 lost prospects: "Where would you place [the winner] and us?"
- Adjust until map matches buyer reality, not internal perception
---
## Intelligence Sharing Across Roles
### What Each Role Needs and When
**CRO (Sales):**
- Needs: Battlecards, win rates by competitor, competitor objections + responses
- Cadence: Updated battlecards monthly; triggered updates on major competitor moves
- Format: 1-pager per competitor in CRM, linked from deal record
**CMO (Marketing):**
- Needs: Messaging shifts, new claims, ad spend signals, keyword battles
- Cadence: Quarterly positioning review, triggered on major launches
- Format: Positioning brief with recommended response to messaging shifts
**CPO (Product):**
- Needs: Feature gap analysis, competitor roadmap signals (job postings, changelog), what we lose to
- Cadence: Monthly feature gap update, triggered on major launches
- Format: Feature comparison matrix + gap prioritization recommendation
**CTO (Engineering):**
- Needs: Tech stack signals, infrastructure approaches, scale they've achieved
- Cadence: Quarterly
- Format: Technical comparison notes, relevant for architectural decisions
**CEO:**
- Needs: Summary of threat landscape, recommended responses, board-level narrative
- Cadence: Monthly 1-pager + quarterly deep dive
- Format: 1-page brief: who moved, what it means, what we do
### The Single Source of Truth Rule
All competitive intel in one place. Suggest:
- Notion database per competitor: profile, battlecard, changelog, win/loss notes
- Slack channel: `#competitive-intel` for real-time triggered alerts
- Monthly digest email to leadership
If it lives only in Slack, it disappears. If it lives only in a wiki that nobody reads, it doesn't matter. Combine both.
---
## How to Track Without Obsessing
**Set up the system, then let it run:**
- Google Alerts for competitor names + CEO names
- LinkedIn Saved Searches for their job postings
- Klue/Crayon if budget allows (automated aggregation)
- Monthly 60-minute competitive review meeting (not 4 hours)
**What to do when competitor makes a big move:**
1. Read the announcement objectively
2. Talk to 3 customers: "Did you see this? What do you think?"
3. Assess: does this change any buying criteria in your deals?
4. If yes: update battlecard and positioning within 1 week
5. If no: log it, move on
**The test:** After reviewing a competitor move, do you feel urgency to ship something? If yes, you're reacting. The right feeling is "noted — let's see if customers care."
FILE:templates/battlecard-template.md
# Sales Battlecard Template
**COMPETITOR:** [Name]
**Last updated:** [YYYY-MM-DD] | **Owner:** [Name]
**Win rate vs this competitor:** [X]% | **Deals tracked:** [N]
---
## 30-Second Summary
[Who they are. Who they target. Why they win. What they're known for. 3-4 sentences max.]
---
## Their Strengths
*Know these. Don't dismiss them. Prospects have already heard their pitch.*
- **[Strength]:** [What customers genuinely love; source if available]
- **[Strength]:** [Specific capability or trait]
- **[Strength]:** [Brand, market position, or ecosystem advantage]
---
## Their Real Weaknesses
*From win/loss data only — not wishful thinking.*
- **[Weakness]:** "[Customer quote]" — seen in [N] deals
- **[Weakness]:** [Documented limitation with evidence]
- **[Weakness]:** [Implementation, support, or pricing issue]
---
## Our Differentiated Advantages
*Must be real and provable. Each needs a proof point.*
- **[Advantage]:** [Proof: metric / customer quote / case study]
- **[Advantage]:** [Proof]
- **[Advantage]:** [Proof]
---
## Common Objections + Responses
**"They have [feature X] and you don't."**
> [Acknowledge. Reframe to your strength. Redirect to outcome.
> "You're right that they have X. What we've found is that customers who care most about X tend to also care about [Y], where we're significantly stronger. Can I show you [specific example]?"]
**"They're cheaper."**
> [Don't fight on price. Reframe to TCO or ROI.
> "They are lower in initial cost. Most customers find the total cost over 12 months is actually comparable when you factor in [implementation time / support costs / integrations]. Want to walk through that?"]
**"They've been around longer / they're more established."**
> [Reframe tenure as potential liability or irrelevance.
> "Their longevity means they have a lot of technical debt and a big customer base that pulls their roadmap in every direction. Our customers tell us that's exactly why they chose us — we move faster and we're laser-focused on [their specific use case]."]
**"[Competitor] is already used by [big customer they respect]."**
> [Name-drop your wins in their segment.
> "We work with [comparable logo]. Want me to connect you with their [role] to ask how they made the decision?"]
---
## Trap-Setting Questions
*Ask early in discovery to establish criteria that favor you.*
- "How important is [your key differentiator] to your workflow?"
- "What happens when [their known limitation] occurs? Has that been an issue before?"
- "How long does your team typically take to onboard a new tool?"
- "Who manages the integration work — do you have dedicated engineering resources for that?"
- "What does your current vendor do when you need support?"
---
## When We Win
- [Scenario or segment where we consistently beat them]
- [Use case that plays to our strengths]
- [Buyer profile that prefers us]
## When We Lose (Be Honest)
- [Scenario where they genuinely win — don't fight here]
- [Segment where their strengths matter more than ours]
---
## Do NOT Say
- ❌ Don't claim [X] — it's not accurate and they'll check
- ❌ Don't attack [Y] — it backfires and makes us look insecure
- ❌ Don't say "we're better" without specifics — be concrete
---
## Recent Intel
*Last 90 days only. Older than 90 days: archive.*
- [Date]: [What happened — funding, product launch, pricing change, key hire]
- [Date]: [Customer feedback from win/loss interview]
- [Date]: [Any notable market move]
---
*Battlecards are only useful if current. If this is >90 days old, flag to [owner] for update.*
Xây ma trận phân tích cạnh tranh với chấm điểm và phân tích khoảng cách.
---
name: competitive-matrix
description: Build competitive analysis matrices with scoring and gap analysis. Usage: /competitive-matrix <analyze> [options]
---
# /competitive-matrix
Build competitive matrices with weighted scoring, gap analysis, and market positioning insights.
## Usage
```
/competitive-matrix analyze <competitors.json> Full analysis
/competitive-matrix analyze <competitors.json> --weights pricing=2,ux=1.5 Custom weights
```
## Input Format
```json
{
"your_product": { "name": "MyApp", "scores": {"ux": 8, "pricing": 7, "features": 9} },
"competitors": [
{ "name": "Competitor A", "scores": {"ux": 7, "pricing": 9, "features": 6} }
],
"dimensions": ["ux", "pricing", "features"]
}
```
## Examples
```
/competitive-matrix analyze competitors.json
/competitive-matrix analyze competitors.json --format json --output matrix.json
```
## Scripts
- `product-team/competitive-teardown/scripts/competitive_matrix_builder.py` — Matrix builder
## Skill Reference
→ `product-team/competitive-teardown/SKILL.md`
Cấu hình khung tuân thủ áp dụng, tính độ chồng lấn kiểm soát, mô phỏng kiểm toán nội bộ và hợp nhất bằng chứng.
---
name: "compliance-os"
description: "Compliance OS — meta-orchestrator that lets compliance teams CONFIGURE which frameworks apply, COMPUTE cross-framework control overlap, SIMULATE internal audits, and CONSOLIDATE evidence across multiple frameworks. Four decisions: (1) Given a company profile, which of the 12 supported frameworks apply (ISO 27001/13485/42001/14971, EU AI Act, MDR 745, GDPR, SOC 2, FDA QSR, NIST CSF 2.0, NIS2, HIPAA)? (2) Across selected frameworks, which controls overlap and how much evidence reuses? (3) For a given framework + scope, what does a realistic mock audit produce — drawing from the 205-scenario library? (4) Across selected frameworks, what's the unified evidence checklist with reuse map? Use when standing up a multi-framework program, planning the annual audit calendar, or preparing for certification stage 1. Does NOT replace per-framework skills (it orchestrates them)."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: compliance-os
domain: multi-framework-compliance-orchestration
updated: 2026-05-13
python-tools: framework_selector.py, cross_framework_mapper.py, audit_simulator.py, evidence_pool_generator.py
frameworks: iso-27001, iso-13485, iso-42001, iso-14971, eu-ai-act, eu-mdr-745, gdpr, soc-2, fda-qsr, nist-csf, nis2, hipaa
---
# Compliance OS — Meta-Orchestrator
Multi-framework compliance program orchestration. **Four decisions, no per-framework deep-dive:**
1. **Which frameworks apply to this company?** — `framework_selector.py` ranks the 12 supported frameworks against a company profile (industry, geography, AI use, medical, financial, headcount, customers, healthcare-PHI, NIS2 essential/important entity, US gov contractor) and returns applicable ones with dependency graph
2. **How much do selected frameworks overlap?** — `cross_framework_mapper.py` computes control-level overlap with confidence rating; outputs unified control matrix + evidence-reuse opportunities
3. **What does a mock audit produce?** — `audit_simulator.py` generates 8–15 finding scenarios with severity distribution matching IIA expectations + interview questions per control
4. **What's the unified evidence checklist?** — `evidence_pool_generator.py` consolidates evidence across enabled frameworks; outputs which artefact satisfies which controls across which frameworks
This skill is **NOT** a per-framework deep-dive. The per-framework skills (`ra-qm-team/skills/iso42001-specialist/`, `compliance-team-eu-ai-act/`, `ra-qm-team/skills/gdpr-dsgvo-expert/`, etc.) do the operational work. Compliance OS orchestrates them.
This skill is **NOT** a substitute for binding legal advice. Cross-framework mappings reflect published guidance (ISO standards, regulations, EDPB/Commission guidance, IIA / AICPA professional standards). Novel cross-walks should be reviewed with counsel.
## Keywords
compliance orchestration, multi-framework compliance, compliance OS, cross-framework mapping, control overlap, evidence pool, evidence reuse, audit simulation, mock audit, internal audit programme, GRC, governance risk compliance, framework selector, compliance program, integrated compliance, ISO 19011, IIA IPPF, AICPA AT-C, NIST CSF profile, multi-cert program, SOC 2 + ISO 27001, ISO 27001 + ISO 42001, ISO 13485 + MDR 745, AI Act + ISO 42001, GDPR + ISO 27001, compliance officer, compliance team workflow, certification readiness
## Quick Start
```bash
# Decision A: Which frameworks apply for the company?
python scripts/framework_selector.py # embedded mid-stage AI SaaS sample
python scripts/framework_selector.py path/to/profile.json
# Decision B: Compute cross-framework overlap
python scripts/cross_framework_mapper.py # embedded ISO 27001 + SOC 2 sample
python scripts/cross_framework_mapper.py path/to/control_libs.json
# Decision C: Simulate an audit
python scripts/audit_simulator.py # embedded ISO 27001 sample
python scripts/audit_simulator.py path/to/audit_scope.json
# Decision D: Consolidate evidence checklist across frameworks
python scripts/evidence_pool_generator.py # embedded 3-framework sample
python scripts/evidence_pool_generator.py path/to/program.json
```
## Key Questions (ask these first)
- **Have you named every applicable framework?** Forgetting one means rebuilding the audit program later. Run `framework_selector.py` with your profile.
- **What's the most certificate / regulation your company already operates?** That's your reuse anchor. Map every new framework against it.
- **What's the audit calendar?** A multi-framework program means surveillance audits stacked through the year — plan auditor independence + capacity.
- **Where is evidence stored?** Multi-framework programs collapse when evidence lives in one team's drive without an index. Run `evidence_pool_generator.py` to surface the reuse opportunities.
- **What's the management-review cadence across frameworks?** Each framework wants its own management review, but a single integrated review (per ISO Annex SL) typically satisfies all of them with one calendar slot.
- **Who owns the meta-program?** If no single accountable role, the program fragments.
## Core Responsibilities
### 1. Framework Selection
**The framework:** company-profile JSON in → applicable-framework list out with dependency graph.
**Deterministic logic:**
- Medical device → ISO 13485 + ISO 14971 + (EU MDR 745 if EU market) + (FDA QSR if US market)
- Customer-facing AI → ISO 42001 + EU AI Act (if EU users) + GDPR (if personal data)
- B2B SaaS with enterprise customers → SOC 2 + ISO 27001 (often required for procurement)
- EU customers + personal data → GDPR mandatory
- Highly regulated industry (financial, health) → additional sectoral overlays
**Run** `framework_selector.py` to apply the decision rules.
### 2. Cross-Framework Control Mapping
**The framework:** for each selected framework, parse its control library; compute overlap with other selected frameworks.
**Per merged-control output:**
- Mapping confidence (HIGH / MEDIUM / LOW)
- Evidence-reuse opportunity (single artefact satisfies N controls)
- Per-framework citation
- Implementation guidance reusable across frameworks
**Densest known overlap:** ISO 27001 Annex A ↔ SOC 2 Trust Services Criteria — historically ~75% control coverage shared. Adding ISO 42001 brings AI-specific controls; adding GDPR brings privacy-specific.
**Run** `cross_framework_mapper.py` with framework control libraries.
### 3. Audit Simulation
**The framework:** generate a realistic mock internal audit per ISO 19011 + IIA IPPF standards.
**Per audit output:**
- 8–15 finding scenarios per ISO 19011 typical depth
- Severity distribution: ≥ 40% observations/OFI, ≤ 15% critical/major (IIA expectation for healthy programs)
- Interview questions per scoped control (3–5 questions per control)
- Document-review request list
- Walk-through requests where applicable
**Run** `audit_simulator.py` with framework + scope.
### 4. Evidence Pool
**The framework:** consolidate evidence requirements across enabled frameworks; identify reuse opportunities.
**Output:**
- Evidence artefact list (e.g., access-review log, supplier risk register, incident log)
- Per artefact: list of (framework, control) tuples it satisfies
- Reuse-leverage score (artefact A satisfies N controls across M frameworks)
- Acquisition cost estimate (effort to produce + maintain)
**Run** `evidence_pool_generator.py` with program config.
## Workflows
### Workflow 1: Program Bootstrap (multi-framework, 4–8 weeks)
**Goal:** stand up a compliance program covering 2–4 frameworks simultaneously.
```bash
# 1. Run framework selector with company profile
python scripts/framework_selector.py profile.json
# 2. For each applicable framework, identify the per-framework skill and run its gap analysis
# 3. Run cross-framework mapper to identify reuse opportunities
python scripts/cross_framework_mapper.py control_libs.json
# 4. Run evidence pool generator to consolidate
python scripts/evidence_pool_generator.py program.json
# 5. Cross-check with cs-compliance-officer agent
# 6. Output: prioritized program backlog with owners + dates
```
### Workflow 2: Annual Audit Calendar (yearly)
**Goal:** plan internal audit cycles covering all applicable frameworks.
```bash
# 1. Refresh framework selector if profile changed
python scripts/framework_selector.py profile.json
# 2. For each framework, run its internal-audit-plan tool
# (e.g., aims_audit_scheduler.py for ISO 42001; isms_audit_scheduler.py for ISO 27001)
# 3. Coordinate the audit calendar across frameworks (auditor independence + capacity)
# 4. Run audit simulator for each framework to prep auditors
python scripts/audit_simulator.py scope.json
# 5. Output: integrated audit calendar with owners + auditor assignments
```
### Workflow 3: Pre-Certification Readiness (per new framework, 6–12 weeks)
**Goal:** prepare for an external certification audit.
```bash
# 1. Run gap analysis for the new framework
# (ISO 42001: aims_gap_analyzer.py; ISO 27001: compliance_checker.py; SOC 2: gap_analyzer.py)
# 2. Run cross-framework mapper against already-certified frameworks
python scripts/cross_framework_mapper.py control_libs.json
# 3. Reuse evidence for HIGH-confidence mappings; build new for MEDIUM/LOW
# 4. Run audit simulator to dry-run the certification audit
python scripts/audit_simulator.py scope.json
# 5. Close remaining gaps before external auditor stage 1
```
### Workflow 4: Evidence Pool Consolidation (quarterly)
**Goal:** keep the unified evidence pool fresh + reusable.
```bash
# 1. Refresh evidence pool generator
python scripts/evidence_pool_generator.py program.json
# 2. Identify HIGH-reuse-leverage artefacts (1 evidence -> 5+ controls)
# 3. Confirm evidence freshness (within retention requirement per framework)
# 4. Audit the evidence pool itself (no orphan controls, no stale evidence)
```
## Output Standards
```
**Bottom Line:** [one sentence — what's the multi-framework picture + biggest reuse opportunity]
**The Decision:** [one of: framework-set | overlap-map | audit-plan | evidence-consolidation]
**The Evidence:** [framework names + control IDs from the tool, not adjectives]
**How to Act:** [3 concrete next steps with owners + dates]
**Your Decision:** [the call only the compliance officer can make — which frameworks to pursue, audit cycle priority, evidence-reuse policy]
```
## Adjacent Skills
- `../../ra-qm-team/skills/iso42001-specialist/` — ISO 42001 deep-dive (paired with compliance-team-iso42001 plugin)
- `../../ra-qm-team/skills/eu-ai-act-specialist/` — EU AI Act deep-dive (paired with compliance-team-eu-ai-act plugin)
- `../../ra-qm-team/skills/information-security-manager-iso27001/` — ISO 27001 ISMS deep-dive
- `../../ra-qm-team/skills/quality-manager-qms-iso13485/` — ISO 13485 QMS deep-dive
- `../../ra-qm-team/skills/gdpr-dsgvo-expert/` — GDPR deep-dive
- `../../ra-qm-team/skills/soc2-compliance/` — SOC 2 deep-dive
- `../../ra-qm-team/skills/fda-consultant-specialist/` — FDA QSR deep-dive
- `../../ra-qm-team/skills/mdr-745-specialist/` — EU MDR 745 deep-dive
- `../../ra-qm-team/skills/risk-management-specialist/` — ISO 14971 deep-dive
- `../../c-level-advisor/chief-ai-officer-advisor/` — Executive AI risk decisions (build-vs-buy, model selection)
- `../../c-level-advisor/skills/general-counsel-advisor/` — Legal review for novel cases
## References
- [compliance_os_pattern.md](references/compliance_os_pattern.md) — The meta-framework architecture (configure → map → simulate → consolidate → review); when to use vs not
- [cross_framework_overlap.md](references/cross_framework_overlap.md) — The 9-framework × control-family overlap table with mapping confidence (Phase 3 expands to 12 frameworks via `cross_framework_mapper.py`)
- [audit_simulation_methodology.md](references/audit_simulation_methodology.md) — ISO 19011 + IIA IPPF + AICPA AT-C audit-simulation principles + severity distribution heuristics
- [evidence_management.md](references/evidence_management.md) — Evidence pool design + retention + freshness + reuse-leverage scoring
- [multi_framework_audit_playbook.md](references/multi_framework_audit_playbook.md) — Integrated audit programme for 2+ frameworks (Phase 2)
- [evidence_artifact_reuse_index.md](references/evidence_artifact_reuse_index.md) — Empirically-derived reuse-leverage ranking across all 12 frameworks (Phase 3)
## Phase 3 Asset: Mock Audit Scenario Library
`assets/mock_audit_library.json` — 205 pre-built finding scenarios spanning 12 frameworks + 26 themes + 4 severity levels (34 critical, 88 major, 54 minor, 29 observation). Each scenario tags applicable frameworks; cross-reference `scripts/cross_framework_mapper.py` merged-controls catalogue to resolve framework-specific control IDs. Use as input to enrich `audit_simulator.py` mock audits, as a training resource for new internal auditors, or as the seed for finding-pattern detection across multi-framework programmes.
---
**Version:** 1.2.0
**Status:** Production Ready
FILE:assets/company_profile_template.json
{
"company": "<company name>",
"industry": "<saas | medical_device | financial | healthcare | other>",
"products_include_ai": false,
"ai_high_risk_per_eu": false,
"deploys_ai_in_eu": false,
"products_are_medical_devices": false,
"sells_to_eu_customers": false,
"sells_to_us_customers": false,
"sells_to_enterprise_b2b": false,
"processes_personal_data": false,
"processes_eu_personal_data": false,
"headcount": 0,
"stage": "<seed | series_a | series_b | series_c | growth>",
"processes_phi": false,
"us_healthcare_covered_entity": false,
"us_healthcare_business_associate": false,
"nis2_essential_entity": false,
"nis2_important_entity": false,
"adopts_nist_csf": false,
"us_government_contractor": false
}
FILE:assets/control_library_template.json
{
"program": "<program name>",
"enabled_frameworks": [
"iso_27001",
"soc_2",
"iso_42001",
"eu_ai_act",
"gdpr"
],
"_supported_framework_ids": [
"iso_27001",
"iso_13485",
"iso_42001",
"iso_14971",
"eu_ai_act",
"eu_mdr_745",
"gdpr",
"soc_2",
"fda_qsr"
],
"_note": "Enable only the frameworks the framework_selector returned as applicable. Cross-framework mapper will compute overlap across enabled frameworks only."
}
FILE:assets/mock_audit_library.json
{
"schema_version": "1.0.0",
"description": "Pre-built finding scenarios for mock internal audits. Each scenario has theme + severity + applicable_frameworks tags; cross-reference scripts/cross_framework_mapper.py merged-controls catalogue to resolve framework-specific control IDs.",
"supported_frameworks": [
"iso_27001", "iso_13485", "iso_42001", "iso_14971",
"eu_ai_act", "eu_mdr_745", "gdpr", "soc_2", "fda_qsr",
"nist_csf", "nis2", "hipaa"
],
"severity_levels": {
"critical": "Major nonconformity: absence of, or systemic failure to implement, a required management-system process. Blocks certification at stage 1.",
"major": "Material gap in a required control. Corrective action plan within 30 days.",
"minor": "Localized gap; control works overall. Corrective action within 90 days.",
"observation": "Improvement opportunity; no nonconformity. Optional recommendation."
},
"scenarios": [
{"id": "F-AC-001", "theme": "access_control", "severity": "critical", "title": "Orphaned privileged access from terminations", "description": "Quarterly access review missed 3 cycles; 12 terminated employees retain prod admin access > 90 days post-termination. Audit log shows 4 of them performed actions in the system after their last working day.", "remediation": "Immediate revocation; investigate access logs for unauthorized activity; reinstate quarterly review cadence with automated tooling.", "remediation_days": 14, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "gdpr", "nist_csf", "hipaa", "nis2"]},
{"id": "F-AC-002", "theme": "access_control", "severity": "critical", "title": "Shared admin credentials in production", "description": "Production database admin password shared across 5 engineers; rotation last performed > 12 months ago. No audit trail for individual actions.", "remediation": "Rotate immediately; provision per-user named accounts; enable individual audit logging; document procedure.", "remediation_days": 7, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2"]},
{"id": "F-AC-003", "theme": "access_control", "severity": "major", "title": "Quarterly access review evidence lacks justification", "description": "Quarterly access review records exist but lack documented business justification for retained privileges. Reviewers approve in bulk without per-user rationale.", "remediation": "Update review template to require per-user justification; train reviewers; sample-check next quarter.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-AC-004", "theme": "access_control", "severity": "major", "title": "JML workflow does not auto-deprovision", "description": "Joiner-mover-leaver workflow exists but is manual; observed 5+ day gap between HR termination and access revocation.", "remediation": "Implement IDP integration with HR system for auto-deprovisioning within 24 hours; trail for exceptions.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "gdpr", "hipaa", "nis2"]},
{"id": "F-AC-005", "theme": "access_control", "severity": "major", "title": "MFA not enforced on admin accounts", "description": "Multi-factor authentication is documented in policy but not technically enforced on cloud admin accounts; 8 admin users authenticate without MFA.", "remediation": "Enforce MFA at IDP level; emergency-break-glass procedure documented; close legacy accounts.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2", "gdpr"]},
{"id": "F-AC-006", "theme": "access_control", "severity": "minor", "title": "Access review records lack completion timestamps", "description": "Access review records lack documented review-completion timestamps in 2 of 6 sampled reviews. Cannot confirm review was completed on time.", "remediation": "Update review tooling to capture timestamp at review-action time; backfill where possible.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa"]},
{"id": "F-AC-007", "theme": "access_control", "severity": "minor", "title": "RBAC matrix doesn't cover cloud resources", "description": "Role-based access control matrix exists for application tier but does not address cloud-resource scope (IAM policies, S3 buckets, KMS keys).", "remediation": "Extend RBAC matrix; document cloud-IAM role-to-business-role mapping.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-AC-008", "theme": "access_control", "severity": "observation", "title": "Consider just-in-time (JIT) access for production", "description": "Standing access to production is the default; JIT access with approval workflow would reduce blast radius and improve audit trail.", "remediation": "Pilot JIT tooling (e.g., Teleport, ConductorOne, ConsoleMe) for one team.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-AC-009", "theme": "access_control", "severity": "observation", "title": "Privileged access review cadence could be more frequent", "description": "Quarterly cadence meets standard; for ≥ critical-tier systems, monthly review provides earlier detection of orphaned access.", "remediation": "Increase cadence for critical-tier systems to monthly.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-AC-010", "theme": "access_control", "severity": "observation", "title": "Session timeout policies inconsistent", "description": "Session-timeout policies vary across applications (30 min in CRM, 8 hours in BI tool, no timeout in internal admin tool). Inconsistent risk posture.", "remediation": "Define policy by data sensitivity tier; align tooling configuration.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa"]},
{"id": "F-AI-001", "theme": "asset_inventory", "severity": "major", "title": "Asset inventory missing cloud + SaaS + AI tools", "description": "Asset register includes server inventory but omits 60% of SaaS tools and 100% of AI/LLM tools acquired in past 12 months. No central source of truth.", "remediation": "Integrate SSO with SaaS-discovery tooling; require AI-tool registration before procurement; quarterly refresh.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "nist_csf", "gdpr"]},
{"id": "F-AI-002", "theme": "asset_inventory", "severity": "major", "title": "Data classification scheme not applied", "description": "Data classification scheme documented (public / internal / confidential / restricted) but only 30% of data stores have classification labels applied.", "remediation": "Apply classification to remaining stores; automate via DLP tooling where feasible.", "remediation_days": 120, "applicable_frameworks": ["iso_27001", "soc_2", "gdpr", "hipaa", "nist_csf"]},
{"id": "F-AI-003", "theme": "asset_inventory", "severity": "minor", "title": "Asset owners not assigned for 15% of assets", "description": "15% of inventory entries lack named owners; orphan ownership impedes timely incident response.", "remediation": "Assign owners; require owner field on new asset creation.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-AI-004", "theme": "asset_inventory", "severity": "minor", "title": "Third-party AI services not tagged in inventory", "description": "Inventory does not flag which assets are powered by third-party AI services (e.g., OpenAI, Anthropic, Cohere). Material for ISO 42001 A.10 + EU AI Act Article 25.", "remediation": "Add AI-vendor tag; update procurement intake form.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "eu_ai_act", "iso_27001"]},
{"id": "F-AI-005", "theme": "asset_inventory", "severity": "observation", "title": "Asset decommissioning workflow informal", "description": "When assets are decommissioned, data destruction is documented but inventory entries persist; clutters reporting.", "remediation": "Add decommission state to inventory schema; archive after retention period.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa"]},
{"id": "F-RM-001", "theme": "risk_management", "severity": "critical", "title": "Risk register without treatment plans", "description": "Risk register identifies 30+ risks but lacks documented treatment plans (modify/share/retain/avoid per ISO 23894) for high/critical risks.", "remediation": "Run risk-treatment workshop per high/critical risk; document treatment + signoff; link to specific controls.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-RM-002", "theme": "risk_management", "severity": "critical", "title": "AI risk assessment not re-run after material model change", "description": "AI risk assessment last performed at initial deployment 18 months ago. Model has been retrained twice; risk profile not re-evaluated.", "remediation": "Trigger re-assessment; update register; document drift monitoring threshold; commit to re-assessment on every material change.", "remediation_days": 45, "applicable_frameworks": ["iso_42001", "eu_ai_act"]},
{"id": "F-RM-003", "theme": "risk_management", "severity": "major", "title": "Risk methodology inconsistently applied", "description": "Different teams use different risk-scoring methodologies; severity scores not comparable across the register.", "remediation": "Standardize on single methodology (e.g., 5x5 likelihood × impact matrix); train risk owners; re-score existing register.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_14971", "nist_csf", "soc_2"]},
{"id": "F-RM-004", "theme": "risk_management", "severity": "major", "title": "Residual risk acceptance lacks management signoff", "description": "30% of 'retain' risk-treatment decisions lack documented management signoff. Some retain decisions made by individual contributors.", "remediation": "Define signoff matrix by severity; backfill where possible; route remaining retain decisions through proper authority.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_14971", "nis2", "hipaa"]},
{"id": "F-RM-005", "theme": "risk_management", "severity": "major", "title": "Risk register not updated for 6+ months", "description": "Risk register last refreshed > 6 months ago. New risks from product changes, new vendors, regulatory developments not captured.", "remediation": "Refresh; commit to quarterly cadence minimum.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "iso_42001", "nist_csf", "nis2"]},
{"id": "F-RM-006", "theme": "risk_management", "severity": "minor", "title": "DPIA exists but Article 35(7) elements incomplete", "description": "DPIA documented for high-risk processing but does not cover all Article 35(7)(a)-(d) required elements (missing necessity + proportionality assessment).", "remediation": "Update DPIA template; refresh affected DPIAs.", "remediation_days": 60, "applicable_frameworks": ["gdpr", "iso_42001"]},
{"id": "F-RM-007", "theme": "risk_management", "severity": "minor", "title": "Risk treatment plans lack effective-date tracking", "description": "Treatment plans are documented but lack effective-date or expected-completion fields; cannot track remediation timeliness.", "remediation": "Add date fields; update existing entries.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2"]},
{"id": "F-RM-008", "theme": "risk_management", "severity": "observation", "title": "Consider FAIR quantitative risk methodology for top-tier risks", "description": "Current methodology is qualitative; quantitative analysis (e.g., Open FAIR) for top-5 risks would improve decision quality.", "remediation": "Pilot FAIR on 2-3 top risks.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "nist_csf"]},
{"id": "F-RM-009", "theme": "risk_management", "severity": "observation", "title": "Risk-related KPIs not reported to executive", "description": "Risk register exists but no rolled-up KPIs (e.g., # critical risks open, mean time to treatment) reported in management review.", "remediation": "Add risk KPIs to management review inputs.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "nist_csf"]},
{"id": "F-SM-001", "theme": "supplier_management", "severity": "critical", "title": "Critical SaaS in use without DPA", "description": "Critical SaaS supplier (handles personal data of 500K+ users) in use without signed DPA per GDPR Article 28. Pre-existing arrangement not refreshed since 2018.", "remediation": "Engage vendor for DPA execution; if vendor refuses, evaluate replacement.", "remediation_days": 30, "applicable_frameworks": ["gdpr", "iso_27001", "soc_2", "hipaa"]},
{"id": "F-SM-002", "theme": "supplier_management", "severity": "critical", "title": "Business Associate Agreement missing for HIPAA-relevant vendor", "description": "Vendor processes PHI on behalf of the organization but no signed Business Associate Agreement (BAA) per HIPAA §164.314(a). Material exposure.", "remediation": "Sign BAA; if vendor refuses, evaluate replacement; document remediation timeline.", "remediation_days": 30, "applicable_frameworks": ["hipaa", "iso_27001"]},
{"id": "F-SM-003", "theme": "supplier_management", "severity": "major", "title": "Annual supplier reviews incomplete", "description": "Annual supplier security review not completed for 3 of 8 critical suppliers in past year.", "remediation": "Run overdue reviews; calendar future reviews; document escalation for non-responsive vendors.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "hipaa", "nis2", "gdpr"]},
{"id": "F-SM-004", "theme": "supplier_management", "severity": "major", "title": "Sub-processor list not maintained", "description": "Critical supplier handling personal data uses sub-processors; the sub-processor list is not maintained or available; GDPR Article 28(2) not satisfied.", "remediation": "Request sub-processor list from vendor; establish change notification mechanism; document.", "remediation_days": 60, "applicable_frameworks": ["gdpr", "iso_27001", "nist_csf"]},
{"id": "F-SM-005", "theme": "supplier_management", "severity": "major", "title": "AI-specific contract clauses not in vendor agreements", "description": "Third-party AI service in use; contract lacks AI-specific clauses (training-data use restrictions, drift notification, sub-processor list for AI sub-services).", "remediation": "Negotiate addendum; document acceptance.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "eu_ai_act", "iso_27001"]},
{"id": "F-SM-006", "theme": "supplier_management", "severity": "major", "title": "Supplier exit / termination procedure not documented", "description": "No procedure for safe vendor exit (data return, model deletion, monitoring transition). Discovered during attempt to terminate one supplier.", "remediation": "Draft procedure; pilot on next vendor termination; document.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2", "gdpr"]},
{"id": "F-SM-007", "theme": "supplier_management", "severity": "minor", "title": "Vendor onboarding checklist applied inconsistently", "description": "Supplier onboarding checklist exists but is bypassed in 'urgent' procurements; 4 of 12 recent vendors lack complete onboarding evidence.", "remediation": "Make checklist mandatory at procurement gate; remediate gaps in existing 4.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-SM-008", "theme": "supplier_management", "severity": "minor", "title": "Supplier SOC 2 reports collected but not reviewed", "description": "Critical suppliers' SOC 2 Type II reports collected on initial onboarding but not reviewed annually as new reports issued.", "remediation": "Set calendar for annual review; document key findings + acceptance.", "remediation_days": 60, "applicable_frameworks": ["soc_2", "iso_27001"]},
{"id": "F-SM-009", "theme": "supplier_management", "severity": "observation", "title": "Consider centralizing supplier risk evidence in GRC tool", "description": "Supplier evidence scattered across procurement Drive, Compliance Drive, and email. Centralization in GRC tool would reduce audit prep effort.", "remediation": "Evaluate GRC tooling; migrate over 6 months.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001"]},
{"id": "F-SM-010", "theme": "supplier_management", "severity": "observation", "title": "Vendor risk-tiering could be more granular", "description": "Vendors tier as 'critical / non-critical' currently; more granular tiers (e.g., based on data type, criticality, integration depth) would refine review cadence.", "remediation": "Define 3-tier model; reclassify existing inventory.", "remediation_days": 120, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa"]},
{"id": "F-IR-001", "theme": "incident_response", "severity": "critical", "title": "GDPR Article 33 breach notification missed", "description": "Breach occurred 96 hours ago; supervisory authority not notified despite Article 33 72-hour requirement. Investigation revealed unclear breach-criteria decision.", "remediation": "File notification immediately with rationale for delay; review breach-criteria decision tree; conduct tabletop exercise; document.", "remediation_days": 7, "applicable_frameworks": ["gdpr", "iso_27001", "hipaa", "nis2"]},
{"id": "F-IR-002", "theme": "incident_response", "severity": "critical", "title": "Recent P1 incident lacks PIR within SLA", "description": "P1 production incident occurred 45 days ago; post-incident review (PIR) not documented within stated 30-day SLA.", "remediation": "Complete PIR immediately; identify corrective actions; calendar future PIRs.", "remediation_days": 14, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "nist_csf"]},
{"id": "F-IR-003", "theme": "incident_response", "severity": "critical", "title": "Severity definitions inconsistently applied", "description": "Severity definitions documented but inconsistently applied across teams; impact analysis varies. Two recent P2 incidents arguably P1 by definition.", "remediation": "Train responders on severity rubric; calibration exercise quarterly; track severity-classification consistency.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "gdpr", "hipaa"]},
{"id": "F-IR-004", "theme": "incident_response", "severity": "major", "title": "Notification SLAs not aligned across frameworks", "description": "GDPR 72h, NIS2 24h-early-warning + 72h-notification, EU AI Act 15-day (or 2-day critical-infra), HIPAA 60-day. Internal procedures collapse to a single 'breach' notification without per-framework branching.", "remediation": "Update IR procedure to branch by applicable framework; train responders.", "remediation_days": 60, "applicable_frameworks": ["gdpr", "nis2", "eu_ai_act", "hipaa", "iso_27001"]},
{"id": "F-IR-005", "theme": "incident_response", "severity": "major", "title": "Incident commander rotation not documented", "description": "Incident commander rotation exists informally but is not documented; recent incidents had ambiguous IC ownership.", "remediation": "Document rotation; publish on-call schedule.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-IR-006", "theme": "incident_response", "severity": "major", "title": "Breach log incomplete per Article 33(5)", "description": "GDPR breach log captures only DPA-notifiable events; Article 33(5) requires ALL breaches logged regardless of notifiability.", "remediation": "Update breach log scope; backfill recent breaches; train DPO on requirement.", "remediation_days": 60, "applicable_frameworks": ["gdpr", "iso_27001", "hipaa"]},
{"id": "F-IR-007", "theme": "incident_response", "severity": "major", "title": "Detection mechanism gaps", "description": "Mean time to detect (MTTD) for past 3 incidents averaged 8 days; SIEM rules not tuned for recently-onboarded systems.", "remediation": "Audit SIEM coverage; tune rules; test detection for high-impact attack scenarios.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2"]},
{"id": "F-IR-008", "theme": "incident_response", "severity": "minor", "title": "Tabletop exercise not conducted in last 12 months", "description": "Annual incident-response tabletop exercise not performed in past 12 months.", "remediation": "Schedule + run tabletop; document lessons learned.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-IR-009", "theme": "incident_response", "severity": "minor", "title": "Customer notification timing not tracked", "description": "Customer-facing incident notifications sent but timing not tracked against committed SLA. Cannot demonstrate SLA compliance.", "remediation": "Track notification timestamps; report against SLA quarterly.", "remediation_days": 60, "applicable_frameworks": ["soc_2", "iso_27001", "gdpr"]},
{"id": "F-IR-010", "theme": "incident_response", "severity": "observation", "title": "Consider chaos engineering for resilience testing", "description": "Incident response prepares for failures; chaos engineering would proactively surface latent weaknesses.", "remediation": "Pilot chaos engineering on non-prod first; expand if mature.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-ML-001", "theme": "monitoring_logging", "severity": "critical", "title": "Production application logs disabled", "description": "Production application logs disabled in past 30 days due to disk space; not detected until audit fieldwork. 30-day blind spot.", "remediation": "Re-enable; resize storage; alert on log volume drops; investigate any incidents during blind period.", "remediation_days": 7, "applicable_frameworks": ["iso_27001", "soc_2", "iso_42001", "hipaa", "nist_csf"]},
{"id": "F-ML-002", "theme": "monitoring_logging", "severity": "major", "title": "Log retention misaligned with framework requirement", "description": "Log retention configured at 90 days; ISO 27001 + framework requirements expect 12 months minimum for some logs.", "remediation": "Update retention configuration; backfill from archives where feasible; document policy.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf", "gdpr"]},
{"id": "F-ML-003", "theme": "monitoring_logging", "severity": "major", "title": "Tamper-evident logging not enforced", "description": "Tamper-evident logging not enforced on privileged-user activity logs; logs writable to same store as application data.", "remediation": "Move logs to write-once storage; document architecture; verify immutability.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf", "nis2"]},
{"id": "F-ML-004", "theme": "monitoring_logging", "severity": "major", "title": "AI model drift not monitored", "description": "AI system in production; no drift monitoring against original validation data. No defined drift threshold for retraining.", "remediation": "Implement drift monitoring; define threshold; escalation path.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "eu_ai_act"]},
{"id": "F-ML-005", "theme": "monitoring_logging", "severity": "minor", "title": "Monitoring alert thresholds not documented", "description": "Monitoring alert thresholds exist in tooling but not documented; rationale unclear.", "remediation": "Document thresholds + rationale + on-call response action.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-ML-006", "theme": "monitoring_logging", "severity": "minor", "title": "Cloud audit logs not centralized", "description": "Cloud audit logs (CloudTrail/Cloud Audit Logs) exist per account but not centralized to SIEM; cross-account analysis manual.", "remediation": "Forward logs to central SIEM; configure cross-account analysis.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-ML-007", "theme": "monitoring_logging", "severity": "observation", "title": "Consider anomaly detection on top of rule-based monitoring", "description": "Current monitoring is rule-based; anomaly detection (statistical or ML-based) would surface novel patterns.", "remediation": "Pilot on key data flows.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-CM-001", "theme": "change_management", "severity": "critical", "title": "Emergency change procedure not formalized", "description": "Emergency change procedure not documented; observed 3 cases of production changes in past 30 days without recorded approval. Two affected customer data.", "remediation": "Draft emergency change procedure including retroactive review; train engineers; audit recent emergency changes.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "iso_13485", "hipaa", "nist_csf"]},
{"id": "F-CM-002", "theme": "change_management", "severity": "major", "title": "Change advisory board rubber-stamps", "description": "Change advisory board records show approvals but zero rejected changes in last 6 months. Board likely not exercising substantive review.", "remediation": "Calibration training for board; track reject + revise rate; ensure reviewers have time + context.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "iso_13485"]},
{"id": "F-CM-003", "theme": "change_management", "severity": "major", "title": "Rollback procedure not tested", "description": "Rollback procedure documented but not tested for 2 services in audit scope. Cannot confirm operability.", "remediation": "Test rollback in staging; document; schedule quarterly verification.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "iso_13485", "nist_csf"]},
{"id": "F-CM-004", "theme": "change_management", "severity": "minor", "title": "Post-implementation reviews skipped for high-risk changes", "description": "Change advisory board records show approvals but no post-implementation review for high-risk changes (defined by impact rubric).", "remediation": "Reinstate post-implementation review for high-risk; define follow-up timeline.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "iso_13485"]},
{"id": "F-CM-005", "theme": "change_management", "severity": "observation", "title": "Link change records to deployment automation", "description": "Change records and deployment automation are separate systems; linking would strengthen evidence chain.", "remediation": "Integrate via deployment tagging.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-BC-001", "theme": "business_continuity", "severity": "critical", "title": "BCP/DRP exists but never tested", "description": "Business continuity + disaster recovery plans exist on paper but no recovery exercise in 24+ months. Untested = ineffective.", "remediation": "Conduct full DR exercise; document results; commit to annual exercise cadence.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-BC-002", "theme": "business_continuity", "severity": "major", "title": "RPO/RTO objectives not measured", "description": "Recovery objectives defined but not measured during recent failover events. Cannot confirm objectives are achievable.", "remediation": "Measure during next exercise; tune objectives or recovery capability.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa"]},
{"id": "F-BC-003", "theme": "business_continuity", "severity": "major", "title": "Backup integrity not verified", "description": "Backups occur but restoration testing not performed in past 12 months. Cannot confirm backups are usable.", "remediation": "Quarterly restoration tests; document verification evidence.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nis2"]},
{"id": "F-BC-004", "theme": "business_continuity", "severity": "minor", "title": "BCP doesn't address third-party SaaS outage", "description": "BCP covers self-hosted infrastructure; doesn't address critical SaaS-vendor outage scenarios.", "remediation": "Extend BCP for SaaS outage scenarios; document vendor SLAs + alternatives.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2"]},
{"id": "F-BC-005", "theme": "business_continuity", "severity": "observation", "title": "Consider chaos game-day exercises", "description": "Annual DR exercise meets standard; chaos game-day adds value by testing under more realistic conditions.", "remediation": "Pilot game-day for one service.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-CT-001", "theme": "competence_training", "severity": "major", "title": "Annual security training not 100% complete", "description": "Annual security training completion is 89% across the company; 12 employees past due > 30 days.", "remediation": "Escalate to managers for non-completers; revoke access for chronic non-completers; document policy.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2"]},
{"id": "F-CT-002", "theme": "competence_training", "severity": "major", "title": "AI literacy training not in place", "description": "EU AI Act Article 4 requires AI literacy for staff dealing with AI systems; no AI-specific training implemented.", "remediation": "Develop + roll out AI literacy training; track completion by role.", "remediation_days": 90, "applicable_frameworks": ["eu_ai_act", "iso_42001"]},
{"id": "F-CT-003", "theme": "competence_training", "severity": "major", "title": "Competence requirements undefined for ML engineers", "description": "Competence requirements defined for engineering roles but not specifically for ML engineers; assumes 'they have degrees'.", "remediation": "Define ML-engineer competence requirements; verify against existing staff.", "remediation_days": 90, "applicable_frameworks": ["iso_42001"]},
{"id": "F-CT-004", "theme": "competence_training", "severity": "minor", "title": "Training effectiveness verification missing", "description": "Training completion recorded but effectiveness verification (assessment, simulation, observed behavior) not performed.", "remediation": "Add post-training assessment; track scores.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2"]},
{"id": "F-CT-005", "theme": "competence_training", "severity": "observation", "title": "Consider role-based training tiers", "description": "Training is uniform across roles; role-based tiers would surface compliance-officer-specific, dev-specific, etc.", "remediation": "Design role-tiered curriculum.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-DG-001", "theme": "data_governance", "severity": "critical", "title": "Training data lacks provenance records", "description": "AI training data sourced from multiple vendors + scraped sources; no provenance records. EU AI Act Article 10(2)(d) + ISO 42001 A.7.4 not satisfied.", "remediation": "Audit current training data; document provenance per source; remove data without verifiable provenance.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "eu_ai_act", "gdpr"]},
{"id": "F-DG-002", "theme": "data_governance", "severity": "critical", "title": "PII in training data without lawful basis", "description": "Training data contains PII; lawful basis (GDPR Article 6) not documented for AI training use case. Article 10(5) AI Act bias-detection exception not applicable here.", "remediation": "Document lawful basis or remove PII; if legitimate interests, document LIA; halt training until resolved.", "remediation_days": 30, "applicable_frameworks": ["gdpr", "iso_42001", "eu_ai_act"]},
{"id": "F-DG-003", "theme": "data_governance", "severity": "major", "title": "Data quality dimensions not defined", "description": "Data quality monitoring exists but dimensions (completeness, accuracy, timeliness, consistency) not formally defined. Audit against ISO 42001 A.7.3 incomplete.", "remediation": "Define dimensions per data store; document measurement methodology.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "iso_27001", "gdpr"]},
{"id": "F-DG-004", "theme": "data_governance", "severity": "major", "title": "Article 30 RoPA stale", "description": "GDPR Article 30 records of processing activities last refreshed 8 months ago; new processing activities not captured.", "remediation": "Refresh RoPA; commit to quarterly updates; integrate with new-feature intake.", "remediation_days": 60, "applicable_frameworks": ["gdpr"]},
{"id": "F-DG-005", "theme": "data_governance", "severity": "major", "title": "Retention schedules not enforced", "description": "Data retention schedules documented but not enforced in tooling. Data persists beyond stated retention.", "remediation": "Implement automated retention enforcement; backfill cleanup; document deletions.", "remediation_days": 90, "applicable_frameworks": ["gdpr", "iso_27001", "hipaa", "iso_42001"]},
{"id": "F-DG-006", "theme": "data_governance", "severity": "minor", "title": "Consent management workflow lacks withdrawal mechanism", "description": "Consent collected at signup; withdrawal mechanism exists in privacy notice but not technically implemented.", "remediation": "Implement self-service consent withdrawal; honour within reasonable time.", "remediation_days": 90, "applicable_frameworks": ["gdpr"]},
{"id": "F-DG-007", "theme": "data_governance", "severity": "observation", "title": "Consider data lineage tooling", "description": "Data flows documented manually; data-lineage tooling would automate + maintain freshness.", "remediation": "Evaluate tooling (e.g., OpenLineage, DataHub, Atlan).", "remediation_days": 180, "applicable_frameworks": ["iso_42001", "gdpr"]},
{"id": "F-CR-001", "theme": "cryptography", "severity": "major", "title": "Encryption at rest using deprecated algorithm", "description": "Some data stores still use deprecated AES-128 (or 3DES); current standard expects AES-256.", "remediation": "Plan migration; document; complete within 6 months.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2", "gdpr"]},
{"id": "F-CR-002", "theme": "cryptography", "severity": "major", "title": "Key rotation not enforced", "description": "Cryptographic key rotation policy exists (annual) but not enforced; production keys 3+ years old.", "remediation": "Rotate immediately; automate rotation via KMS; document.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2", "gdpr"]},
{"id": "F-CR-003", "theme": "cryptography", "severity": "major", "title": "TLS configuration permits deprecated versions", "description": "TLS 1.0 + 1.1 still accepted on public endpoints; current standard expects TLS 1.2 minimum.", "remediation": "Disable TLS 1.0 + 1.1; verify all clients support 1.2+; document.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2", "gdpr"]},
{"id": "F-CR-004", "theme": "cryptography", "severity": "minor", "title": "Cryptographic inventory incomplete", "description": "Cryptographic inventory exists but lacks documentation of algorithm + key length per data store.", "remediation": "Audit each store; document; flag deprecated algorithms.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "nist_csf", "hipaa"]},
{"id": "F-CR-005", "theme": "cryptography", "severity": "observation", "title": "Consider post-quantum cryptography roadmap", "description": "Current crypto is RSA + ECC; post-quantum standards finalized in 2024. Long-term planning for migration recommended.", "remediation": "Define PQC migration roadmap.", "remediation_days": 365, "applicable_frameworks": ["iso_27001", "nist_csf", "nis2"]},
{"id": "F-SD-001", "theme": "secure_sdlc", "severity": "critical", "title": "Production deploy without SAST results", "description": "Recent production deploys lack SAST scan evidence; SAST configured in CI but bypassed via manual override.", "remediation": "Make SAST a required gate; remove override capability for production; investigate bypassed deploys.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-SD-002", "theme": "secure_sdlc", "severity": "major", "title": "Code review records inconsistent", "description": "Some commits to main branch lack documented review; review-required branch protection not consistently enforced.", "remediation": "Enforce review on protected branches across all repos; audit recent commits.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-SD-003", "theme": "secure_sdlc", "severity": "major", "title": "Threat modeling not performed for new services", "description": "New service launched last quarter without threat model. ISO 27001 A.8.25-31 + secure-by-design expectations not met.", "remediation": "Retroactive threat model; integrate threat modeling into design-review gate.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2"]},
{"id": "F-SD-004", "theme": "secure_sdlc", "severity": "minor", "title": "Dependency scanning missing for some repos", "description": "Dependency scanning configured for production services but not for internal tools.", "remediation": "Extend dependency scanning to all repos.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-SD-005", "theme": "secure_sdlc", "severity": "observation", "title": "Consider supply-chain security per SLSA", "description": "Build provenance + supply-chain security gaps; SLSA framework would formalize improvements.", "remediation": "Adopt SLSA Level 2 minimum for production builds.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "nist_csf", "nis2"]},
{"id": "F-VM-001", "theme": "vulnerability_mgmt", "severity": "critical", "title": "Critical vulnerabilities past patch SLA", "description": "5 critical-severity CVEs in production older than 30-day patch SLA; one is actively exploited in wild.", "remediation": "Patch immediately; document compensating controls if patching not possible; investigate any compromise indicators.", "remediation_days": 14, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-VM-002", "theme": "vulnerability_mgmt", "severity": "major", "title": "Vulnerability scanning not running weekly", "description": "Scanning configured but execution stopped in past quarter due to tool change. 90+ day blind spot.", "remediation": "Resume scanning; investigate vulnerabilities discovered post-resume.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-VM-003", "theme": "vulnerability_mgmt", "severity": "major", "title": "Patch SLAs not defined by severity", "description": "Patch SLA defined for 'all CVEs within 90 days'; not differentiated by severity. Critical vulns should be < 30 days.", "remediation": "Define severity-tiered SLAs; communicate; track compliance.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2"]},
{"id": "F-VM-004", "theme": "vulnerability_mgmt", "severity": "minor", "title": "Vulnerability exceptions lack expiry", "description": "Exception tracking exists but exceptions have no expiry; some are 18+ months old without re-evaluation.", "remediation": "Add expiry; re-evaluate all open exceptions.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-VM-005", "theme": "vulnerability_mgmt", "severity": "observation", "title": "Consider container image base auditing", "description": "Vulnerability scanning catches runtime; auditing base images at build time would prevent vulnerabilities reaching production.", "remediation": "Add build-time scanning + base-image inventory.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "nist_csf"]},
{"id": "F-PS-001", "theme": "physical_security", "severity": "major", "title": "Server room access log incomplete", "description": "Server room access log shows entries but lacks visitor escort records for 4 of 12 sampled entries.", "remediation": "Reinforce escort policy; train + supervise; verify in next quarter.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "iso_13485", "hipaa"]},
{"id": "F-PS-002", "theme": "physical_security", "severity": "major", "title": "Workstation security policy not enforced", "description": "Workstation locking policy documented but not enforced; observed several unattended unlocked workstations during walkthrough.", "remediation": "Configure auto-lock at 5 min; train staff; verify.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "hipaa", "soc_2"]},
{"id": "F-PS-003", "theme": "physical_security", "severity": "minor", "title": "Visitor sign-in process bypassed", "description": "Visitor sign-in book exists but bypassed for 'known' visitors; 8 sampled visits lack sign-in evidence.", "remediation": "Reinforce policy + signage; consider electronic visitor management.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_13485", "hipaa"]},
{"id": "F-PS-004", "theme": "physical_security", "severity": "observation", "title": "Consider biometric access for sensitive zones", "description": "Current access is card-based; biometric for sensitive zones (server rooms, R&D labs) would strengthen access discipline.", "remediation": "Evaluate biometric tooling; pilot.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "hipaa", "iso_13485"]},
{"id": "F-DP-001", "theme": "data_protection_privacy", "severity": "critical", "title": "Right to erasure not honored within SLA", "description": "Erasure request from 60 days ago not fully completed; data persists in 3 systems including backups. GDPR Article 17 + 12(3) breached.", "remediation": "Complete erasure; identify all systems; commit to per-system erasure workflow.", "remediation_days": 14, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-002", "theme": "data_protection_privacy", "severity": "critical", "title": "International transfer without SCCs", "description": "Personal data transferred to US subprocessor; no adequacy decision relied on, no SCCs signed, no derogation applies. Schrems II requirement breached.", "remediation": "Execute SCCs (Commission 2021/914); conduct TIA per EDPB Rec. 01/2020; supplementary measures where needed.", "remediation_days": 30, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-003", "theme": "data_protection_privacy", "severity": "major", "title": "Privacy notice missing Article 13/14 elements", "description": "Privacy notice published but lacks retention periods + data subject rights detail per Article 13(2).", "remediation": "Update notice; publish version; track versions for evidence trail.", "remediation_days": 30, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-004", "theme": "data_protection_privacy", "severity": "major", "title": "Cookie banner pre-ticks consent", "description": "Cookie banner pre-ticks non-essential cookies; valid consent per GDPR Article 7 + EDPB guidance requires affirmative action.", "remediation": "Redesign banner; default to no consent for non-essential; document A/B test.", "remediation_days": 30, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-005", "theme": "data_protection_privacy", "severity": "major", "title": "DPO appointment not formal", "description": "DPO exists but appointment letter not signed by senior management per GDPR Article 37 + 38. Reporting line ambiguous.", "remediation": "Formal appointment letter; clarify reporting line to highest management; publish contact.", "remediation_days": 30, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-006", "theme": "data_protection_privacy", "severity": "minor", "title": "DSAR identity verification process inconsistent", "description": "DSAR identity verification varies across teams; one DSAR processed without proper identity check.", "remediation": "Standardize verification procedure; train DPO + intake team.", "remediation_days": 60, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-007", "theme": "data_protection_privacy", "severity": "observation", "title": "Consider privacy-enhancing technologies (PETs)", "description": "Current privacy posture is procedural; PETs (differential privacy, federated learning, secure enclaves) for high-risk processing would reduce exposure.", "remediation": "Pilot PET for one high-risk processing.", "remediation_days": 365, "applicable_frameworks": ["gdpr", "iso_42001"]},
{"id": "F-MR-001", "theme": "management_review", "severity": "critical", "title": "Management review not performed in 18 months", "description": "Management review last documented 18 months ago. Clause 9.3 expects at planned intervals (annual minimum). System effectiveness not formally evaluated.", "remediation": "Schedule + conduct review; document inputs + outputs; calendar future reviews.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2"]},
{"id": "F-MR-002", "theme": "management_review", "severity": "major", "title": "Management review missing AI-specific inputs", "description": "Management review covers ISMS but not AIMS-specific inputs (drift events, incidents, risk-register changes per ISO 42001 Clause 9.3).", "remediation": "Update review template for AIMS inputs; include in next review.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-MR-003", "theme": "management_review", "severity": "major", "title": "Open action items past due", "description": "Management review action items: 4 of 9 past due > 60 days. Tracking not actively managed.", "remediation": "Reassign owners; escalate stuck items; re-baseline due dates.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2"]},
{"id": "F-MR-004", "theme": "management_review", "severity": "minor", "title": "Review attendance lacks senior leadership", "description": "Review held but CEO + CTO absent; attendance of senior leadership expected per Clause 5.1 + 9.3.", "remediation": "Schedule with leadership in advance; share inputs ahead of meeting.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2"]},
{"id": "F-IA-001", "theme": "internal_audit", "severity": "critical", "title": "No internal audit programme", "description": "Clause 9.2 internal audit programme not documented; audits happen ad-hoc; no rolling 3-year coverage plan.", "remediation": "Design programme; assign auditors; schedule next 12 months minimum.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2", "hipaa"]},
{"id": "F-IA-002", "theme": "internal_audit", "severity": "major", "title": "Auditors audit own work", "description": "Internal auditor for Clause 8.3 audit also owns the lifecycle process being audited. Independence breached.", "remediation": "Reassign auditor; document independence verification per assignment.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485"]},
{"id": "F-IA-003", "theme": "internal_audit", "severity": "major", "title": "Audit findings not tracked to closure", "description": "Audit findings logged but closure verification not consistently performed. 12 findings show 'closed' without evidence of effectiveness.", "remediation": "Verify closure; require evidence; reopen unverified.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2"]},
{"id": "F-IA-004", "theme": "internal_audit", "severity": "minor", "title": "Audit programme doesn't cover all clauses", "description": "Audit programme covers Clauses 4-7 but not 8-10 in current 3-year cycle.", "remediation": "Update programme; add missing clauses to remaining cycle.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485"]},
{"id": "F-CI-001", "theme": "continual_improvement", "severity": "major", "title": "CAPA without effectiveness verification", "description": "Corrective action plans documented + closed but effectiveness verification missing for 6 of 10 sampled CAPAs.", "remediation": "Add measurable effectiveness verification to template; verify per CAPA; sample-check.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "fda_qsr"]},
{"id": "F-CI-002", "theme": "continual_improvement", "severity": "major", "title": "Root cause analysis shallow", "description": "Root cause analysis on CAPAs documented but stops at proximate cause (e.g., 'engineer made mistake'); 5 Whys not applied.", "remediation": "Train CAPA owners on RCA methodology; re-do RCA on recent CAPAs.", "remediation_days": 90, "applicable_frameworks": ["iso_13485", "iso_42001", "iso_27001", "fda_qsr"]},
{"id": "F-CI-003", "theme": "continual_improvement", "severity": "minor", "title": "Trend analysis not performed", "description": "Individual CAPAs handled but trend analysis across CAPAs not performed; missed systemic issues.", "remediation": "Quarterly trend analysis; pattern identification; address systemic causes.", "remediation_days": 90, "applicable_frameworks": ["iso_13485", "iso_27001", "iso_42001", "fda_qsr"]},
{"id": "F-CI-004", "theme": "continual_improvement", "severity": "observation", "title": "Consider integrating CAPA into existing ticketing", "description": "CAPA tracking in separate tool from incident tickets; integration would reduce overhead.", "remediation": "Evaluate ticket-system extensions; pilot.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2"]},
{"id": "F-DC-001", "theme": "documentation_control", "severity": "major", "title": "Obsolete documents accessible", "description": "Old versions of policies and procedures accessible in shared drives without 'obsolete' marking; risk of using superseded content.", "remediation": "Archive obsolete versions; reorganize document drive; reinforce procedure.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_13485", "iso_42001", "fda_qsr"]},
{"id": "F-DC-002", "theme": "documentation_control", "severity": "major", "title": "Document approval workflow bypassed", "description": "Document approval workflow exists but 3 recent policy updates published without documented approval.", "remediation": "Enforce workflow at publication; train owners; audit recent publications.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "iso_13485", "iso_42001", "soc_2"]},
{"id": "F-DC-003", "theme": "documentation_control", "severity": "minor", "title": "Document review cadence not enforced", "description": "Annual review cadence stated but 25% of controlled documents past due > 90 days.", "remediation": "Calendar reviews; track due dates; remind owners.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_13485", "iso_42001"]},
{"id": "F-AIMS-001", "theme": "aims_specific", "severity": "critical", "title": "AI policy missing required commitments", "description": "AI policy commits to lawful use only; missing beneficial purpose, human oversight, and continual improvement. ISO 42001 Clause 5.2 + Annex A.2.2 not satisfied.", "remediation": "Rewrite policy with all 4 commitments; board signoff; publish.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIMS-002", "theme": "aims_specific", "severity": "critical", "title": "AIMS scope omits third-party AI", "description": "AIMS scope statement (Clause 4.3) lists company-built AI systems but omits AI features in SaaS vendors used internally. Scope incomplete.", "remediation": "Update scope; inventory third-party AI; include in AIMS controls.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIMS-003", "theme": "aims_specific", "severity": "critical", "title": "AI system lifecycle skips decommission", "description": "AI lifecycle procedure (A.6) covers design through deployment + operation but lacks decommission phase. ISO 42001 expects full lifecycle.", "remediation": "Define decommission procedure; train owners; document.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIMS-004", "theme": "aims_specific", "severity": "major", "title": "V&V procedure for AI systems undefined", "description": "Annex A.6.2.4 verification + validation procedure not documented; tests exist but acceptance criteria not formalized.", "remediation": "Define V&V procedure; document acceptance criteria per system class; train.", "remediation_days": 90, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIMS-005", "theme": "aims_specific", "severity": "major", "title": "Impact assessment signed by wrong authority", "description": "AI impact assessments for high-impact systems signed by tech lead; management approval expected per A.5.4.", "remediation": "Define signoff authority by impact tier; re-route assessments; backfill where needed.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIA-001", "theme": "ai_act_specific", "severity": "critical", "title": "Article 5 prohibited practice in production", "description": "AI system performs emotion recognition in workplace setting; Article 5(1)(f) prohibition applies. System cannot remain on EU market.", "remediation": "Disable in EU immediately; evaluate redesign for permitted use cases; document.", "remediation_days": 7, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-002", "theme": "ai_act_specific", "severity": "critical", "title": "High-risk AI without conformity assessment", "description": "Annex III high-risk AI system on EU market; no Article 43 conformity assessment performed before placement.", "remediation": "Withdraw from market until conformity assessment complete; document Annex IV; CE marking.", "remediation_days": 30, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-003", "theme": "ai_act_specific", "severity": "major", "title": "Non-EU provider without authorized representative", "description": "Non-EU provider placing AI system on EU market without appointed authorized representative per Article 22.", "remediation": "Appoint EU-established authorized representative; document mandate.", "remediation_days": 60, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-004", "theme": "ai_act_specific", "severity": "major", "title": "Article 50 transparency not implemented", "description": "Customer-facing chatbot does not disclose AI interaction per Article 50(1).", "remediation": "Add disclosure to UX; A/B test wording.", "remediation_days": 30, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-005", "theme": "ai_act_specific", "severity": "major", "title": "GPAI without Article 53 technical documentation", "description": "GPAI model provided to downstream integrators; Annex XI technical documentation not maintained.", "remediation": "Develop documentation per Annex XI; publish training-data summary; copyright policy.", "remediation_days": 60, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-13485-001", "theme": "qms_specific", "severity": "critical", "title": "DHF incomplete for commercial device", "description": "Design history file for commercially distributed device lacks design validation evidence per ISO 13485 Clause 7.3.7.", "remediation": "Compile validation evidence; document; if not feasible, withdraw + revalidate.", "remediation_days": 60, "applicable_frameworks": ["iso_13485", "fda_qsr"]},
{"id": "F-13485-002", "theme": "qms_specific", "severity": "critical", "title": "Process validation stale", "description": "Sterilization process not revalidated for 7 years despite supplier changes. ISO 13485 Clause 7.5.6 expects periodic revalidation.", "remediation": "Revalidate; document; calendar future revalidation.", "remediation_days": 90, "applicable_frameworks": ["iso_13485", "fda_qsr"]},
{"id": "F-13485-003", "theme": "qms_specific", "severity": "major", "title": "Risk management file frozen at release", "description": "ISO 14971 risk management file not updated post-launch; post-production information feedback not occurring.", "remediation": "Update RMF with post-production information; commit to periodic review.", "remediation_days": 90, "applicable_frameworks": ["iso_13485", "iso_14971", "eu_mdr_745", "fda_qsr"]},
{"id": "F-13485-004", "theme": "qms_specific", "severity": "major", "title": "PMCF plan exists but not executed", "description": "Post-market clinical follow-up plan documented per EU MDR Annex XIV Part B; execution data lacking after 12 months.", "remediation": "Execute per plan; document; report to notified body if outside plan.", "remediation_days": 90, "applicable_frameworks": ["iso_13485", "eu_mdr_745"]},
{"id": "F-FDA-001", "theme": "fda_specific", "severity": "critical", "title": "MDR-reportable event not reported", "description": "Serious adverse event reportable per 21 CFR 803.50 not reported within 30 days. FDA enforcement exposure.", "remediation": "File MDR immediately with delay rationale; review complaint trending; CAPA.", "remediation_days": 7, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-FDA-002", "theme": "fda_specific", "severity": "major", "title": "Complaint files incomplete", "description": "Complaint log per 21 CFR 820.198 missing investigation closure for 8 of 30 sampled complaints.", "remediation": "Investigate + close; train complaint handlers.", "remediation_days": 60, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-FDA-003", "theme": "fda_specific", "severity": "major", "title": "Form 483 open observations past response window", "description": "Form 483 received 6 months ago; 2 of 5 observations lack documented response within 15-working-day window.", "remediation": "Respond immediately; document corrective action; escalate to legal counsel.", "remediation_days": 14, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-FDA-004", "theme": "fda_specific", "severity": "minor", "title": "Labeling review evidence gaps", "description": "Labeling per 21 CFR 801 reviewed at launch but no documented re-review for label changes in past 18 months.", "remediation": "Audit labels; document review per change.", "remediation_days": 60, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-HIPAA-001", "theme": "hipaa_specific", "severity": "critical", "title": "PHI breach not assessed under Breach Notification Rule", "description": "PHI exposure event 4 months ago; risk-of-compromise assessment per §164.402 not documented. Breach notification potentially required + missed.", "remediation": "Conduct retroactive assessment; if breach, notify per §164.404 + §164.406; document.", "remediation_days": 14, "applicable_frameworks": ["hipaa"]},
{"id": "F-HIPAA-002", "theme": "hipaa_specific", "severity": "critical", "title": "Security Risk Analysis not performed", "description": "HIPAA Security Rule §164.308(a)(1)(ii)(A) risk analysis not documented in past 24 months despite material system changes.", "remediation": "Conduct + document analysis; address top risks; calendar annual review.", "remediation_days": 60, "applicable_frameworks": ["hipaa"]},
{"id": "F-HIPAA-003", "theme": "hipaa_specific", "severity": "major", "title": "Encryption addressable spec not formally evaluated", "description": "HIPAA encryption is 'addressable'; organization not encrypting PHI at rest in one data store; no documented analysis of why.", "remediation": "Document analysis; if not encrypted, implement alternative protective measure or encrypt.", "remediation_days": 90, "applicable_frameworks": ["hipaa"]},
{"id": "F-HIPAA-004", "theme": "hipaa_specific", "severity": "major", "title": "Workforce sanctions policy not enforced", "description": "§164.308(a)(1)(ii)(C) sanctions policy documented but no recorded sanctions despite repeat policy violations.", "remediation": "Apply sanctions per policy; document; refresh training.", "remediation_days": 60, "applicable_frameworks": ["hipaa"]},
{"id": "F-NIS2-001", "theme": "nis2_specific", "severity": "critical", "title": "Incident notification 24h early warning missed", "description": "NIS2 Article 23 24-hour early warning to competent authority + CSIRT not provided after recent significant incident.", "remediation": "File retrospectively; document delay rationale; engage authority; update IR procedure.", "remediation_days": 7, "applicable_frameworks": ["nis2"]},
{"id": "F-NIS2-002", "theme": "nis2_specific", "severity": "critical", "title": "Management body not approving cybersecurity measures", "description": "NIS2 Article 20 requires management bodies to approve cybersecurity risk-management measures + oversee implementation. Approval missing from board minutes.", "remediation": "Add to board agenda; document approval; ongoing oversight cadence.", "remediation_days": 60, "applicable_frameworks": ["nis2"]},
{"id": "F-NIS2-003", "theme": "nis2_specific", "severity": "major", "title": "10 minimum cybersecurity measures incomplete", "description": "NIS2 Article 21(2)(a)-(j) 10 minimum measures: 2 not documented (policies on cryptography, basic cyber hygiene).", "remediation": "Document missing policies; verify implementation; submit registration update.", "remediation_days": 90, "applicable_frameworks": ["nis2"]},
{"id": "F-CSF-001", "theme": "csf_specific", "severity": "major", "title": "NIST CSF profile not defined", "description": "Organization adopts NIST CSF 2.0 conceptually but no documented profile (current + target state) per CSF practice.", "remediation": "Develop profile; identify gaps; roadmap.", "remediation_days": 90, "applicable_frameworks": ["nist_csf"]},
{"id": "F-CSF-002", "theme": "csf_specific", "severity": "minor", "title": "Recover function under-developed", "description": "CSF GOVERN + IDENTIFY + PROTECT + DETECT + RESPOND well-developed; RECOVER function lacks documented recovery planning.", "remediation": "Develop recovery planning + communications procedures.", "remediation_days": 90, "applicable_frameworks": ["nist_csf", "iso_27001"]},
{"id": "F-AC-011", "theme": "access_control", "severity": "major", "title": "Service accounts without rotation", "description": "Service-account credentials shared across systems; no rotation in past 24 months.", "remediation": "Rotate; introduce secrets-management tooling; document.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa", "nis2"]},
{"id": "F-AC-012", "theme": "access_control", "severity": "major", "title": "Privileged access logs not reviewed", "description": "Privileged user activity logs collected but no periodic review for anomalous behavior.", "remediation": "Define review cadence; assign reviewer; SIEM alerts for high-risk patterns.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-AC-013", "theme": "access_control", "severity": "minor", "title": "Break-glass account not monitored", "description": "Emergency break-glass account exists but its usage not monitored; could be used without trace.", "remediation": "Alert on break-glass usage; quarterly review.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa"]},
{"id": "F-AI-006", "theme": "asset_inventory", "severity": "major", "title": "Personal device access not inventoried", "description": "BYOD devices accessing corporate data not in asset inventory; mobile device management (MDM) coverage incomplete.", "remediation": "Inventory BYOD; require MDM enrollment; document policy.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-AI-007", "theme": "asset_inventory", "severity": "major", "title": "Shadow IT discovered during audit", "description": "5 SaaS tools in use by teams without procurement / security review; some handle personal data.", "remediation": "Bring shadow IT under management or sunset; revise procurement gate.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "gdpr", "hipaa", "nist_csf"]},
{"id": "F-AI-008", "theme": "asset_inventory", "severity": "observation", "title": "Inventory not integrated with CMDB", "description": "Asset inventory in spreadsheet; lacks integration with operational CMDB. Drift inevitable.", "remediation": "Integrate via API or migrate to CMDB-as-source-of-truth.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-RM-010", "theme": "risk_management", "severity": "major", "title": "AI bias risk not formally identified", "description": "AI risk register lacks systematic identification of bias risks across protected demographic categories.", "remediation": "Apply ISO 23894 risk identification methodology; bias testing per category; document.", "remediation_days": 90, "applicable_frameworks": ["iso_42001", "eu_ai_act"]},
{"id": "F-RM-011", "theme": "risk_management", "severity": "minor", "title": "Risk treatment costs not estimated", "description": "Risk treatment plans don't estimate implementation cost; cost/benefit analysis missing.", "remediation": "Add cost estimate field; quarterly review.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "nist_csf"]},
{"id": "F-SM-011", "theme": "supplier_management", "severity": "major", "title": "Critical vendor SOC 2 expired", "description": "Critical vendor's SOC 2 Type II report on file is 18 months old; current period not yet collected.", "remediation": "Request current report; if vendor delayed, document compensating evidence.", "remediation_days": 60, "applicable_frameworks": ["soc_2", "iso_27001"]},
{"id": "F-SM-012", "theme": "supplier_management", "severity": "minor", "title": "Vendor contact lists stale", "description": "Vendor security contact information stale; recent contact attempts bounced.", "remediation": "Refresh contact lists; verify quarterly.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "gdpr"]},
{"id": "F-IR-011", "theme": "incident_response", "severity": "major", "title": "Forensic data preservation not standard", "description": "Recent incidents lack forensic preservation of affected systems; impedes investigation.", "remediation": "Document forensic preservation procedure; train IR team.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-IR-012", "theme": "incident_response", "severity": "minor", "title": "External communications template missing", "description": "External communications for incidents drafted ad-hoc; no pre-approved templates.", "remediation": "Develop templates; legal + comms review; approve.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "gdpr"]},
{"id": "F-ML-008", "theme": "monitoring_logging", "severity": "major", "title": "Database query logging disabled", "description": "Production database query logging disabled for performance reasons; can't audit who queried what.", "remediation": "Enable query logging for sensitive tables; size storage; document trade-offs.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "gdpr", "nist_csf"]},
{"id": "F-ML-009", "theme": "monitoring_logging", "severity": "minor", "title": "Log timestamps not in standard timezone", "description": "Logs across systems use mix of local timezones + UTC; correlation difficult.", "remediation": "Standardize on UTC; document; backfill where feasible.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-CM-006", "theme": "change_management", "severity": "minor", "title": "Configuration drift not detected", "description": "Production configuration drift from documented baseline; no detection mechanism.", "remediation": "Deploy infrastructure-as-code drift detection; alert on deviations.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-CM-007", "theme": "change_management", "severity": "observation", "title": "Consider GitOps for change discipline", "description": "Some changes still applied imperatively; GitOps would enforce change-via-PR discipline.", "remediation": "Pilot GitOps for one infrastructure layer.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-BC-006", "theme": "business_continuity", "severity": "major", "title": "Single region deployment without DR plan", "description": "Production deployment in single AWS region; no documented multi-region or cross-region DR plan.", "remediation": "Define DR plan (cross-region replicas, runbooks); test.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2"]},
{"id": "F-BC-007", "theme": "business_continuity", "severity": "minor", "title": "Communications plan missing for major outage", "description": "BCP covers technical recovery but lacks customer + employee communication plan for major outage.", "remediation": "Develop communications plan; pre-approved templates; cascade.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "nis2"]},
{"id": "F-CT-006", "theme": "competence_training", "severity": "minor", "title": "Onboarding security training not within 30 days", "description": "Some new hires complete security training 60+ days after start; expected within 30 days.", "remediation": "Calendar reminders; manager accountability; track completion timeline.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "hipaa", "nist_csf"]},
{"id": "F-CT-007", "theme": "competence_training", "severity": "observation", "title": "Phishing simulation results trending up", "description": "Phishing simulation click-rate increasing; training content may not be effective.", "remediation": "Refresh training content; targeted training for repeat clickers.", "remediation_days": 120, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "nis2", "hipaa"]},
{"id": "F-DG-008", "theme": "data_governance", "severity": "major", "title": "Data classification policy applied unevenly", "description": "Data classification policy applied to engineering data stores but not marketing tools containing customer data.", "remediation": "Extend classification; train marketing.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "soc_2", "gdpr", "hipaa"]},
{"id": "F-DG-009", "theme": "data_governance", "severity": "minor", "title": "Pseudonymization not consistently applied", "description": "Pseudonymization documented for some pipelines; not consistently applied to analytics datasets containing personal data.", "remediation": "Audit analytics datasets; pseudonymize where lawful basis is analytics.", "remediation_days": 90, "applicable_frameworks": ["gdpr", "iso_42001"]},
{"id": "F-CR-006", "theme": "cryptography", "severity": "major", "title": "Keys stored alongside data", "description": "Encryption keys stored in same cloud account / region as encrypted data; compromise of one yields the other.", "remediation": "Move keys to dedicated KMS account; restrict access.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa"]},
{"id": "F-CR-007", "theme": "cryptography", "severity": "minor", "title": "Certificate expiration monitoring incomplete", "description": "Certificate expiration alerts configured for some endpoints; internal certificates lack monitoring.", "remediation": "Extend monitoring; centralize certificate inventory.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-SD-006", "theme": "secure_sdlc", "severity": "major", "title": "Secrets in source control", "description": "Code review uncovered API keys + DB credentials committed to git history.", "remediation": "Rotate exposed secrets; remove from history; install pre-commit hooks; train.", "remediation_days": 30, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa"]},
{"id": "F-SD-007", "theme": "secure_sdlc", "severity": "minor", "title": "Pull-request templates lack security checklist", "description": "PR templates exist but don't prompt security considerations (auth, input validation, secrets).", "remediation": "Add security checklist to template; train.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf"]},
{"id": "F-VM-006", "theme": "vulnerability_mgmt", "severity": "major", "title": "Penetration test recommendations untracked", "description": "Annual penetration test completed; 12 findings; tracking + closure of remediation not centralized.", "remediation": "Centralize tracking; assign owners; verify closure.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "soc_2", "nist_csf", "hipaa"]},
{"id": "F-VM-007", "theme": "vulnerability_mgmt", "severity": "observation", "title": "Consider bug bounty programme", "description": "External vulnerability discovery limited to annual pentest; bug bounty would broaden coverage.", "remediation": "Evaluate bug bounty platforms; pilot.", "remediation_days": 180, "applicable_frameworks": ["iso_27001", "nist_csf"]},
{"id": "F-PS-005", "theme": "physical_security", "severity": "minor", "title": "Clean desk policy not enforced", "description": "Clean desk policy documented but walkthrough found sensitive printouts on unattended desks.", "remediation": "Reinforce policy; periodic walkthroughs; train.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "hipaa"]},
{"id": "F-PS-006", "theme": "physical_security", "severity": "observation", "title": "Hardware disposal evidence incomplete", "description": "Hardware disposal documented for laptops; lacks evidence of certified destruction for storage media.", "remediation": "Use certified destruction service; collect certificates.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "hipaa", "nist_csf"]},
{"id": "F-DP-008", "theme": "data_protection_privacy", "severity": "major", "title": "DSAR response > 30 days", "description": "12 of 50 DSARs in past quarter responded after Article 12(3) 1-month SLA; no extension communicated.", "remediation": "Investigate process bottlenecks; resource appropriately; communicate extensions where needed.", "remediation_days": 60, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-009", "theme": "data_protection_privacy", "severity": "minor", "title": "Privacy notice version history missing", "description": "Privacy notice updated multiple times; no version archive; cannot demonstrate which notice was active when.", "remediation": "Archive past versions with date stamps.", "remediation_days": 60, "applicable_frameworks": ["gdpr"]},
{"id": "F-DP-010", "theme": "data_protection_privacy", "severity": "minor", "title": "Article 22 automated decisions not flagged", "description": "Automated decision-making (Article 22) used in credit decisions; data subjects not informed; human review not offered.", "remediation": "Add transparency; offer human review; document procedure.", "remediation_days": 60, "applicable_frameworks": ["gdpr", "eu_ai_act"]},
{"id": "F-DC-004", "theme": "documentation_control", "severity": "observation", "title": "Consider read-only published documents", "description": "Controlled documents stored as editable Google Docs; risk of unauthorized edit. Read-only PDF publishing would be stronger control.", "remediation": "Publish read-only PDFs; restrict editing to authors.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_13485", "iso_42001"]},
{"id": "F-IA-005", "theme": "internal_audit", "severity": "minor", "title": "Audit reports lack standard format", "description": "Audit reports vary in format across auditors; difficult to compare or trend.", "remediation": "Define standard report template.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2", "iso_13485"]},
{"id": "F-AIMS-006", "theme": "aims_specific", "severity": "major", "title": "AI model card missing", "description": "Production AI system lacks model card per Annex A.6.2.7. Documentation per Mitchell et al. (2019) pattern not produced.", "remediation": "Develop model card; publish internally; commit to update with retraining.", "remediation_days": 60, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIMS-007", "theme": "aims_specific", "severity": "minor", "title": "Datasheet for datasets not produced", "description": "Training datasets lack datasheet per Gebru et al. (2021) pattern; not satisfying Annex A.7.4 fully.", "remediation": "Develop datasheets per dataset; document provenance + composition + intended use.", "remediation_days": 90, "applicable_frameworks": ["iso_42001"]},
{"id": "F-AIA-006", "theme": "ai_act_specific", "severity": "major", "title": "Article 27 FRIA missing for public-sector deployer", "description": "Public-sector body deploying high-risk AI; Fundamental Rights Impact Assessment per Article 27 not performed.", "remediation": "Conduct FRIA; document; consult DPA where required.", "remediation_days": 60, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-007", "theme": "ai_act_specific", "severity": "minor", "title": "EU database registration pending", "description": "High-risk Annex III system not yet registered in EU database per Article 71.", "remediation": "Register; document.", "remediation_days": 30, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-008", "theme": "ai_act_specific", "severity": "critical", "title": "Substantial modification turns deployer into provider", "description": "Deployer substantially modified high-risk AI system; now operates as provider per Article 25(1) but did not assume provider obligations.", "remediation": "Document role change; assume provider obligations; conformity assessment.", "remediation_days": 30, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-13485-005", "theme": "qms_specific", "severity": "major", "title": "Design transfer evidence missing", "description": "Design transfer per Clause 7.3.8 not formally documented for recent product. Manufacturing operates with insufficient design records.", "remediation": "Compile transfer evidence; document training; verify capability.", "remediation_days": 60, "applicable_frameworks": ["iso_13485", "fda_qsr"]},
{"id": "F-13485-006", "theme": "qms_specific", "severity": "observation", "title": "Consider digital quality management system", "description": "QMS run on shared drives; eQMS would improve traceability + audit-readiness.", "remediation": "Evaluate eQMS vendors; pilot.", "remediation_days": 180, "applicable_frameworks": ["iso_13485", "fda_qsr"]},
{"id": "F-FDA-005", "theme": "fda_specific", "severity": "major", "title": "UDI compliance gaps", "description": "Some devices commercially distributed lack UDI labeling per 21 CFR 830.", "remediation": "Audit + label; submit to GUDID; document.", "remediation_days": 90, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-FDA-006", "theme": "fda_specific", "severity": "observation", "title": "Pre-submission strategy could leverage Q-sub", "description": "Product strategy proceeds toward 510(k) without leveraging FDA Q-Submission programme.", "remediation": "Consider Q-sub for novel aspects.", "remediation_days": 180, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-HIPAA-005", "theme": "hipaa_specific", "severity": "major", "title": "Workforce member access not minimum-necessary", "description": "Workforce access provisioned at role level rather than minimum-necessary per §164.502(b). Some members access PHI beyond their need.", "remediation": "Audit + tighten access; document minimum-necessary determination.", "remediation_days": 90, "applicable_frameworks": ["hipaa"]},
{"id": "F-HIPAA-006", "theme": "hipaa_specific", "severity": "minor", "title": "Notice of privacy practices outdated", "description": "Notice of privacy practices per §164.520 last updated 2 years ago; substantive policy changes not reflected.", "remediation": "Update notice; redistribute per requirement; document.", "remediation_days": 60, "applicable_frameworks": ["hipaa"]},
{"id": "F-NIS2-004", "theme": "nis2_specific", "severity": "major", "title": "Registration with competent authority pending", "description": "Organization meets NIS2 essential entity criteria but has not registered with national competent authority per Article 24.", "remediation": "Submit registration; document.", "remediation_days": 30, "applicable_frameworks": ["nis2"]},
{"id": "F-NIS2-005", "theme": "nis2_specific", "severity": "minor", "title": "Supply-chain security measures not documented", "description": "NIS2 Article 21(2)(d) supply-chain security measures not separately documented from generic supplier-management.", "remediation": "Document NIS2-specific supply-chain measures.", "remediation_days": 60, "applicable_frameworks": ["nis2"]},
{"id": "F-CSF-003", "theme": "csf_specific", "severity": "minor", "title": "CSF tiers not assigned", "description": "NIST CSF 2.0 implementation tiers (Partial / Risk Informed / Repeatable / Adaptive) not assigned per function.", "remediation": "Self-assess tiers; document; target tier.", "remediation_days": 90, "applicable_frameworks": ["nist_csf"]},
{"id": "F-MDR-001", "theme": "mdr_specific", "severity": "critical", "title": "EU MDR technical documentation gap", "description": "Technical documentation per Annex II/III lacks recent clinical-evaluation update; notified body audit imminent.", "remediation": "Update documentation immediately; engage notified body.", "remediation_days": 30, "applicable_frameworks": ["eu_mdr_745"]},
{"id": "F-MDR-002", "theme": "mdr_specific", "severity": "major", "title": "Person Responsible for Regulatory Compliance not appointed", "description": "EU MDR Article 15 PRRC role not formally appointed for the EU operations.", "remediation": "Appoint PRRC meeting Article 15(1)-(2) qualifications; document.", "remediation_days": 30, "applicable_frameworks": ["eu_mdr_745"]},
{"id": "F-MDR-003", "theme": "mdr_specific", "severity": "minor", "title": "PMCF reports lag schedule", "description": "Post-Market Clinical Follow-up reports not produced per agreed schedule.", "remediation": "Catch up; rebaseline schedule.", "remediation_days": 90, "applicable_frameworks": ["eu_mdr_745"]},
{"id": "F-14971-001", "theme": "risk_management_medical", "severity": "major", "title": "Risk management plan not updated for software change", "description": "ISO 14971 risk management plan + risk file not updated after material software change.", "remediation": "Update RMF; re-evaluate risks; document.", "remediation_days": 60, "applicable_frameworks": ["iso_14971", "iso_13485", "eu_mdr_745"]},
{"id": "F-14971-002", "theme": "risk_management_medical", "severity": "minor", "title": "Residual risk evaluation lacks acceptability criteria", "description": "Residual risk evaluated but acceptability criteria per ISO 14971 §7 not formally established.", "remediation": "Define acceptability criteria; document.", "remediation_days": 90, "applicable_frameworks": ["iso_14971", "iso_13485"]},
{"id": "F-MDR-004", "theme": "mdr_specific", "severity": "major", "title": "EUDAMED registration incomplete", "description": "EU MDR EUDAMED registration of device, manufacturer, or UDI elements incomplete despite mandatory data submission requirements.", "remediation": "Complete required EUDAMED modules; track future module activations.", "remediation_days": 60, "applicable_frameworks": ["eu_mdr_745"]},
{"id": "F-MDR-005", "theme": "mdr_specific", "severity": "minor", "title": "Vigilance reporting log incomplete", "description": "EU MDR vigilance reporting log per Article 87 has 3 entries past 15-day reporting timeline.", "remediation": "Investigate root cause; tighten internal SLA; train.", "remediation_days": 60, "applicable_frameworks": ["eu_mdr_745"]},
{"id": "F-14971-003", "theme": "risk_management_medical", "severity": "major", "title": "Production + post-production information feedback weak", "description": "ISO 14971 §9 requires production + post-production information be collected + analysed; current process only acts on customer complaints, missing field data + service trends.", "remediation": "Expand information sources; document process; integrate with PMS.", "remediation_days": 90, "applicable_frameworks": ["iso_14971", "iso_13485", "eu_mdr_745"]},
{"id": "F-AIA-009", "theme": "ai_act_specific", "severity": "major", "title": "Deepfake content not marked AI-generated", "description": "Generative AI feature produces audio/video without machine-readable AI-generated marking per Article 50(2).", "remediation": "Implement watermarking; document.", "remediation_days": 60, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-AIA-010", "theme": "ai_act_specific", "severity": "minor", "title": "Instructions for use missing operational risks section", "description": "Article 13 instructions for use provided to deployers but do not adequately describe foreseeable operational risks.", "remediation": "Update IFU with risks + mitigations; train downstream.", "remediation_days": 60, "applicable_frameworks": ["eu_ai_act"]},
{"id": "F-FDA-007", "theme": "fda_specific", "severity": "major", "title": "Cybersecurity for connected device not addressed in 510(k)", "description": "Connected device 510(k) submission lacks cybersecurity content per FDA Cybersecurity Guidance (Sep 2023); FDA refused acceptance.", "remediation": "Develop cybersecurity content per guidance; resubmit.", "remediation_days": 90, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-FDA-008", "theme": "fda_specific", "severity": "minor", "title": "510(k) summary lacks comparative data", "description": "510(k) summary per 21 CFR 807.92 lacks substantive comparison to predicate device.", "remediation": "Add comparative data; resubmit if FDA requests.", "remediation_days": 60, "applicable_frameworks": ["fda_qsr"]},
{"id": "F-HIPAA-007", "theme": "hipaa_specific", "severity": "minor", "title": "Workforce member termination workflow missing PHI access revocation", "description": "Termination workflow revokes general access but doesn't specifically address PHI access systems; 2 terminated members retained EHR access > 2 days.", "remediation": "Add PHI-specific revocation step; verify.", "remediation_days": 30, "applicable_frameworks": ["hipaa", "iso_27001"]},
{"id": "F-MR-005", "theme": "management_review", "severity": "minor", "title": "Management review inputs not pre-distributed", "description": "Management review held but inputs distributed only at meeting; senior leadership cannot prepare in advance.", "remediation": "Pre-distribute inputs 1 week in advance.", "remediation_days": 60, "applicable_frameworks": ["iso_27001", "iso_42001", "iso_13485", "soc_2"]},
{"id": "F-IA-006", "theme": "internal_audit", "severity": "observation", "title": "Audit programme could integrate cross-framework findings", "description": "Audits performed per framework but cross-framework finding impact not systematically tracked; missed reuse opportunity.", "remediation": "Use compliance-os cross_framework_mapper output to tag findings.", "remediation_days": 90, "applicable_frameworks": ["iso_27001", "iso_42001", "soc_2", "iso_13485"]}
]
}
FILE:references/audit_simulation_methodology.md
# Audit Simulation Methodology — ISO 19011 + IIA IPPF + AICPA AT-C
This reference answers exactly one decision: **what does a realistic internal audit look like, and how do we generate a mock audit that prepares the team without breaking trust?**
Pair with `scripts/audit_simulator.py` for the deterministic mock audit generator.
## Why Simulate Audits?
External certification audits are high-stakes events. A team that has never been audited internally before its first stage 2 ISO certification audit will struggle even if every artefact is in place — interview cadence, document-pull SLAs, walk-through pacing are operational muscles built only by practice.
Mock audits provide:
- Operational practice (auditees experience the rhythm of an interview)
- Auditor-side practice (internal auditors practice their methodology before high-stakes certification audits)
- Discovery of gaps before they become findings
- Calibration of effort (how long does evidence assembly actually take?)
- Cross-training (auditors from one team learn another team's controls)
## Audit Standards That Govern Simulation
**ISO/IEC 19011:2018** — Guidelines for auditing management systems. Defines:
- Audit principles: integrity, fair presentation, due professional care, confidentiality, independence, evidence-based approach, risk-based approach
- Auditor competence (Clause 7)
- Audit process: initiating → preparing → conducting → reporting (Clauses 5–6)
**IIA International Professional Practices Framework (IPPF)** — internal-audit-specific:
- IPPF Standards 1000-1322 — Attribute Standards (purpose, independence, proficiency, due professional care, quality assurance)
- IPPF Standards 2000-2600 — Performance Standards (engagement planning through monitoring)
- Severity grading approach (rated finding scale)
**AICPA AT-C 105 + AU-C 240** — SOC 2 audit context: trust services criteria + auditor's responsibility framework.
## The Mock Audit Workflow
Compliance OS `audit_simulator.py` deterministically generates one stage of a mock audit. The full simulation lifecycle:
```
1. SCOPE → define framework + controls in scope + auditee team
2. PREPARE → audit_simulator.py outputs: findings + interview questions + document-review requests
3. CONDUCT → simulated interview + document review (1-2 hours per control)
4. REPORT → finding write-up + severity classification + corrective action assignment
5. CLOSE → corrective action tracking through CAPA
```
## Finding Severity Distribution (the IIA expectation)
A healthy compliance program produces audits with this distribution:
| Severity | Healthy proportion | What it indicates |
|---|---|---|
| **Critical (major nonconformity)** | ≤ 15% | Blocks certification; requires major corrective action |
| **Major** | 15–25% | Important gaps requiring 30-day corrective action plans |
| **Minor** | 20–30% | Operational gaps requiring corrective action timeline |
| **Observation / OFI** | ≥ 40% | Improvement opportunities; no required action |
**Why this shape?** If 80% of findings are critical, either the audit was destructive (auditee not given fair chance to demonstrate compliance) or the program is genuinely failing. If 80% of findings are observations, the audit was too superficial. The compliance OS audit simulator enforces this shape by deterministic severity rotation.
A first audit (year 1) will skew higher to critical/major; a mature program (year 3+) skews to observations.
## Number of Findings Per Audit
ISO 19011 Clause 6 typical audit depth:
- Small scope (5 controls, 1 day): 5–10 findings
- Medium scope (10–15 controls, 3–5 days): 10–20 findings
- Full system audit (all clauses, 1–2 weeks): 25–50 findings
The simulator targets 8–15 findings per audit (medium scope) as the default.
## Interview Question Quality
Auditor questions follow the **walk-through pattern**:
1. **Open** — "Walk me through how this control is implemented day-to-day."
2. **Sample** — "Show me a specific example from the last 30 days."
3. **Drill** — "What happens if [edge case]?"
4. **Verify** — "Where is this documented?"
Each control gets 3–5 questions following this pattern. The simulator's `interview_questions()` function provides theme-specific questions per the IIA performance standards.
## Document-Review Requests
Per ISO 19011, the auditor reviews:
- The procedure (the "what should happen")
- The records (the "what actually happened")
- The evidence of management oversight (the "did anyone check?")
A document-review request typically asks for all three. The simulator's `document_requests()` function generates the request list per theme.
## Auditor Independence Test
Clause 9.2 of ISO management-system standards requires auditor independence. The simulator does NOT enforce auditor assignment (that's `aims_audit_scheduler.py` for ISO 42001 or `isms_audit_scheduler.py` for ISO 27001) but the workflow assumes an independent auditor.
**Independence rules:**
- Auditor cannot audit their own work
- Auditor reports to a different chain of command than the auditee
- For small organizations, rotating auditors between teams + occasional external auditor satisfies independence
## Finding Categories (the taxonomy)
The simulator uses 5 finding themes mapped to common control families:
| Theme | Maps to control families |
|---|---|
| `access_control` | ISO 27001 A.5.15 / A.8.2 / A.8.3; SOC 2 CC6.1-6.3; ISO 42001 A.4.4 |
| `logging_monitoring` | ISO 27001 A.8.15 / A.8.16; SOC 2 CC7.1-7.2; ISO 42001 A.9.3 / A.9.4 |
| `change_management` | ISO 27001 A.8.32; SOC 2 CC8.1; ISO 42001 A.6.2.5 |
| `supplier_mgmt` | ISO 27001 A.5.19-A.5.22; SOC 2 CC9.2; ISO 42001 A.10.2; GDPR Art. 28 |
| `incident_response` | ISO 27001 A.5.24-27, A.6.8; SOC 2 CC7.3-7.5; ISO 42001 A.8.4; EU AI Act Art. 73; GDPR Art. 33-34 |
This taxonomy covers the highest-leverage controls across the 9 supported frameworks. Adding new themes is a matter of extending `FINDING_TEMPLATES` + `CONTROL_TO_THEME` mappings.
## Anti-Patterns in Audit Simulation
1. **Auditing for trapping vs auditing for evidence.** Mock audits aim to surface gaps, not embarrass the auditee. If team morale drops after the mock, the audit was structured wrong.
2. **Skipping the "obvious" controls.** Critical findings often hide in mundane controls (e.g., terminated employee with retained access). Simulator deliberately includes prosaic theme rotation.
3. **No prior-year follow-up.** The simulator's `prior_year_findings_open` parameter forces the first finding to be a follow-up. Real audits always follow up on prior open findings (ISO 19011 Clause 6.3).
4. **One severity-skewed audit.** Distribution rule guards against this; if all findings are critical or all are observations, recalibrate the audit scope or methodology.
## When This Reference Doesn't Help
- **Specific industry-vertical audit requirements.** Use sectoral skills (financial, healthcare).
- **Auditor competence + certification.** See ISACA CISA, IRCA Lead Auditor courses.
- **Audit report-writing detail.** See ISO 19011 Clause 6.5 + IIA performance standards 2410–2440.
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 19011:2018** — Guidelines for auditing management systems (the canonical methodology)
- **IIA International Professional Practices Framework (IPPF)** — Attribute Standards 1000-1322 + Performance Standards 2000-2600
- **AICPA AT-C 105** — Trust Services Criteria attestation engagement
- **AICPA AU-C 240** — Auditor's responsibilities relating to fraud (financial audit, conceptually applied)
- **ISACA CISA Review Manual** (27th ed., 2024) — IS audit practitioner methodology
- **ASQ Certified Quality Auditor (CQA) Body of Knowledge** — quality audit methodology
- **NIST SP 800-53A Rev 5** — Assessing Security and Privacy Controls (assessment procedures for each control)
- **ISO/IEC 17021-1:2015** — Conformity assessment requirements for bodies providing audit and certification
- **IRCA (International Register of Certificated Auditors)** — Lead auditor certification programme materials
- **The Open Group** — Open FAIR (Factor Analysis of Information Risk) for risk-based audit prioritization
FILE:references/compliance_os_pattern.md
# Compliance OS — The Meta-Framework Pattern
This reference answers exactly one decision: **when do we orchestrate frameworks vs run them separately, and what does the meta-framework architecture look like?**
## The Problem Compliance OS Solves
Most growing companies hit a wall: 2–3 compliance frameworks operating in parallel, each with its own tooling, its own audit calendar, its own evidence requirements, its own internal owner. The result:
- **Duplicate evidence collection** — access-review records assembled 3 times for ISO 27001, SOC 2, and ISO 42001 audits
- **Conflicting audit calendars** — surveillance audits stack in the same week with insufficient auditor capacity
- **Fragmented management review** — each framework wants its own management review, taking 5x the executive time
- **Inconsistent control taxonomies** — "access control" means slightly different things across SOC 2 and ISO 27001 Annex A and ISO 42001 Annex A
- **Unowned cross-framework gaps** — controls in framework A but not B fall to ad-hoc ownership
- **Evidence freshness mismatch** — ISO 27001 wants 12-month log retention, GDPR can want longer, leading to either over-retention or compliance gaps
Compliance OS is the orchestration layer that sits **above** per-framework skills and consolidates the cross-framework view.
## The Four Operations
```
[ Company Profile JSON ]
│
v
╔═══════════════════════╗
║ 1. CONFIGURE ║ framework_selector.py
║ "Which apply?" ║
╚═══════════════════════╝
│
v
╔═══════════════════════╗
║ 2. MAP ║ cross_framework_mapper.py
║ "What overlaps?" ║
╚═══════════════════════╝
│
v
╔═══════════════════════╗
║ 3. SIMULATE ║ audit_simulator.py
║ "What audit looks ║
║ like to fail?" ║
╚═══════════════════════╝
│
v
╔═══════════════════════╗
║ 4. CONSOLIDATE ║ evidence_pool_generator.py
║ "Where's the evidence║
║ + what reuses?" ║
╚═══════════════════════╝
│
v
[ Multi-framework plan ]
```
Each operation is a stdlib Python tool with deterministic logic — no LLM calls, no hidden state.
## When to Use Compliance OS
| Situation | Use compliance-os? |
|---|---|
| Single framework only (e.g., just SOC 2) | No — the per-framework skill is sufficient |
| 2+ frameworks operating in parallel | Yes |
| Adding a new framework to existing program | Yes — for cross-framework reuse mapping |
| Planning annual audit calendar across multiple certifications | Yes |
| Onboarding a new AI system that triggers ISO 42001 + EU AI Act + GDPR | Yes |
| Acquiring a company with different compliance posture | Yes — for gap mapping post-acquisition |
| Internal-audit-only program (no external certification) | Yes if multi-framework; No if single |
## What Compliance OS Is NOT
- **NOT a per-framework deep-dive skill.** Per-framework skills (`ra-qm-team/skills/iso42001-specialist/`, etc.) do the operational work. Compliance OS orchestrates them.
- **NOT a GRC platform replacement.** GRC platforms (Drata, Vanta, OneTrust, Hyperproof, etc.) are tools that operationalize what compliance OS describes — they're complementary. Compliance OS gives the conceptual map; GRC tools store the evidence.
- **NOT a binding legal opinion.** Cross-framework mappings reflect published guidance from ISO, AICPA, NIST, IIA, EDPB. Novel cross-walks need outside counsel.
- **NOT a certification body.** Certification audits are performed by accredited bodies. Compliance OS prepares for them.
## Roles and Ownership
A multi-framework compliance program typically has these roles. Compliance OS does not replace them — it gives them a shared mental model.
| Role | Owns |
|---|---|
| **Compliance officer** | The meta-program; framework selector; cross-framework mapper; consolidated evidence pool |
| **CISO** | ISO 27001 + SOC 2 + cybersecurity slices of ISO 42001 + GDPR Article 32 |
| **DPO** | GDPR; privacy slice of ISO 42001 (A.7.6); EU AI Act Article 27 FRIA where applicable |
| **AIMS lead** | ISO 42001; AI-specific slice of EU AI Act Article 17 QMS |
| **QMS lead** | ISO 13485 / FDA QSR / EU MDR 745 (medical-device contexts) |
| **Risk manager** | ISO 14971 + AI risk per ISO 23894 |
| **Internal auditor(s)** | Clause 9.2 audit programmes across all frameworks |
| **Executive sponsor** | Management review (Clause 9.3) across all frameworks |
A typical mid-stage AI SaaS has compliance officer + CISO + DPO as the core trio; AIMS lead is a part-time hat.
## The Integrated Management System Pattern
When multiple management-system standards apply (ISO 27001 + ISO 42001 + ISO 9001/13485 + ISO 14001), the recommended structure is an **Integrated Management System (IMS)** rather than parallel siloed systems. The IMS pattern:
- Single scope statement covering all applicable standards
- Single policy set with framework-specific overlays (e.g., the AI policy required by ISO 42001 A.2.2 sits alongside the info-sec policy required by ISO 27001 A.5.1)
- Single document control procedure
- Single internal audit programme covering all standards over a rolling 3-year cycle
- Single management review covering all standards
- Single CAPA loop with framework-tagged nonconformities
- Per-framework deep-dive evidence under common umbrella
Compliance OS is the operating model for the IMS pattern.
## How Compliance OS Relates to Sectoral Programs
| Sectoral context | Compliance OS approach |
|---|---|
| Pure SaaS (no AI, no medical) | Skip compliance-os. Use ISO 27001 + SOC 2 + GDPR skills directly. |
| AI SaaS (EU users) | Use compliance-os. Frameworks: ISO 27001 + SOC 2 + ISO 42001 + EU AI Act + GDPR. |
| AI medical device | Use compliance-os. Frameworks: ISO 13485 + 14971 + 42001 + EU AI Act + EU MDR / FDA QSR + GDPR. Most complex case. |
| Financial / regulated industry | Use compliance-os + sectoral overlay (e.g., NYDFS, FINMA, NIS2). |
## Anti-Patterns to Avoid
1. **Building compliance-os before having ≥ 2 frameworks operating maturely.** Premature orchestration. Mature one framework first; layer the second; THEN orchestrate.
2. **Using compliance-os to bypass per-framework deep work.** The cross-framework mapping says "reuse evidence from framework A." That presumes framework A's evidence is solid. Reuse mapping ≠ skip diligence.
3. **Treating mapping confidence as binary.** HIGH confidence means same evidence; MEDIUM means existing evidence with overlay; LOW means concept overlap. LOW mappings still need new artefacts.
4. **Forgetting that bindings (regulations) outrank certifications.** GDPR + EU AI Act non-compliance carries actual penalties; ISO 27001 non-certification just blocks procurement. Sequence accordingly.
5. **Replacing the per-framework skill with compliance-os.** Compliance OS orchestrates; per-framework skills do the deep work.
## When This Reference Doesn't Help
- **Specific framework requirements.** See the per-framework skill.
- **GRC platform selection.** Tooling decision; commercial market evolves rapidly.
- **Per-sector regulatory deep-dive.** Use sectoral skills (financial, healthcare, etc.).
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 19011:2018** — Guidelines for auditing management systems (the canonical audit standard for ISO-family certifications)
- **IIA International Professional Practices Framework (IPPF)** — Internal Audit Standards (Standards 1000-2600); attribute + performance standards
- **AICPA AT-C 105 + AU-C 240** — Trust Services + auditor's responsibility framework (SOC 2 + financial audit overlap)
- **COSO Enterprise Risk Management 2017** — Integrated framework for risk management across the enterprise
- **NIST Cybersecurity Framework 2.0** — profile pattern for organizing security/risk programmes (precedent for compliance-os approach)
- **ISO/IEC 27001:2022** — Information security management (foundational management system for most compliance programs)
- **ISO/IEC 17021** — Conformity assessment requirements (governs certification bodies; informs audit cycle)
- **ISACA** — *Auditing Artificial Intelligence* (2nd ed., 2024) — multi-framework AI audit guidance
- **ENISA** — *Multilayer Framework for Good Cybersecurity Practices for AI* (Mar 2023) — multi-layer integration
- **Annex SL of the ISO/IEC Directives** (2024) — the high-level structure shared by management system standards enabling integration
FILE:references/cross_framework_overlap.md
# Cross-Framework Overlap — The 9-Framework × Control-Family Matrix
This reference answers exactly one decision: **for each common control family, which of the 9 supported frameworks address it, and at what confidence?**
Pair with `scripts/cross_framework_mapper.py` for the deterministic lookup.
## The 9 Frameworks
| ID | Standard | Type |
|---|---|---|
| iso_27001 | ISO/IEC 27001:2022 + Annex A | Certifiable management system (info-sec) |
| iso_13485 | ISO 13485:2016 | Certifiable management system (medical device QMS) |
| iso_42001 | ISO/IEC 42001:2023 | Certifiable management system (AIMS) |
| iso_14971 | ISO 14971:2019 | Process standard (medical device risk management) |
| eu_ai_act | Regulation (EU) 2024/1689 | Binding regulation (AI) |
| eu_mdr_745 | Regulation (EU) 2017/745 | Binding regulation (medical devices) |
| gdpr | Regulation (EU) 2016/679 | Binding regulation (privacy) |
| soc_2 | AICPA SOC 2 TSC | Attestation (US enterprise procurement) |
| fda_qsr | FDA 21 CFR 820 | Binding regulation (US medical devices) |
## Highest-Overlap Pairs (where reuse leverage is maximized)
1. **ISO 27001 ↔ SOC 2** — densest known overlap. ISO 27001:2022 Annex A 93 controls map to SOC 2 TSC ~75% by published cross-walks. The 19 merged controls in `cross_framework_mapper.py` cite 51 atomic ISO 27001 + 34 atomic SOC 2 controls in HIGH-confidence themes. Adding SOC 2 on top of certified ISO 27001 is typically ~3 months of incremental work.
2. **ISO 13485 ↔ FDA QSR** — harmonised in 2024 (FDA Quality Management System Regulation rule). Most evidence reuses.
3. **ISO 42001 ↔ ISO 27001** — 60% reuse: most Clauses 4–10 evidence transfers with AI scope appended; Annex A controls A.7 (data) + A.10 (third-party) overlap heavily; the 40% net-new is mostly A.5 (impact assessment) + A.6 (lifecycle) + A.9 (use of AI systems).
4. **EU AI Act Article 17 ↔ ISO 42001** — ISO 42001 satisfies most of Article 17(1)(a)–(m) QMS requirements. The cross-walk in `compliance-team-iso42001/references/cross_framework_mapping_ai.md` provides Article 17 line-item mapping.
5. **GDPR ↔ ISO 27001 Annex A.5.34** — privacy by design overlap; GDPR Article 32 technical and organizational measures maps to ISO 27001 cryptography (A.8.24) + access control (A.5.15) + incident response (A.5.24).
## Control Family Overlap Matrix (summary)
Legend: ✅ direct overlap; 🔶 partial overlap with overlay; ⚠️ concept overlap only; ⛔ not applicable.
| Control family | 27001 | 13485 | 42001 | 14971 | EU AI Act | MDR | GDPR | SOC 2 | FDA QSR |
|---|---|---|---|---|---|---|---|---|---|
| Access control | ✅ | 🔶 | 🔶 | ⛔ | ⛔ | ⛔ | 🔶 | ✅ | 🔶 |
| Asset inventory | ✅ | ✅ | ✅ | ⛔ | ⛔ | ⛔ | 🔶 | ✅ | ✅ |
| Risk management | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 🔶 | ✅ | 🔶 |
| Supplier mgmt | ✅ | ✅ | ✅ | ⛔ | 🔶 | 🔶 | ✅ | ✅ | 🔶 |
| Incident response | ✅ | ✅ | 🔶 | 🔶 | 🔶 | ✅ | ✅ | ✅ | ✅ |
| Logging & monitoring | ✅ | 🔶 | 🔶 | ⛔ | 🔶 | 🔶 | ⚠️ | ✅ | 🔶 |
| Change management | ✅ | ✅ | 🔶 | ⛔ | ⛔ | ✅ | ⛔ | ✅ | ✅ |
| BCP / DR | ✅ | 🔶 | ⛔ | ⛔ | ⛔ | ⛔ | ⛔ | ✅ | ⛔ |
| Competence + training | ✅ | ✅ | ✅ | ⛔ | 🔶 | ✅ | ⛔ | ✅ | ✅ |
| Data governance | 🔶 | ✅ | ✅ | ⛔ | ✅ | ⚠️ | ✅ | ⚠️ | 🔶 |
| Internal audit | ✅ | ✅ | ✅ | ⛔ | ⛔ | 🔶 | ⛔ | ✅ | 🔶 |
| Management review | ✅ | ✅ | ✅ | ⛔ | ⛔ | 🔶 | ⛔ | 🔶 | ⛔ |
| Cryptography | ✅ | ⛔ | ⛔ | ⛔ | ⛔ | ⛔ | ✅ | ✅ | ⛔ |
| Secure SDLC | ✅ | ⛔ | 🔶 | ⛔ | 🔶 | ⛔ | ⛔ | ✅ | ⛔ |
| Vulnerability mgmt | ✅ | ⛔ | ⛔ | ⛔ | ⛔ | ⛔ | ⛔ | ✅ | ⛔ |
| Physical security | ✅ | ✅ | ⛔ | ⛔ | ⛔ | ✅ | ⛔ | ✅ | ✅ |
| Personal data protection | ✅ | ⛔ | 🔶 | ⛔ | 🔶 | ⛔ | ✅ | 🔶 | ⛔ |
| Documentation control | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 🔶 | ✅ | ✅ |
| Continual improvement / CAPA | ✅ | ✅ | ✅ | ✅ | ⛔ | ✅ | ⛔ | ✅ | ✅ |
## How to Use This Matrix
1. **Identify the union** of applicable frameworks (from `framework_selector.py`)
2. **For each control family**, find the row and read the columns for your frameworks
3. **Build evidence once** for the framework with the strongest requirement, then reuse-with-overlay for others
4. **Document the reuse mapping** in your compliance program documentation so auditors can trace evidence to framework controls
## Practical Reuse Sequencing
If you operate ISO 27001 (mature) and add a second framework:
| Add | Reuse leverage from 27001 |
|---|---|
| **SOC 2** | ~75% — heaviest reuse; the canonical pair |
| **ISO 42001** | ~60% — Clauses 4–10 reuse strong; Annex A.7/A.10 reuse strong; A.5/A.6/A.9 net-new |
| **GDPR** | ~50% — Article 32 organizational measures reuse; Articles 5/6/30 net-new privacy work |
| **EU AI Act** | ~40% — Article 17 QMS via ISO 42001 path; Articles 9/10 net-new; transparency net-new |
| **ISO 13485** | ~30% — document control + CAPA reuse; design controls + medical specifics net-new |
| **FDA QSR** | ~30% — via ISO 13485 path; sectoral overlay |
| **EU MDR 745** | ~25% — most net-new (technical documentation, clinical evidence, UDI) |
| **ISO 14971** | ~20% — process standard, integrates with 13485 |
## Confidence Levels Explained
The `cross_framework_mapper.py` returns one of three confidence levels per mapping:
- **HIGH (H)** — same evidence satisfies both framework controls without modification. Example: a quarterly access-review record satisfies ISO 27001 A.5.15 + SOC 2 CC6.1 simultaneously.
- **MEDIUM (M)** — existing evidence plus a framework-specific overlay. Example: ISO 27001 supplier-management procedure adapted to add AI-specific clauses for ISO 42001 A.10.2.
- **LOW (L)** — concept overlap only; new artefact required. Example: ISO 42001 A.5.2 impact assessment uses concepts from GDPR DPIA but is a separate artefact.
## When This Reference Doesn't Help
- **Specific atomic control numbers.** See the per-framework skill's references.
- **Sector-specific overlays.** See sectoral skills (financial, healthcare).
- **Audit simulation depth.** See `audit_simulation_methodology.md`.
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 27001:2022** + Annex A (the foundational pair source)
- **ISO/IEC 42001:2023** + Annex A
- **AICPA Trust Services Criteria** (2017 + 2022 update)
- **Regulation (EU) 2024/1689** (EU AI Act)
- **Regulation (EU) 2016/679** (GDPR)
- **Regulation (EU) 2017/745** (EU MDR)
- **ISO 13485:2016**
- **ISO 14971:2019**
- **FDA 21 CFR 820** (QSR) — harmonised under the FDA Quality Management System Regulation rule (effective 2026)
- **NIST SP 800-53 Rev 5** — security and privacy controls catalog (cross-walk reference)
- **NIST CSF 2.0** — profile pattern
- **ISACA** — *Mapping ISO 27001 to SOC 2* (continually updated)
- **CIS Controls v8** — additional cross-walk
- **CSA STAR** — cloud-specific cross-walk
FILE:references/evidence_artifact_reuse_index.md
# Evidence Artefact Reuse Index — Which Evidence Type Satisfies Most Controls Across Frameworks
This reference answers exactly one decision: **which evidence artefacts have the highest reuse leverage across the 12 supported frameworks, and what's the priority order for building them in a multi-framework programme?**
Pair with `scripts/evidence_pool_generator.py` for the operational catalogue. This document is the empirically-derived ranking + reasoning.
## Methodology
Reuse leverage = count of distinct (framework, control) tuples that one evidence artefact satisfies. Computed by tracing artefact-to-control mappings across:
- ISO/IEC 27001:2022 Annex A
- ISO/IEC 42001:2023 Annex A
- ISO 13485:2016 + ISO 14971:2019
- AICPA Trust Services Criteria (SOC 2)
- Regulation (EU) 2024/1689 (AI Act)
- Regulation (EU) 2017/745 (MDR)
- Regulation (EU) 2016/679 (GDPR)
- FDA 21 CFR 820 (QSR / QMSR)
- NIST Cybersecurity Framework 2.0
- Directive (EU) 2022/2555 (NIS2)
- HIPAA Security Rule + Privacy Rule + Breach Notification
For each evidence artefact, count of frameworks × controls satisfied = leverage score.
## The Top-Tier Artefacts (Build These First)
| Rank | Artefact | Reuse leverage | Acquisition cost | Why it's #1 |
|---|---|---|---|---|
| 1 | **Risk register with treatment plans** | 30+ mappings × 8+ frameworks | High | Every management-system standard + binding regulation demands risk management. Single artefact serves ISO 27001 Clause 6.1, ISO 42001 Clause 6.1.2, SOC 2 CC3, EU AI Act Article 9, GDPR Article 35 DPIA, NIST CSF GV.RM + ID.RA, NIS2 Article 21(2)(a), HIPAA §164.308(a)(1)(ii)(A) |
| 2 | **Asset inventory with classification** | 25+ mappings × 7+ frameworks | Medium | Required for ISO 27001 A.5.9-12, SOC 2 CC6.1, ISO 42001 A.4, GDPR Article 30, NIST CSF ID.AM, HIPAA §164.308 + §164.310(d). Foundation for almost every other artefact. |
| 3 | **Incident log + post-incident reviews + notifications** | 30+ mappings × 8+ frameworks | Medium | ISO 27001 A.5.24-27 + A.6.8, SOC 2 CC7.3-5, GDPR Articles 33-34, EU AI Act Article 73, NIS2 Article 23, HIPAA §164.308(a)(6) + Breach Notification, NIST CSF RS + RC |
| 4 | **Supplier inventory + reviews + DPAs/BAAs** | 25+ mappings × 8+ frameworks | Medium | ISO 27001 A.5.19-22, SOC 2 CC9.2, ISO 42001 A.10, GDPR Article 28, EU AI Act Article 25, NIST CSF GV.SC, NIS2 Article 21(2)(d), HIPAA §164.314(a) BAA |
| 5 | **Policy set (AI + info-sec + privacy + code-of-conduct)** | 20+ mappings × 7+ frameworks | Medium | ISO 27001 A.5.1, ISO 42001 Clause 5.2 + A.2.2-3, SOC 2 CC1.1-2, GDPR Article 24, NIST CSF GV.PO, EU AI Act Article 17(1)(a) |
## High-Leverage Artefacts (Build Next)
| Rank | Artefact | Reuse leverage | Acquisition cost | Notes |
|---|---|---|---|---|
| 6 | **Centralized tamper-evident logs** | 20+ mappings × 6+ frameworks | High | ISO 27001 A.8.15-16, SOC 2 CC7.1-2, ISO 42001 A.9.3-4, EU AI Act Article 12 + 72, NIST CSF DE.CM, HIPAA §164.312(b) audit controls |
| 7 | **Training records (per role, with effectiveness verification)** | 18+ mappings × 7+ frameworks | Medium | ISO 27001 A.6.3, SOC 2 CC1.4 + CC2.2, ISO 42001 Clause 7.2-3 + A.4.4, EU AI Act Article 4, NIST CSF PR.AT, NIS2 Article 21(2)(g), HIPAA §164.308(a)(5) |
| 8 | **Data inventory + provenance + consent register** | 20+ mappings × 6+ frameworks | High | ISO 27001 A.5.34, ISO 42001 A.7, EU AI Act Article 10, GDPR Articles 5+6+30, NIST CSF PR.DS + ID.AM-07, HIPAA §164.502 + §164.514 |
| 9 | **Internal audit programme records** | 15+ mappings × 6+ frameworks | Medium | ISO 27001 Clause 9.2, ISO 42001 Clause 9.2, ISO 13485 Clause 8.2.4, SOC 2 CC4.1, NIST CSF ID.IM, HIPAA §164.308(a)(8) |
| 10 | **Management review minutes + action tracking** | 12+ mappings × 5+ frameworks | Low | ISO 27001 Clause 9.3, ISO 42001 Clause 9.3, ISO 13485 Clause 5.6, NIST CSF GV.OV, NIS2 Article 20 |
## Mid-Leverage Artefacts
| Rank | Artefact | Reuse leverage | Acquisition cost | Notes |
|---|---|---|---|---|
| 11 | **Change records + rollback procedures + post-implementation reviews** | 14+ mappings × 5+ frameworks | Low | ISO 27001 A.8.32, SOC 2 CC8.1, ISO 42001 A.6.2.5, ISO 13485 Clause 7.3.9, NIST CSF PR.PS, HIPAA §164.308(a)(5)(ii)(B) |
| 12 | **Crypto records (algorithms, key lifecycle, KMS architecture)** | 14+ mappings × 6+ frameworks | Medium | ISO 27001 A.8.24, SOC 2 CC6.1 + CC6.7, GDPR Article 32(1)(a), NIST CSF PR.DS-01-02 + PR.PS-05, NIS2 Article 21(2)(h), HIPAA §164.312(a)(2)(iv) + §164.312(e)(2)(ii) |
| 13 | **BCP/DRP + RPO/RTO + exercise records** | 12+ mappings × 5+ frameworks | High | ISO 27001 A.5.29-30 + A.8.13-14, SOC 2 A1.2-3, NIST CSF RC.RP + RC.IM + RC.CO, NIS2 Article 21(2)(c), HIPAA §164.308(a)(7) |
| 14 | **DPIA records + LIAs + privacy notice version history** | 12+ mappings × 4+ frameworks | High | GDPR Articles 5+6+24+25+30+35+38, EU AI Act Article 27 FRIA (overlap), ISO 27001 A.5.34, ISO 42001 A.7.6 |
| 15 | **Quarterly access review records + RBAC matrix + JML evidence** | 18+ mappings × 7+ frameworks | Low | ISO 27001 A.5.15 + A.8.2-3, SOC 2 CC6.1-3, ISO 42001 A.4.4, GDPR Article 32(1)(b), NIST CSF PR.AA, NIS2 Article 21(2)(i), HIPAA §164.308(a)(3-4) + §164.312(a)(1) |
| 16 | **Vulnerability scan + patch SLA + remediation evidence** | 12+ mappings × 5+ frameworks | Medium | ISO 27001 A.8.7-9, SOC 2 CC7.1-2 + CC7.4, NIST CSF ID.RA + PR.PS-02, NIS2 Article 21(2)(f), HIPAA §164.308(a)(5)(ii)(B) |
## Low-Leverage (Framework-Specific) Artefacts
Build these only when the specific framework applies; lower reuse value across the programme.
| Artefact | Primary framework(s) | Why low-leverage |
|---|---|---|
| Annex IV technical documentation (EU AI Act) | EU AI Act | Specific to AI Act high-risk systems |
| Design History File (DHF) | ISO 13485, FDA QSR | Specific to medical-device QMS |
| Process validation (IQ/OQ/PQ) | ISO 13485, FDA QSR | Specific to medical-device manufacturing |
| Clinical evaluation (Annex XIV) | EU MDR | Specific to medical-device EU placement |
| Model card + datasheet | ISO 42001, EU AI Act | AI-specific |
| FRIA (Fundamental Rights Impact Assessment) | EU AI Act | Specific to high-risk AI public-sector deployers |
| Notice of Privacy Practices | HIPAA | Specific to US healthcare |
| Form 483 response records | FDA QSR | Specific to FDA-inspected entities |
| NIS2 incident notifications (24h/72h/1m) | NIS2 | Specific to NIS2-in-scope entities |
| EUDAMED registration | EU MDR | Specific to EU MDR |
## Reuse-Leverage Operational Pattern
For a multi-framework programme, the recommended build order is:
```
Phase 1 (Weeks 1-4):
- Risk register with treatment plans (top reuse)
- Asset inventory with classification
- Policy set
- Quarterly access review records + RBAC matrix
Phase 2 (Weeks 5-12):
- Centralized tamper-evident logs
- Supplier inventory + DPAs/BAAs
- Training records
- Crypto records
- Internal audit programme records
- Management review records
Phase 3 (Weeks 13-24):
- Data inventory + provenance + consent (build alongside Phase 1 if GDPR/HIPAA early)
- BCP/DRP + exercise records
- DPIA records
- Vulnerability scan + remediation
- Change records + rollback procedures
- Incident log + post-incident reviews
- Physical security records (if applicable)
Phase 4 (Weeks 25+):
- Framework-specific artefacts:
* Annex IV docs (if EU AI Act)
* DHF + process validation (if ISO 13485 / FDA QSR)
* Clinical evaluation (if EU MDR)
* Model cards + datasheets (if ISO 42001)
* FRIA (if EU AI Act public-sector deployer)
* Notice of Privacy Practices (if HIPAA)
```
## Common Mistakes (Anti-Patterns)
1. **Building framework-specific artefacts before top-tier reuse artefacts.** Common when team is led by a single-framework specialist; results in 5x more total effort across the programme.
2. **Separate evidence stores per framework.** Each framework wants the same access-review log; storing it 3 times in 3 systems = stale + inconsistent.
3. **Not citing the same artefact in multiple audit reports.** Different auditors may ask for the same evidence renamed; cite the shared artefact ID in both reports.
4. **Skipping centralized inventory in Phase 1.** Asset inventory is the foundation for risk register, supplier list, data inventory, etc. Without it, everything downstream is incomplete.
5. **Treating evidence as one-time collection rather than continuous artefact.** Quarterly access review records must be produced quarterly, not "fixed for the audit and then ignored".
## Evidence Freshness Discipline
Reuse leverage breaks down if evidence is stale. Per-artefact target freshness:
| Artefact | Refresh cadence | Stale = ineffective |
|---|---|---|
| Risk register | Quarterly minimum | Within 90 days |
| Asset inventory | Quarterly minimum | Within 90 days |
| Access review records | Quarterly | Within 1 quarter |
| Incident log + PIRs | Continuous + 30-day PIR | PIR within 30 days |
| Supplier reviews | Annually | Within 12 months |
| Training records | Annually + new-hire 30 days | Annual completion 100% |
| Policy set | Annually reviewed | Within 12 months |
| Crypto inventory | Quarterly review | Within 90 days |
| DPIA records | At new processing + on material change | Always current |
| BCP/DRP exercise records | Annually | Within 12 months |
## Anti-Reuse Patterns to Avoid
- **Per-framework reformatting** — collecting an artefact, then reformatting for each framework's report. Cite the shared artefact + map to framework controls instead.
- **Per-team ownership without integration** — security owns SOC 2 evidence, DPO owns GDPR evidence, RA/QM owns ISO 13485 evidence, no shared discovery layer. Use compliance-os meta-orchestrator to enforce shared inventory.
- **Custodial-only ownership** — artefact lives in one team's drive without index. New audit cycle re-discovers from scratch.
## When This Reference Doesn't Help
- **Specific GRC platform configuration.** Tooling decision; see vendor documentation.
- **Per-control evidence requirements.** See per-framework skill references.
- **Sector-specific evidence (financial NYDFS, energy NERC CIP).** Sectoral; not in 12-framework scope.
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 27001:2022** + Annex A
- **ISO/IEC 42001:2023** + Annex A
- **ISO/IEC 19011:2018** — Guidelines for auditing management systems (audit evidence)
- **AICPA Trust Services Criteria** (2017 + 2022 update) + SOC 2 Reporting Guide
- **Regulation (EU) 2024/1689** — AI Act
- **Regulation (EU) 2017/745** — EU MDR
- **Regulation (EU) 2016/679** — GDPR
- **Regulation (EU) 2022/2555** — NIS2 Directive
- **NIST Cybersecurity Framework 2.0** + NIST SP 800-53A Rev 5 assessment procedures
- **HIPAA 45 CFR Parts 160 + 164** — Security + Privacy + Breach Notification Rules
- **FDA 21 CFR 820** — Quality System Regulation
- **ISO 13485:2016** + ISO 14971:2019
- **IIA International Professional Practices Framework** — Performance Standards on engagement records (2330)
- **DAMA-DMBOK 2** — Data Management Body of Knowledge (provenance + quality dimensions)
- **NIST SP 800-92** — Guide to Computer Security Log Management (retention + integrity)
- **Industry retrospectives** — Big 4 + Schellman + Coalfire + A-LIGN published findings on common audit exceptions
FILE:references/evidence_management.md
# Evidence Management — Unified Pool + Reuse Leverage
This reference answers exactly one decision: **how do we collect compliance evidence once and satisfy multiple frameworks, without losing audit-grade traceability?**
Pair with `scripts/evidence_pool_generator.py` for the deterministic evidence catalogue.
## The Evidence Reuse Problem
Most multi-framework compliance programs accidentally collect the same evidence multiple times. Each framework's auditor wants:
- A documented procedure (the "what should happen")
- Records that the procedure was followed (the "what actually happened")
- Evidence of management oversight (the "did anyone check?")
When ISO 27001, SOC 2, and ISO 42001 audits ask for "access review records," teams often produce three different exports of the same Okta data with different formatting because three different control owners assembled them.
The fix: a **unified evidence pool** with explicit (artefact, framework, control) mapping. Collect once; cite multiple times.
## The Reuse-Leverage Score
Every evidence artefact gets a **reuse-leverage score** = number of distinct (framework, control) tuples it satisfies. Higher score = higher priority to build first.
From the `evidence_pool_generator.py` curated catalogue, the top-leverage artefacts (when all 9 frameworks are enabled):
| Artefact | Leverage |
|---|---|
| Risk register | 9+ mappings |
| Supplier inventory + reviews + DPAs | 8+ |
| Incident log + post-mortems + notifications | 11+ |
| Data inventory + provenance + consent | 9+ |
| Policy set (AI + info-sec + privacy + code-of-conduct) | 8+ |
| Tamper-evident logs centralized | 7+ |
| Training records | 6+ |
**Implementation order:** build high-leverage artefacts first. The risk register alone unlocks evidence for 9+ controls across 4+ frameworks.
## Evidence Acquisition Cost
The catalogue tracks acquisition cost per artefact: low / medium / high.
| Cost | Examples | Time to build |
|---|---|---|
| **Low** | Quarterly access review records, change records, management review records | 1-2 weeks (often automated from existing IT systems) |
| **Medium** | Asset register, supplier inventory, training records, crypto records, vuln scans | 2-6 weeks (requires inventory + classification) |
| **High** | Risk register, BCP/DR exercises, data inventory + consent register, secure SDLC | 6-12 weeks (requires cross-functional process design) |
**Strategy:** in year 1, prioritize low-cost high-leverage artefacts (e.g., management review records, change records). Build high-cost high-leverage artefacts in parallel (risk register, data inventory).
## Retention by Framework
Retention requirements vary per framework. Use the longest applicable retention:
| Framework | Typical retention |
|---|---|
| ISO 27001 | 3 years for audit evidence (or as policy specifies) |
| SOC 2 | 1 year minimum; 3 years recommended |
| ISO 42001 | 3 years (Clause 7.5 documented information) |
| EU AI Act | 10 years for declaration of conformity (Article 18); other docs 6 years |
| GDPR | Varies by data type; data subject records 3 years; breach records indefinite |
| ISO 13485 | Lifecycle of device + period defined by regulator (often 5+ years) |
| EU MDR | Device lifetime + 10 years (Article 10) |
| FDA QSR | 2 years past commercial distribution (21 CFR 820.180) |
**Default policy:** 36 months for most artefacts; 60 months for personal-data and policy-set artefacts; 120 months for EU AI Act declarations of conformity.
## Evidence Freshness
Auditors want recent evidence, not stale. Freshness expectations:
- Operational records (access reviews, change records, incident records): within last 90-180 days
- Quarterly artefacts: at least 1 record from current quarter
- Annual artefacts (training records, supplier reviews, BCP exercises): within last 12 months
- Policies: reviewed annually (review records demonstrate freshness)
**Stale evidence = effective gap.** An ISO 27001 A.5.15 quarterly access review that was last conducted 8 months ago is a major nonconformity even if the review existed historically.
## Evidence Owner Assignment
Each artefact has a primary owner. Typical pattern:
| Artefact type | Primary owner | Secondary |
|---|---|---|
| Access reviews | IT / Security | Compliance |
| Asset register | Security | DPO |
| Risk register | Compliance officer | Risk manager |
| Supplier inventory | Procurement | Compliance + DPO |
| Incident log | Security / IR team | Compliance |
| Logs (centralized) | Platform / SRE | Security |
| Change records | Engineering / Platform | Compliance |
| BCP/DR | Platform / SRE | Compliance |
| Training records | HR / People Ops | Compliance |
| Data inventory + consent | DPO / Data team | Engineering |
| Internal audit records | Compliance officer | Internal auditor |
| Management review records | Compliance officer + Exec | All function heads |
| Policy set | Compliance officer + Exec | All policy owners |
| Crypto records | Security | Platform |
| Vuln scans + patches | Security | Engineering |
**Single accountable owner per artefact** is critical. Joint ownership without accountability is the most common cause of stale evidence.
## Evidence Storage Architecture
Patterns observed in mature programs:
1. **GRC platform (Drata, Vanta, OneTrust, Hyperproof, etc.)** — the most common pattern; integrates with operational tools (Okta, AWS, GitHub) and auto-pulls evidence. Centralizes audit-trail.
2. **Compliance-team-managed repository** — folder per framework with subdivision per control; manual evidence assembly. Works for small programs; doesn't scale.
3. **Hybrid** — automated evidence (logs, access reviews, change records) in GRC platform; manual evidence (policies, management review minutes, training records) in document management system. Most common at growth-stage.
Compliance OS does not prescribe a storage pattern — but it does require:
- Single index of evidence (the unified pool)
- Per-evidence audit trail (who created, who approved, when)
- Per-evidence retention timer
- Per-evidence freshness alert
## Evidence Pool Quality Indicators
Healthy pool:
| Indicator | Healthy value |
|---|---|
| Average reuse leverage | ≥ 4 |
| Stale evidence (past expected freshness) | 0% |
| Orphan controls (no evidence assigned) | 0 |
| Unowned artefacts | 0 |
| Retention compliance | 100% |
Unhealthy pool:
- Many low-leverage artefacts (each satisfies only 1 framework) — likely silo'd collection
- High stale rate — operational discipline broken
- Orphan controls — gap in coverage that will surface at next audit
## Evidence Pool Audit (the meta-audit)
Once a year, audit the evidence pool itself:
1. Sample 10% of artefacts; verify they exist + are owned + are fresh
2. Sample 10% of controls; verify each has at least one evidence artefact assigned
3. Verify retention compliance — look for old evidence that should be deleted (GDPR retention) and recent evidence that should be retained longer
4. Verify framework coverage — are all enabled frameworks adequately represented?
This audit-of-audit is the most underappreciated discipline in mature multi-framework programs.
## When This Reference Doesn't Help
- **Specific GRC platform configuration.** Tooling-specific; market evolves rapidly.
- **Evidence retention for novel data types (e.g., AI training data).** Sector-specific; engage counsel.
- **Cross-framework specific mapping.** See `cross_framework_overlap.md`.
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 27001:2022 Clause 7.5** — Documented information requirements
- **ISO/IEC 42001:2023 Clause 7.5** — AI-specific documented information
- **AICPA AT-C 205** — Examination engagements (SOC 2 evidence standards)
- **NIST SP 800-53A Rev 5** — Assessing Security and Privacy Controls (per-control evidence types)
- **NIST SP 800-92** — Guide to Computer Security Log Management
- **ISO/IEC 19011:2018 Clause 6.4** — Conducting audit activities (evidence collection)
- **IIA IPPF Performance Standard 2330** — Documenting Information (engagement records)
- **GDPR Article 30** — Records of processing activities (retention + evidence)
- **EU AI Act Article 18** — Document retention (10 years post-market for declaration of conformity)
- **FDA 21 CFR 820.180** — General requirements for records (2 years past commercial distribution)
- **DAMA-DMBOK 2** — Data Management Body of Knowledge (data-quality + provenance frameworks)
FILE:references/multi_framework_audit_playbook.md
# Multi-Framework Audit Playbook — Orchestrating Audits Across N Frameworks
This reference answers exactly one decision: **when 2+ frameworks operate simultaneously, how do we run audits in coordinated cycles with minimal duplication?**
Pair with `scripts/audit_simulator.py` (multi-framework mock audits) + the per-framework audit playbooks (`isms-audit-expert/references/iso27001_audit_playbook.md`, `qms-audit-expert/references/iso13485_audit_playbook.md`, `gdpr-dsgvo-expert/references/gdpr_audit_playbook.md`, `soc2-compliance/references/soc2_audit_playbook.md`).
## The Multi-Framework Audit Problem
Mature multi-framework programs face four orchestration challenges:
1. **Audit calendar conflicts** — surveillance audits stacking in same week, insufficient auditor capacity
2. **Auditor independence across frameworks** — same internal auditor pulled to audit own work in a different framework
3. **Evidence freshness mismatch** — Audit A wants Q3 data; Audit B (3 months later) wants same control's Q3+Q4 data
4. **Finding cross-impact** — a critical finding in ISO 27001 audit triggers compensating questions in SOC 2 audit
This playbook describes the integrated audit programme (IAP) pattern that solves these.
## The Integrated Audit Programme
```
Annual Compliance Calendar
|
┌─────────────────────┼─────────────────────┐
| | |
Q1: ISO 27001 Q2: ISO 42001 Q3: ISO 13485
internal audit internal audit internal audit
(auditor pool A) (auditor pool B) (auditor pool A)
|
Q4: Integrated Management
Review (Clause 9.3 across
all frameworks)
|
External surveillance audits
scheduled by certification body
```
The IAP coordinates:
- **Single audit programme document** covering all applicable frameworks
- **Single auditor pool** with skill-based + independence-based assignment
- **Single evidence pool** (per `evidence_pool_generator.py`) so audits cite shared evidence
- **Single management review** (per Annex SL) covering all frameworks' Clause 9.3 inputs
## The 12-Month Calendar Pattern
A typical mid-stage AI SaaS running ISO 27001 + SOC 2 + ISO 42001 + GDPR + EU AI Act:
| Quarter | Activity | Frameworks audited internally |
|---|---|---|
| **Q1** | ISO 27001 internal audit + SOC 2 Type II observation begins | 27001 + SOC 2 |
| **Q2** | ISO 42001 internal audit + EU AI Act readiness checkpoint | 42001 + AI Act |
| **Q3** | GDPR annual review + SOC 2 mid-period checkpoint | GDPR + SOC 2 |
| **Q4** | Integrated management review + SOC 2 Type II field + cert body surveillance audits | all |
External audits (certification body + SOC 2 audit firm) typically:
- Q1: ISO 27001 surveillance audit (timed to follow Q1 internal audit)
- Q3: SOC 2 Type II field testing (timed for Q4 report)
- Q4: ISO 42001 surveillance audit (timed to follow Q2 + Q4 internal audits)
## Auditor Independence Across Frameworks
ISO management-system standards (Clause 9.2 across 27001 / 42001 / 13485) all require auditor independence: nobody audits their own work. With multiple frameworks running, independence must be tracked **across** frameworks, not just within.
**Pattern:** maintain an auditor competence + independence matrix:
| Auditor | Owns (cannot audit) | Competent to audit |
|---|---|---|
| Alice | 27001 A.5.15 (access control); 42001 A.4.4 | 27001 except A.5.15; 42001 except A.4.4; all GDPR; all SOC 2 |
| Bob | 42001 A.6 (lifecycle); 13485 7.3 (design) | 27001; GDPR; SOC 2 |
| Carol (external) | (none — independent contractor) | All frameworks |
| Dave | 27001 A.5.19 (suppliers); GDPR Article 28 | 27001 except A.5.19; 42001; SOC 2; 13485 |
Use `aims_audit_scheduler.py` (ISO 42001) + per-framework scheduler patterns to enforce independence.
## Cross-Framework Finding Impact
A finding in one framework's audit often affects another. Pattern:
- **ISO 27001 A.5.15 finding** → likely SOC 2 CC6.1 finding (same evidence)
- **ISO 27001 A.5.19-21 finding** → likely SOC 2 CC9.2 finding + GDPR Article 28 finding
- **ISO 42001 Annex A.7.6 finding** → likely GDPR Article 35 DPIA finding
- **ISO 13485 Clause 7.3 finding** → likely EU MDR Annex II finding
- **GDPR Article 33 breach** → triggers ISO 27001 A.5.24 audit + EU AI Act Article 73 review
**Discipline:** when a finding is issued, the issuing auditor flags cross-framework impact in the finding worksheet. The compliance officer reviews and triggers corresponding follow-up across frameworks.
## Shared Evidence Discipline
Per `evidence_management.md`, the evidence pool has unified artefacts. Audit work cites these artefacts, not framework-specific copies.
**Anti-pattern:**
```
ISO 27001 audit asks for: "ISO 27001 access review records Q3"
SOC 2 audit asks for: "SOC 2 access review records Q3"
Team produces TWO documents from same Okta export.
```
**Pattern:**
```
Both audits cite: "ev.access_review_quarterly Q3 2026" (single artefact)
Audit reports reference the shared artefact ID + framework-control mapping.
```
The audit report shows the auditor consulted the same evidence; framework-specific formatting happens in report assembly.
## Integrated Management Review (Clause 9.3 Across Frameworks)
Each management-system standard (27001, 42001, 13485, etc.) requires its own management review with prescribed inputs + outputs. Running 4 separate management reviews per year is unsustainable.
**Per Annex SL** (the high-level structure shared across ISO management-system standards), a single integrated management review can satisfy all of them if inputs cover every framework's prescribed list. Required inputs across the 5 most-common frameworks:
| Input | 27001 | 42001 | 13485 | 14001 | 9001 |
|---|---|---|---|---|---|
| Audit results | ✅ | ✅ | ✅ | ✅ | ✅ |
| Feedback from interested parties | ✅ | ✅ | ✅ | ✅ | ✅ |
| Risk + opportunity changes | ✅ | ✅ | ✅ | ✅ | ✅ |
| Performance of processes | ✅ | ✅ | ✅ | ✅ | ✅ |
| Nonconformities + CAPA | ✅ | ✅ | ✅ | ✅ | ✅ |
| Improvement opportunities | ✅ | ✅ | ✅ | ✅ | ✅ |
| AI-specific (drift, incidents, lifecycle) | — | ✅ | — | — | — |
| Customer feedback + complaints | — | ✅ | ✅ | — | ✅ |
| Resource needs | ✅ | ✅ | ✅ | ✅ | ✅ |
Outputs are similarly aligned: decisions on improvement, resource changes, scope adjustments, policy changes.
**Cadence:** annual minimum; quarterly preferred for mature multi-framework programs.
## Pre-Audit Readiness Checklist (per framework)
Universal pre-audit readiness (apply to each framework's internal audit):
- [ ] Scope confirmed (clauses + controls + business units in scope)
- [ ] Auditor independence verified (no self-audit; competence covers scope)
- [ ] Prior-year findings open list pulled + status reviewed
- [ ] Document evidence assembled in advance (auditor reads pre-fieldwork)
- [ ] Auditee leadership briefed; team availability confirmed
- [ ] Mock audit run via `audit_simulator.py` to surface likely findings
- [ ] Cross-framework impact considered (which findings might cascade)
- [ ] Audit plan circulated 2 weeks ahead
## Post-Audit Disciplines
- Findings logged in unified CAPA system (not framework-siloed)
- Corrective action owner named; due date agreed
- Cross-framework impact flagged in finding worksheet
- Closure verified by evidence + re-test (not self-attestation)
- Trend analysis monthly: aging CAPAs > 30 days, repeat findings across frameworks
- Inputs prepared for next management review
## When This Reference Doesn't Help
- **Single-framework deep audit detail.** See per-framework playbooks.
- **External certification body audit process.** Different from internal; see ISO 17021.
- **External SOC 2 audit firm engagement.** Different from internal; see `soc2_audit_playbook.md`.
- **Sectoral regulatory enforcement.** Out of scope; engage outside counsel.
---
**Source authorities (non-exhaustive):**
- **ISO/IEC 19011:2018** — Guidelines for auditing management systems
- **IIA International Professional Practices Framework (IPPF)** — Performance Standards 2000-2600
- **AICPA AT-C 105** — Attestation engagement standard (SOC 2)
- **ISO/IEC 27001:2022 Clause 9.2** — Internal audit programme
- **ISO/IEC 42001:2023 Clause 9.2** — Internal audit programme (AI management system)
- **ISO 13485:2016 Clause 8.2.4** — Internal audit (medical devices)
- **Regulation (EU) 2016/679 Article 24** — Accountability (GDPR — operational discipline for audit prep)
- **ISO 17021-1:2015** — Conformity assessment requirements (governs external certification audits; informs internal practice)
- **Annex SL of the ISO/IEC Directives** (2024) — high-level structure enabling integrated management systems
- **NIST SP 800-53A Rev 5** — Assessing Security and Privacy Controls (multi-framework assessment procedures)
- **The Institute of Internal Auditors** — practical guides on integrated audit programme design
FILE:scripts/audit_simulator.py
#!/usr/bin/env python3
"""audit_simulator.py — Mock internal audit generator per ISO 19011 + IIA IPPF.
Stdlib-only. Given a framework + scope, generates a realistic mock audit with:
- 8-15 finding scenarios per typical ISO 19011 audit depth
- Severity distribution matching IIA expectations:
observation/OFI: ≥ 40%
minor: 20-30%
major: 15-25%
critical: ≤ 15%
- 3-5 interview questions per scoped control
- Document-review request list
- Walk-through scenarios where applicable
Deterministic generation from finding templates. Severity distribution is
proportional to the scope size. No randomness, no LLM calls.
Input schema (JSON):
{
"audit_name": "Q3 ISO 27001 internal audit — Platform team",
"framework": "iso_27001",
"scope_controls": ["A.5.15", "A.8.2", "A.8.15", "A.8.32", "A.5.19"],
"auditee_team": "Platform engineering",
"prior_year_findings_open": 2
}
Usage:
python audit_simulator.py
python audit_simulator.py path/to/audit_scope.json
python audit_simulator.py audit_scope.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"audit_name": "Q3 ISO 27001 internal audit — Platform team",
"framework": "iso_27001",
"scope_controls": ["A.5.15", "A.8.2", "A.8.15", "A.8.32", "A.5.19", "A.5.24", "A.6.8"],
"auditee_team": "Platform engineering",
"prior_year_findings_open": 2,
}
# Finding template library (theme -> {severity bucket -> finding patterns})
# Each template produces a finding scenario when invoked.
FINDING_TEMPLATES: Dict[str, Dict[str, List[str]]] = {
"access_control": {
"critical": [
"Privileged access reviewed annually instead of quarterly; orphaned accounts found in production.",
],
"major": [
"Quarterly access review evidence present but lacks documented business justification for retained privileges.",
"Joiner-mover-leaver workflow does not auto-deprovision on termination; manual gap of 5+ days observed.",
],
"minor": [
"Access review records lack documented review-completion timestamps in 2 of 6 sampled reviews.",
],
"observation": [
"Consider extending RBAC matrix to include cloud-resource scope (currently application-tier only).",
],
},
"logging_monitoring": {
"critical": [
"Production application logs disabled in past 30 days; no detection of the gap until audit fieldwork.",
],
"major": [
"Log retention configured at 90 days but framework requires 12 months; misalignment not detected.",
"Tamper-evident logging not enforced on privileged-user activity logs.",
],
"minor": [
"Monitoring alert thresholds not formally documented; reviewed verbally by SRE only.",
],
"observation": [
"Centralized log aggregation in place; consider adding anomaly detection.",
],
},
"change_management": {
"critical": [
"Emergency change procedure not formalized; observed 3 cases of production changes without recorded approval.",
],
"major": [
"Change advisory board records show approvals but no post-implementation review of high-risk changes.",
],
"minor": [
"Rollback procedure documented but not tested for 2 services in scope.",
],
"observation": [
"Consider linking change records to deployment automation for stronger evidence chain.",
],
},
"supplier_mgmt": {
"critical": [
"Critical SaaS supplier in use without signed DPA + security questionnaire (GDPR exposure).",
],
"major": [
"Annual supplier security review not completed for 3 of 8 critical suppliers.",
"Sub-processor list not maintained for critical suppliers handling personal data.",
],
"minor": [
"Supplier onboarding checklist exists but not consistently applied across business units.",
],
"observation": [
"Consider centralizing supplier risk evidence in a single GRC system.",
],
},
"incident_response": {
"critical": [
"Recent P1 incident lacks documented post-incident review (PIR) within 30-day SLA.",
],
"major": [
"Severity definitions documented but inconsistently applied across teams; impact varies.",
"Notification SLAs not aligned across frameworks (GDPR 72h, framework X 24h, framework Y 15 days).",
],
"minor": [
"Incident commander rotation not documented.",
],
"observation": [
"Consider quarterly tabletop exercises to validate runbooks.",
],
},
}
# Control -> theme mapping (heuristic; deterministic)
CONTROL_TO_THEME: Dict[str, str] = {
# ISO 27001 mapping
"A.5.15": "access_control",
"A.8.2": "access_control",
"A.8.3": "access_control",
"A.5.19": "supplier_mgmt",
"A.5.20": "supplier_mgmt",
"A.5.21": "supplier_mgmt",
"A.5.22": "supplier_mgmt",
"A.5.24": "incident_response",
"A.5.25": "incident_response",
"A.5.26": "incident_response",
"A.5.27": "incident_response",
"A.6.8": "incident_response",
"A.8.15": "logging_monitoring",
"A.8.16": "logging_monitoring",
"A.8.32": "change_management",
# SOC 2 mapping
"CC6.1": "access_control",
"CC6.2": "access_control",
"CC6.3": "access_control",
"CC9.2": "supplier_mgmt",
"CC7.3": "incident_response",
"CC7.4": "incident_response",
"CC7.5": "incident_response",
"CC7.1": "logging_monitoring",
"CC7.2": "logging_monitoring",
"CC8.1": "change_management",
# ISO 42001 mapping
"A.4.4": "access_control",
"A.9.3": "logging_monitoring",
"A.9.4": "logging_monitoring",
"A.6.2.5": "change_management",
"A.10.2": "supplier_mgmt",
"A.8.4": "incident_response",
}
def _severity_rotation() -> List[str]:
return [
"observation", "observation", "observation", "minor", "major",
"observation", "minor", "observation", "major", "critical",
"minor", "observation", "minor", "observation", "major",
]
def generate_findings(payload: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate finding scenarios deterministically from scope."""
findings: List[Dict[str, Any]] = []
scope = payload.get("scope_controls", [])
prior_open = payload.get("prior_year_findings_open", 0)
# Rotate severities to hit IIA-target distribution
# Target: >= 40% observation, ~25% minor, ~20% major, <= 15% critical
severity_order = _severity_rotation()
# Pad if scope is large
while len(severity_order) < len(scope) + 5:
severity_order += severity_order
for idx, control in enumerate(scope):
theme = CONTROL_TO_THEME.get(control)
if theme is None:
continue
severity = severity_order[idx]
# If prior_open > 0, force first finding to be major (follow-up)
if idx == 0 and prior_open > 0:
severity = "major"
templates = FINDING_TEMPLATES.get(theme, {}).get(severity, [])
if not templates:
severity = "observation"
templates = FINDING_TEMPLATES.get(theme, {}).get("observation", ["General observation noted."])
finding_text = templates[idx % len(templates)]
findings.append({
"id": f"F-{idx + 1:02d}",
"control": control,
"theme": theme,
"severity": severity,
"description": finding_text,
"follow_up_from_prior": idx == 0 and prior_open > 0,
})
# Add 3-6 additional observations to hit 10-15 total range per ISO 19011 typical depth
extras_needed = max(0, 10 - len(findings))
extras_added = 0
for theme in FINDING_TEMPLATES:
if extras_added >= extras_needed:
break
if not any(f["theme"] == theme for f in findings):
continue
templates = FINDING_TEMPLATES[theme]["observation"]
findings.append({
"id": f"F-{len(findings) + 1:02d}",
"control": "(general)",
"theme": theme,
"severity": "observation",
"description": templates[(extras_added + 1) % len(templates)],
"follow_up_from_prior": False,
})
extras_added += 1
return findings
def interview_questions(control: str) -> List[str]:
"""Deterministic 3-5 audit interview questions per control theme."""
theme = CONTROL_TO_THEME.get(control)
bank = {
"access_control": [
"Walk me through how a new joiner gets access provisioned.",
"Show me the last quarterly access review evidence for a privileged role.",
"What happens within 24 hours of a termination?",
"How is multi-factor authentication enforced for admin access?",
],
"logging_monitoring": [
"Show me a sample log entry for a privileged action in the last 30 days.",
"What's the log retention configuration, and where is it documented?",
"How are tampering attempts detected and alerted?",
"Show me a monitoring alert that fired in the last 7 days and how it was triaged.",
],
"change_management": [
"Walk me through the change approval workflow for a production deployment.",
"Show me a rejected change in the last quarter and the rejection rationale.",
"Where is the rollback procedure for service X documented and last tested?",
"How are emergency changes handled differently from standard changes?",
],
"supplier_mgmt": [
"Show me the supplier inventory and the last review date for 3 critical suppliers.",
"How are AI-specific contractual clauses tracked for AI service suppliers?",
"Walk me through onboarding of a new critical SaaS supplier.",
"Show me where signed DPAs are stored for personal-data sub-processors.",
],
"incident_response": [
"Show me the last 3 incidents with severity, root cause, and corrective action.",
"Walk me through your serious-incident reporting timing for GDPR + AI Act.",
"Where are post-incident reviews documented and tracked to closure?",
"How is the on-call rotation defined and communicated?",
],
}
return bank.get(theme, [
"Walk me through how this control is implemented day-to-day.",
"Show me records of the control being operated in the last 90 days.",
"How is effectiveness of this control measured?",
])
def document_requests(scope: List[str]) -> List[str]:
themes = {CONTROL_TO_THEME.get(c) for c in scope if CONTROL_TO_THEME.get(c)}
docs = []
for t in themes:
if t == "access_control":
docs.append("Access control policy + last 2 quarterly access reviews + RBAC matrix")
elif t == "logging_monitoring":
docs.append("Logging policy + log retention configuration + last 30 days of sample privileged-action logs")
elif t == "change_management":
docs.append("Change management procedure + last 90 days change records + rollback procedure")
elif t == "supplier_mgmt":
docs.append("Supplier inventory + last annual supplier reviews + 3 sample DPAs")
elif t == "incident_response":
docs.append("Incident response procedure + last 5 incident records + post-incident reviews")
return docs
def analyze(payload: Dict[str, Any]) -> Dict[str, Any]:
findings = generate_findings(payload)
by_sev: Dict[str, int] = {"critical": 0, "major": 0, "minor": 0, "observation": 0}
for f in findings:
by_sev[f["severity"]] += 1
total = len(findings)
obs_pct = round((by_sev["observation"] / total) * 100, 1) if total else 0
crit_pct = round((by_sev["critical"] / total) * 100, 1) if total else 0
healthy = (obs_pct >= 40) and (crit_pct <= 15)
return {
"audit_name": payload.get("audit_name"),
"framework": payload.get("framework"),
"scope_controls": payload.get("scope_controls", []),
"auditee_team": payload.get("auditee_team"),
"findings_total": total,
"findings_by_severity": by_sev,
"severity_distribution_healthy": healthy,
"obs_pct": obs_pct,
"crit_pct": crit_pct,
"findings": findings,
"interview_questions_per_control": {c: interview_questions(c) for c in payload.get("scope_controls", [])},
"document_review_requests": document_requests(payload.get("scope_controls", [])),
}
def render_text(r: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("COMPLIANCE OS — MOCK INTERNAL AUDIT (per ISO 19011 + IIA IPPF)")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Audit: {r['audit_name']}")
lines.append(f"Framework: {r['framework']} | Auditee: {r['auditee_team']}")
lines.append(f"Scope controls ({len(r['scope_controls'])}): {', '.join(r['scope_controls'])}")
lines.append("")
s = r["findings_by_severity"]
lines.append(f"Findings total: {r['findings_total']} "
f"(critical={s['critical']}, major={s['major']}, minor={s['minor']}, observation={s['observation']})")
lines.append(f"Distribution: observation={r['obs_pct']}% critical={r['crit_pct']}% "
f"healthy={r['severity_distribution_healthy']}")
lines.append("")
lines.append("-" * 72)
lines.append("FINDINGS:")
lines.append("")
for f in r["findings"]:
marker = "🔥 FOLLOW-UP" if f["follow_up_from_prior"] else ""
lines.append(f" [{f['id']}] [{f['severity'].upper():12s}] control={f['control']:12s} theme={f['theme']:20s} {marker}")
lines.append(f" {f['description']}")
lines.append("")
lines.append("-" * 72)
lines.append("INTERVIEW QUESTIONS PER CONTROL:")
for ctrl, qs in r["interview_questions_per_control"].items():
lines.append(f" {ctrl}:")
for q in qs:
lines.append(f" - {q}")
lines.append("")
lines.append("-" * 72)
lines.append("DOCUMENT-REVIEW REQUESTS:")
for d in r["document_review_requests"]:
lines.append(f" - {d}")
lines.append("")
lines.append("-" * 72)
lines.append("HEALTHY-DISTRIBUTION RULE (IIA expectations):")
lines.append(" observation/OFI ≥ 40% AND critical ≤ 15%")
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(
description="Mock internal audit generator per ISO 19011 + IIA IPPF + AICPA AT-C.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to audit scope JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
payload = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
payload = SAMPLE
source = "<embedded sample: Q3 ISO 27001 internal audit, Platform team, 7 controls>"
result = analyze(payload)
if args.output == "json":
print(json.dumps({"source": source, **result}, indent=2))
else:
print(render_text(result, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/cross_framework_mapper.py
#!/usr/bin/env python3
"""cross_framework_mapper.py — Multi-framework control overlap computation.
Stdlib-only. Takes 1+ framework control libraries (control IDs + categories) and
computes overlap with mapping confidence (HIGH/MEDIUM/LOW) using a curated
ground-truth overlap dictionary distilled from published cross-walks:
- ISO 27001 Annex A <-> SOC 2 TSC (the densest known pair)
- ISO 27001 <-> ISO 42001 (info-sec reuse for AIMS)
- ISO 42001 <-> EU AI Act (Article 17 QMS satisfaction)
- GDPR <-> ISO 27001 (privacy controls overlap)
- ISO 13485 <-> FDA QSR (harmonised)
For each merged control, outputs the participating frameworks + a unified
evidence-requirement statement that satisfies all of them.
Deterministic ground-truth lookup. No LLM calls. No external dependencies.
Input schema (JSON):
{
"program": "Acme AI Inc. Compliance Program",
"enabled_frameworks": ["iso_27001", "soc_2", "iso_42001", "eu_ai_act", "gdpr"]
}
Usage:
python cross_framework_mapper.py # uses embedded 5-framework sample
python cross_framework_mapper.py path/to/program.json
python cross_framework_mapper.py program.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List, Set
SAMPLE: Dict[str, Any] = {
"program": "Acme AI Inc. Compliance Program",
"enabled_frameworks": [
"iso_27001", "soc_2", "iso_42001", "eu_ai_act", "gdpr",
"nist_csf", "nis2", "hipaa",
],
}
# Curated overlap database
# Each merged control: id, theme, evidence requirement, and per-framework mapping
# Mappings: framework_id -> (control_id, confidence)
# Confidence: H (high - same evidence satisfies), M (medium - evidence with overlay), L (low - concept overlap only)
MERGED_CONTROLS: List[Dict[str, Any]] = [
{
"id": "mc.access_control",
"theme": "Access control (identity, authentication, authorization)",
"evidence": "Documented access-control policy + access provisioning/de-provisioning procedure + quarterly access review records + RBAC matrix",
"mappings": {
"iso_27001": ("A.5.15 + A.8.2 + A.8.3", "H"),
"soc_2": ("CC6.1 + CC6.2 + CC6.3", "H"),
"iso_42001": ("A.4.4 (human resources for AI systems)", "M"),
"gdpr": ("Article 32(1)(b) integrity and confidentiality", "M"),
"nist_csf": ("PR.AA-01 + PR.AA-03 + PR.AA-05 (identities + authentication + authorization)", "H"),
"nis2": ("Article 21(2)(i) access control policies", "M"),
"hipaa": ("§164.308(a)(3) workforce security + §164.308(a)(4) information access management + §164.312(a)(1) access control", "H"),
},
},
{
"id": "mc.asset_inventory",
"theme": "Asset inventory and classification",
"evidence": "Asset register including AI systems + data classification scheme + ownership map",
"mappings": {
"iso_27001": ("A.5.9 + A.5.10 + A.5.12", "H"),
"soc_2": ("CC6.1 + CC3.2", "H"),
"iso_42001": ("A.4.2 (data) + A.4.3 (tooling)", "H"),
"gdpr": ("Article 30 (records of processing activities)", "M"),
"nist_csf": ("ID.AM-01 + ID.AM-02 + ID.AM-04 + ID.AM-05 (assets inventoried + classified)", "H"),
"nis2": ("Article 21(2)(b) policies on the use of risk-management measures (implicit: know your assets)", "M"),
"hipaa": ("§164.308(a)(1)(ii)(A) risk analysis (requires asset inventory) + §164.310(d) device + media controls", "M"),
},
},
{
"id": "mc.risk_management",
"theme": "Risk management process",
"evidence": "Risk methodology + risk register with severity matrix + risk treatment plan + residual-risk acceptance signoff",
"mappings": {
"iso_27001": ("Clause 6.1 + Clause 8.2", "H"),
"soc_2": ("CC3.1 + CC3.2 + CC3.4", "H"),
"iso_42001": ("Clause 6.1.2 + A.5", "H"),
"eu_ai_act": ("Article 9 (risk management system)", "M"),
"gdpr": ("Article 35 (DPIA where applicable)", "M"),
"nist_csf": ("GV.RM (risk management strategy) + ID.RA (risk assessment) + ID.IM (improvement)", "H"),
"nis2": ("Article 21(2)(a) risk analysis + Article 21(2)(b) policies on risk-management measures", "H"),
"hipaa": ("§164.308(a)(1)(ii)(A) risk analysis + §164.308(a)(1)(ii)(B) risk management", "H"),
},
},
{
"id": "mc.supplier_management",
"theme": "Third-party / supplier risk management",
"evidence": "Supplier inventory + due-diligence questionnaires + contractual security/privacy/AI clauses + periodic review records",
"mappings": {
"iso_27001": ("A.5.19 + A.5.20 + A.5.21 + A.5.22", "H"),
"soc_2": ("CC9.2", "H"),
"iso_42001": ("A.10.2 + A.10.6", "H"),
"eu_ai_act": ("Article 25 (responsibilities along the AI value chain)", "M"),
"gdpr": ("Article 28 (processor obligations)", "H"),
"nist_csf": ("GV.SC (cybersecurity supply chain risk management) + ID.SC", "H"),
"nis2": ("Article 21(2)(d) supply-chain security including security-related aspects of relationships with direct suppliers", "H"),
"hipaa": ("§164.308(b)(1) business associate contracts + §164.314(a) organizational requirements (BAAs)", "H"),
},
},
{
"id": "mc.incident_response",
"theme": "Incident response + notification",
"evidence": "Documented incident response procedure + severity definitions + escalation matrix + notification SLAs + post-incident reviews",
"mappings": {
"iso_27001": ("A.5.24 + A.5.25 + A.5.26 + A.5.27 + A.6.8", "H"),
"soc_2": ("CC7.3 + CC7.4 + CC7.5", "H"),
"iso_42001": ("A.8.4 (communication of AI incidents)", "M"),
"eu_ai_act": ("Article 73 (serious-incident reporting)", "M"),
"gdpr": ("Articles 33 + 34 (breach notification)", "H"),
"nist_csf": ("RS.MA + RS.AN + RS.RP + RS.CO (response: management, analysis, reporting, communication)", "H"),
"nis2": ("Article 23 incident notification (24h early warning / 72h notification / 1-month final report)", "H"),
"hipaa": ("§164.308(a)(6) security incident procedures + §164.400-414 Breach Notification Rule", "H"),
},
},
{
"id": "mc.monitoring_logging",
"theme": "Monitoring + logging",
"evidence": "Logging policy + tamper-evident logs + monitoring dashboards + retention compliant with longest applicable framework",
"mappings": {
"iso_27001": ("A.8.15 + A.8.16", "H"),
"soc_2": ("CC7.1 + CC7.2", "H"),
"iso_42001": ("A.9.3 + A.9.4", "M"),
"eu_ai_act": ("Article 12 (logging) + Article 72 (post-market monitoring)", "M"),
"nist_csf": ("DE.CM (continuous monitoring) + DE.AE (anomalies + events)", "H"),
"nis2": ("Article 21(2)(h) human resources security + ongoing monitoring expectations", "M"),
"hipaa": ("§164.308(a)(1)(ii)(D) information system activity review + §164.312(b) audit controls", "H"),
},
},
{
"id": "mc.change_management",
"theme": "Change management (system + model)",
"evidence": "Change approval workflow + version control + rollback procedure + change advisory board records",
"mappings": {
"iso_27001": ("A.8.32", "H"),
"soc_2": ("CC8.1", "H"),
"iso_42001": ("A.6.2.5 (deployment)", "M"),
"nist_csf": ("PR.PS (platform security including change-mgmt) + ID.IM-03 (improvements identified)", "H"),
"nis2": ("Article 21(2)(e) security in network and information systems acquisition, development and maintenance", "M"),
"hipaa": ("§164.308(a)(5)(ii)(B) protection from malicious software (implies controlled change) + §164.312(a)(1) access control during change", "M"),
},
},
{
"id": "mc.business_continuity",
"theme": "Business continuity and disaster recovery",
"evidence": "BCP/DRP documents + tested recovery objectives (RPO/RTO) + annual exercises + lessons learned",
"mappings": {
"iso_27001": ("A.5.29 + A.5.30 + A.8.13 + A.8.14", "H"),
"soc_2": ("A1.2 + A1.3", "H"),
"nist_csf": ("RC.RP (recovery planning) + RC.IM + RC.CO + ID.BE-05 (resilience requirements)", "H"),
"nis2": ("Article 21(2)(c) business continuity, such as backup management and disaster recovery, and crisis management", "H"),
"hipaa": ("§164.308(a)(7) contingency plan (incl. data backup + disaster recovery + emergency mode operation)", "H"),
},
},
{
"id": "mc.competence_training",
"theme": "Competence + awareness training",
"evidence": "Competence requirements per role + training plan + completion records + effectiveness verification",
"mappings": {
"iso_27001": ("A.6.3", "H"),
"soc_2": ("CC1.4 + CC2.2", "H"),
"iso_42001": ("Clause 7.2 + Clause 7.3 + A.4.4", "H"),
"eu_ai_act": ("Article 4 (AI literacy)", "M"),
"nist_csf": ("PR.AT (awareness + training)", "H"),
"nis2": ("Article 21(2)(g) basic cyber-hygiene practices and cybersecurity training", "H"),
"hipaa": ("§164.308(a)(5) security awareness and training", "H"),
},
},
{
"id": "mc.data_governance",
"theme": "Data governance + data quality",
"evidence": "Data inventory + provenance records + quality metrics + retention/deletion schedule + consent/lawful-basis records",
"mappings": {
"iso_27001": ("A.5.34 (privacy)", "M"),
"iso_42001": ("A.7 (full category)", "H"),
"eu_ai_act": ("Article 10 (data governance for high-risk)", "H"),
"gdpr": ("Articles 5 + 6 + 30", "H"),
"nist_csf": ("PR.DS (data security) + ID.AM-07 (data inventories) + GV.PO (policy)", "H"),
"nis2": ("Article 21(2)(j) policies and procedures (multi-factor + secure communications) implying data discipline", "M"),
"hipaa": ("§164.312(c)(1) integrity + §164.502 uses and disclosures of PHI + §164.514 de-identification", "H"),
},
},
{
"id": "mc.internal_audit",
"theme": "Internal audit programme",
"evidence": "Annual audit plan + auditor independence + findings tracking + closure verification",
"mappings": {
"iso_27001": ("Clause 9.2", "H"),
"soc_2": ("CC4.1", "H"),
"iso_42001": ("Clause 9.2", "H"),
"nist_csf": ("ID.IM (improvement processes including audits)", "M"),
"nis2": ("Article 21(2)(b) policies on the use of risk-management measures (implies periodic audit)", "M"),
"hipaa": ("§164.308(a)(1)(ii)(D) information system activity review + §164.308(a)(8) periodic evaluation", "H"),
},
},
{
"id": "mc.management_review",
"theme": "Management review",
"evidence": "Management review procedure + scheduled inputs + meeting records + action item tracking",
"mappings": {
"iso_27001": ("Clause 9.3", "H"),
"iso_42001": ("Clause 9.3", "H"),
"nist_csf": ("GV.OV (oversight) + GV.PO (organizational policy review)", "H"),
"nis2": ("Article 20 governance: management bodies must approve cybersecurity risk-management measures and oversee implementation", "H"),
"hipaa": ("§164.308(a)(2) assigned security responsibility + §164.308(a)(8) periodic evaluation by senior official", "M"),
},
},
{
"id": "mc.cryptography",
"theme": "Cryptography and key management",
"evidence": "Cryptographic policy + algorithm + key length standards + key rotation + HSM/KMS architecture + key custody records",
"mappings": {
"iso_27001": ("A.8.24", "H"),
"soc_2": ("CC6.1 + CC6.7", "H"),
"gdpr": ("Article 32(1)(a) pseudonymisation + encryption", "H"),
"nist_csf": ("PR.DS-02 (data-in-transit) + PR.DS-01 (data-at-rest) + PR.PS-05 (cryptography)", "H"),
"nis2": ("Article 21(2)(h) policies on the use of cryptography and, where appropriate, encryption", "H"),
"hipaa": ("§164.312(a)(2)(iv) encryption + decryption (addressable) + §164.312(e)(2)(ii) transmission encryption", "H"),
},
},
{
"id": "mc.secure_sdlc",
"theme": "Secure software development lifecycle",
"evidence": "Secure SDLC policy + threat modeling + code review records + SAST/DAST scanning + vulnerability triage",
"mappings": {
"iso_27001": ("A.8.25 + A.8.26 + A.8.27 + A.8.28 + A.8.29 + A.8.30 + A.8.31", "H"),
"soc_2": ("CC8.1 + CC7.1", "H"),
"iso_42001": ("A.6.2.2 + A.6.2.3 + A.6.2.4 (AI-specific SDLC)", "M"),
"nist_csf": ("PR.PS (platform security including secure development) + ID.RA-08 (vulnerabilities identified)", "H"),
"nis2": ("Article 21(2)(e) security in network and information systems acquisition, development and maintenance", "H"),
},
},
{
"id": "mc.vulnerability_mgmt",
"theme": "Vulnerability + patch management",
"evidence": "Vulnerability scanning schedule + patch SLAs by severity + exception tracking + remediation evidence",
"mappings": {
"iso_27001": ("A.8.7 + A.8.8 + A.8.9", "H"),
"soc_2": ("CC7.1 + CC7.2 + CC7.4", "H"),
"nist_csf": ("ID.RA-01 + ID.RA-08 (vulnerabilities) + PR.PS-02 (patching)", "H"),
"nis2": ("Article 21(2)(f) policies and procedures to assess the effectiveness of cybersecurity risk-management measures + vulnerability handling", "H"),
"hipaa": ("§164.308(a)(5)(ii)(B) protection from malicious software + §164.308(a)(1)(ii)(A) periodic risk analysis (covers vulnerability identification)", "M"),
},
},
{
"id": "mc.physical_security",
"theme": "Physical security and environmental controls",
"evidence": "Facility access controls + visitor log + environmental monitoring + tamper-evident seals on critical assets",
"mappings": {
"iso_27001": ("A.7.1 + A.7.2 + A.7.3 + A.7.4 + A.7.5 + A.7.6 + A.7.7 + A.7.8", "H"),
"soc_2": ("CC6.4 + CC6.5", "H"),
"nist_csf": ("PR.AA-06 (physical access) + PR.PS-04 (physical resource security)", "H"),
"hipaa": ("§164.310(a)(1) facility access controls + §164.310(b) workstation use + §164.310(c) workstation security + §164.310(d) device + media controls", "H"),
},
},
{
"id": "mc.data_protection_privacy",
"theme": "Personal data protection (privacy by design)",
"evidence": "Privacy policy + lawful-basis register + retention/deletion schedule + DPIA records + data-subject rights workflow + DPO appointment (where required)",
"mappings": {
"iso_27001": ("A.5.34", "H"),
"iso_42001": ("A.7.6 (data privacy considerations)", "M"),
"gdpr": ("Articles 5 + 6 + 24 + 25 + 30 + 35 + 38", "H"),
"nist_csf": ("GV.PO + PR.DS (data security)", "M"),
"hipaa": ("§164.502 uses and disclosures (Privacy Rule) + §164.520 notice of privacy practices + §164.530 administrative requirements", "H"),
},
},
{
"id": "mc.documentation_control",
"theme": "Documented information control",
"evidence": "Document control procedure + version control + approval workflow + retention + obsolete-doc handling",
"mappings": {
"iso_27001": ("Clause 7.5", "H"),
"soc_2": ("CC4.1 + CC5.1", "H"),
"iso_42001": ("Clause 7.5", "H"),
"nist_csf": ("GV.PO (policy + documentation) + ID.AM-08 (system and data are documented)", "H"),
"nis2": ("Article 21(1) documented cybersecurity risk-management measures", "H"),
"hipaa": ("§164.316 policies, procedures, and documentation requirements (retention 6 years)", "H"),
},
},
{
"id": "mc.continual_improvement",
"theme": "Continual improvement + CAPA",
"evidence": "Nonconformity tracking + root-cause analysis + corrective action plans + effectiveness verification + trend analysis",
"mappings": {
"iso_27001": ("Clause 10.1 + 10.2", "H"),
"soc_2": ("CC4.1 + CC4.2 + CC5.3", "H"),
"iso_42001": ("Clause 10.1 + 10.2", "H"),
"nist_csf": ("ID.IM-01 + ID.IM-02 + ID.IM-03 (improvements identified, evaluated, executed)", "H"),
"hipaa": ("§164.306(e) review + modify (security measures must be reviewed and modified as needed)", "M"),
},
},
]
def merged_in_scope(enabled: Set[str]) -> List[Dict[str, Any]]:
"""Return merged controls where at least 1 enabled framework maps to them."""
out: List[Dict[str, Any]] = []
for mc in MERGED_CONTROLS:
active_maps = {fid: m for fid, m in mc["mappings"].items() if fid in enabled}
if active_maps:
out.append({
"id": mc["id"],
"theme": mc["theme"],
"evidence": mc["evidence"],
"frameworks_count": len(active_maps),
"frameworks": active_maps,
})
return out
def overlap_summary(merged: List[Dict[str, Any]], enabled: Set[str]) -> Dict[str, Any]:
"""Compute per-framework coverage and per-pair overlap."""
coverage: Dict[str, int] = {f: 0 for f in enabled}
high_confidence: Dict[str, int] = {f: 0 for f in enabled}
for mc in merged:
for fid in mc["frameworks"]:
coverage[fid] += 1
_, conf = mc["frameworks"][fid]
if conf == "H":
high_confidence[fid] += 1
multi_framework = [mc for mc in merged if mc["frameworks_count"] >= 2]
high_reuse = [mc for mc in merged if mc["frameworks_count"] >= 3]
return {
"total_merged_controls_in_scope": len(merged),
"per_framework_coverage": coverage,
"per_framework_high_confidence": high_confidence,
"multi_framework_count": len(multi_framework),
"high_reuse_count_3plus_frameworks": len(high_reuse),
}
def analyze(payload: Dict[str, Any]) -> Dict[str, Any]:
enabled = set(payload.get("enabled_frameworks", []))
merged = merged_in_scope(enabled)
summary = overlap_summary(merged, enabled)
return {
"program": payload.get("program"),
"enabled_frameworks": sorted(enabled),
"summary": summary,
"merged_controls": sorted(merged, key=lambda m: -m["frameworks_count"]),
}
def render_text(r: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("COMPLIANCE OS — CROSS-FRAMEWORK CONTROL MAPPING")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Program: {r['program']}")
lines.append(f"Enabled frameworks ({len(r['enabled_frameworks'])}): {', '.join(r['enabled_frameworks'])}")
lines.append("")
s = r["summary"]
lines.append(f"Merged controls in scope: {s['total_merged_controls_in_scope']}")
lines.append(f"Multi-framework controls (≥ 2): {s['multi_framework_count']}")
lines.append(f"High-reuse controls (≥ 3 frameworks): {s['high_reuse_count_3plus_frameworks']}")
lines.append("")
lines.append("Per-framework coverage in merged catalogue:")
for fid in r["enabled_frameworks"]:
cov = s["per_framework_coverage"].get(fid, 0)
hi = s["per_framework_high_confidence"].get(fid, 0)
lines.append(f" {fid:15s} {cov} mappings ({hi} HIGH confidence)")
lines.append("")
lines.append("-" * 72)
lines.append("MERGED CONTROLS (sorted by reuse leverage):")
lines.append("")
for mc in r["merged_controls"]:
lines.append(f" [{mc['id']}] {mc['theme']} ({mc['frameworks_count']} frameworks)")
lines.append(f" Evidence: {mc['evidence']}")
for fid, (ctrl, conf) in mc["frameworks"].items():
conf_label = {"H": "HIGH ", "M": "MED ", "L": "LOW "}[conf]
lines.append(f" [{conf_label}] {fid:12s} -> {ctrl}")
lines.append("")
lines.append("-" * 72)
lines.append("CONFIDENCE LEGEND:")
lines.append(" HIGH — same evidence satisfies both (direct overlap)")
lines.append(" MED — existing evidence with overlay")
lines.append(" LOW — concept overlap; mostly new artefact required")
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(
description="Multi-framework control overlap computation.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to program JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
payload = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
payload = SAMPLE
source = "<embedded sample: ISO 27001 + SOC 2 + ISO 42001 + EU AI Act + GDPR>"
result = analyze(payload)
if args.output == "json":
print(json.dumps({"source": source, **result}, indent=2))
else:
print(render_text(result, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/evidence_pool_generator.py
#!/usr/bin/env python3
"""evidence_pool_generator.py — Consolidated evidence checklist across enabled frameworks.
Stdlib-only. Given a multi-framework compliance program config, produces a unified
evidence pool that maps each evidence artefact to all the (framework, control)
tuples it satisfies. Each artefact gets a reuse-leverage score = number of
distinct (framework, control) tuples satisfied.
Deterministic. No LLM calls. No external dependencies. Uses a curated evidence
catalogue distilled from ISO 27001, ISO 42001, SOC 2, GDPR, EU AI Act published
guidance.
Input schema (JSON):
{
"program": "Acme AI Inc. compliance program",
"enabled_frameworks": ["iso_27001", "soc_2", "iso_42001", "eu_ai_act", "gdpr"],
"audit_cycle_year": "year_1"
}
Usage:
python evidence_pool_generator.py
python evidence_pool_generator.py path/to/program.json
python evidence_pool_generator.py program.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"program": "Acme AI Inc. compliance program",
"enabled_frameworks": ["iso_27001", "soc_2", "iso_42001", "eu_ai_act", "gdpr"],
"audit_cycle_year": "year_1",
}
# Evidence catalogue: each artefact + the (framework, control) tuples it satisfies
# + acquisition cost (low / medium / high) + retention requirement (months)
EVIDENCE_CATALOG: List[Dict[str, Any]] = [
{
"id": "ev.access_review_quarterly",
"title": "Quarterly access review records (privileged + general access)",
"satisfies": [
("iso_27001", "A.5.15"), ("iso_27001", "A.8.2"), ("iso_27001", "A.8.3"),
("soc_2", "CC6.1"), ("soc_2", "CC6.2"), ("soc_2", "CC6.3"),
("iso_42001", "A.4.4"),
("gdpr", "Article 32(1)(b)"),
],
"acquisition_cost": "low",
"retention_months": 36,
"owner": "IT / Security",
},
{
"id": "ev.asset_register",
"title": "Asset register with AI systems + data classification",
"satisfies": [
("iso_27001", "A.5.9"), ("iso_27001", "A.5.10"), ("iso_27001", "A.5.12"),
("soc_2", "CC6.1"), ("soc_2", "CC3.2"),
("iso_42001", "A.4.2"), ("iso_42001", "A.4.3"),
("gdpr", "Article 30"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "Security / DPO",
},
{
"id": "ev.risk_register",
"title": "Risk register with severity matrix + treatment + residual signoff",
"satisfies": [
("iso_27001", "Clause 6.1"), ("iso_27001", "Clause 8.2"),
("soc_2", "CC3.1"), ("soc_2", "CC3.2"), ("soc_2", "CC3.4"),
("iso_42001", "Clause 6.1.2"), ("iso_42001", "A.5"),
("eu_ai_act", "Article 9"),
("gdpr", "Article 35"),
],
"acquisition_cost": "high",
"retention_months": 36,
"owner": "Compliance officer",
},
{
"id": "ev.supplier_inventory_reviews",
"title": "Supplier inventory + annual reviews + signed DPAs",
"satisfies": [
("iso_27001", "A.5.19"), ("iso_27001", "A.5.20"), ("iso_27001", "A.5.21"),
("soc_2", "CC9.2"),
("iso_42001", "A.10.2"), ("iso_42001", "A.10.6"),
("eu_ai_act", "Article 25"),
("gdpr", "Article 28"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "Procurement / Compliance",
},
{
"id": "ev.incident_log_postmortems",
"title": "Incident log + severity classifications + post-incident reviews + notifications sent",
"satisfies": [
("iso_27001", "A.5.24"), ("iso_27001", "A.5.25"), ("iso_27001", "A.5.26"),
("iso_27001", "A.5.27"), ("iso_27001", "A.6.8"),
("soc_2", "CC7.3"), ("soc_2", "CC7.4"), ("soc_2", "CC7.5"),
("iso_42001", "A.8.4"),
("eu_ai_act", "Article 73"),
("gdpr", "Article 33"), ("gdpr", "Article 34"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "Security / IR team",
},
{
"id": "ev.logs_aggregated",
"title": "Tamper-evident logs centralized with retention",
"satisfies": [
("iso_27001", "A.8.15"), ("iso_27001", "A.8.16"),
("soc_2", "CC7.1"), ("soc_2", "CC7.2"),
("iso_42001", "A.9.3"), ("iso_42001", "A.9.4"),
("eu_ai_act", "Article 12"),
],
"acquisition_cost": "high",
"retention_months": 12,
"owner": "Platform / SRE",
},
{
"id": "ev.change_records",
"title": "Change approval records + rollback procedure + post-implementation reviews",
"satisfies": [
("iso_27001", "A.8.32"),
("soc_2", "CC8.1"),
("iso_42001", "A.6.2.5"),
],
"acquisition_cost": "low",
"retention_months": 24,
"owner": "Engineering / Platform",
},
{
"id": "ev.bcp_dr_exercises",
"title": "BCP/DRP exercise records + RPO/RTO validation",
"satisfies": [
("iso_27001", "A.5.29"), ("iso_27001", "A.5.30"),
("iso_27001", "A.8.13"), ("iso_27001", "A.8.14"),
("soc_2", "A1.2"), ("soc_2", "A1.3"),
],
"acquisition_cost": "high",
"retention_months": 36,
"owner": "Platform / SRE",
},
{
"id": "ev.training_records",
"title": "Competence requirements per role + training completion + effectiveness verification",
"satisfies": [
("iso_27001", "A.6.3"),
("soc_2", "CC1.4"), ("soc_2", "CC2.2"),
("iso_42001", "Clause 7.2"), ("iso_42001", "Clause 7.3"),
("eu_ai_act", "Article 4"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "HR / People Ops",
},
{
"id": "ev.data_inventory_consent",
"title": "Data inventory + provenance + retention + consent / lawful-basis register",
"satisfies": [
("iso_27001", "A.5.34"),
("iso_42001", "A.7.2"), ("iso_42001", "A.7.3"), ("iso_42001", "A.7.4"),
("iso_42001", "A.7.5"), ("iso_42001", "A.7.6"),
("eu_ai_act", "Article 10"),
("gdpr", "Article 5"), ("gdpr", "Article 6"), ("gdpr", "Article 30"),
],
"acquisition_cost": "high",
"retention_months": 60,
"owner": "DPO / Data team",
},
{
"id": "ev.internal_audit_records",
"title": "Internal audit plan + auditor independence records + findings tracking",
"satisfies": [
("iso_27001", "Clause 9.2"),
("soc_2", "CC4.1"),
("iso_42001", "Clause 9.2"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "Compliance officer",
},
{
"id": "ev.management_review_records",
"title": "Management review schedule + meeting records + action item tracking",
"satisfies": [
("iso_27001", "Clause 9.3"),
("iso_42001", "Clause 9.3"),
],
"acquisition_cost": "low",
"retention_months": 36,
"owner": "Compliance officer + Exec",
},
{
"id": "ev.policy_set",
"title": "Policy set: AI, info-sec, privacy, code-of-conduct (signed + reviewed annually)",
"satisfies": [
("iso_27001", "A.5.1"),
("soc_2", "CC1.1"), ("soc_2", "CC1.2"),
("iso_42001", "Clause 5.2"), ("iso_42001", "A.2.2"), ("iso_42001", "A.2.3"),
("eu_ai_act", "Article 17(1)(a)"),
("gdpr", "Article 24"),
],
"acquisition_cost": "medium",
"retention_months": 60,
"owner": "Compliance officer + Exec",
},
{
"id": "ev.crypto_records",
"title": "Crypto policy + algorithm/key-length standards + key rotation records",
"satisfies": [
("iso_27001", "A.8.24"),
("soc_2", "CC6.1"), ("soc_2", "CC6.7"),
("gdpr", "Article 32(1)(a)"),
],
"acquisition_cost": "medium",
"retention_months": 36,
"owner": "Security",
},
{
"id": "ev.vuln_scans_patch",
"title": "Vulnerability scan results + patch SLAs + remediation evidence",
"satisfies": [
("iso_27001", "A.8.7"), ("iso_27001", "A.8.8"), ("iso_27001", "A.8.9"),
("soc_2", "CC7.1"), ("soc_2", "CC7.2"), ("soc_2", "CC7.4"),
],
"acquisition_cost": "medium",
"retention_months": 24,
"owner": "Security",
},
]
def filter_by_enabled(catalog: List[Dict[str, Any]], enabled: List[str]) -> List[Dict[str, Any]]:
"""Filter satisfaction tuples to enabled frameworks."""
enabled_set = set(enabled)
out = []
for ev in catalog:
active = [(f, c) for (f, c) in ev["satisfies"] if f in enabled_set]
if not active:
continue
leverage = len(active)
frameworks_satisfied = sorted({f for f, _ in active})
record = {**ev, "active_satisfaction": active, "reuse_leverage": leverage,
"frameworks_satisfied": frameworks_satisfied}
out.append(record)
out.sort(key=lambda x: (-x["reuse_leverage"], x["title"]))
return out
def analyze(payload: Dict[str, Any]) -> Dict[str, Any]:
enabled = payload.get("enabled_frameworks", [])
artefacts = filter_by_enabled(EVIDENCE_CATALOG, enabled)
total_satisfactions = sum(a["reuse_leverage"] for a in artefacts)
by_cost: Dict[str, int] = {"low": 0, "medium": 0, "high": 0}
by_owner: Dict[str, int] = {}
for a in artefacts:
by_cost[a["acquisition_cost"]] += 1
by_owner[a["owner"]] = by_owner.get(a["owner"], 0) + 1
# High-leverage artefacts (satisfy ≥ 5 mappings)
high_leverage = [a for a in artefacts if a["reuse_leverage"] >= 5]
return {
"program": payload.get("program"),
"enabled_frameworks": enabled,
"audit_cycle_year": payload.get("audit_cycle_year"),
"artefact_count": len(artefacts),
"total_satisfactions_across_artefacts": total_satisfactions,
"high_leverage_count": len(high_leverage),
"by_acquisition_cost": by_cost,
"by_owner": by_owner,
"artefacts": artefacts,
}
def render_text(r: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("COMPLIANCE OS — UNIFIED EVIDENCE POOL")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Program: {r['program']}")
lines.append(f"Enabled frameworks: {', '.join(r['enabled_frameworks'])}")
lines.append(f"Audit cycle phase: {r['audit_cycle_year']}")
lines.append(f"Artefacts in scope: {r['artefact_count']}")
lines.append(f"Total (framework, control) satisfactions: {r['total_satisfactions_across_artefacts']}")
lines.append(f"High-leverage artefacts (≥ 5 mappings): {r['high_leverage_count']}")
lines.append("")
lines.append(f"By acquisition cost: low={r['by_acquisition_cost']['low']} "
f"medium={r['by_acquisition_cost']['medium']} high={r['by_acquisition_cost']['high']}")
lines.append(f"By owner: {dict(r['by_owner'])}")
lines.append("")
lines.append("-" * 72)
lines.append("ARTEFACTS (sorted by reuse leverage — highest first):")
lines.append("")
for a in r["artefacts"]:
lines.append(f" [{a['id']}] {a['title']}")
lines.append(f" Leverage: {a['reuse_leverage']} mappings across {len(a['frameworks_satisfied'])} frameworks ({', '.join(a['frameworks_satisfied'])})")
lines.append(f" Owner: {a['owner']} | Cost: {a['acquisition_cost']} | Retention: {a['retention_months']} months")
lines.append(f" Satisfies:")
for fid, ctrl in a["active_satisfaction"]:
lines.append(f" - {fid:12s} -> {ctrl}")
lines.append("")
lines.append("-" * 72)
lines.append("REUSE-LEVERAGE GUIDANCE:")
lines.append(" Build high-leverage artefacts first (single evidence -> ≥ 5 framework controls).")
lines.append(" High-leverage examples (depend on enabled frameworks): risk register, supplier inventory, incident log,")
lines.append(" data inventory + consent, policy set, training records.")
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(
description="Unified evidence pool generator across compliance frameworks.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to program JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
payload = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
payload = SAMPLE
source = "<embedded sample: 5 enabled frameworks, year 1>"
result = analyze(payload)
if args.output == "json":
print(json.dumps({"source": source, **result}, indent=2))
else:
print(render_text(result, source))
return 0
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/framework_selector.py
#!/usr/bin/env python3
"""framework_selector.py — Multi-framework compliance applicability selector.
Stdlib-only. Takes a company profile and returns the applicable compliance frameworks
ranked by priority + dependency graph. Supports 9 frameworks:
- ISO 27001 (info-sec ISMS)
- ISO 13485 (medical device QMS)
- ISO 42001 (AI management system)
- ISO 14971 (medical device risk mgmt)
- EU AI Act (Regulation 2024/1689)
- EU MDR 2017/745 (medical device regulation)
- GDPR (Regulation 2016/679)
- SOC 2 (Trust Services Criteria)
- FDA QSR (21 CFR 820)
Deterministic decision tree. No LLM calls. No external dependencies.
Input schema (JSON):
{
"company": "Acme AI Inc.",
"industry": "saas", # saas | medical_device | financial | other
"products_include_ai": true,
"ai_high_risk_per_eu": true, # falls under Annex III, Article 6
"deploys_ai_in_eu": true,
"products_are_medical_devices": false,
"sells_to_eu_customers": true,
"sells_to_us_customers": true,
"sells_to_enterprise_b2b": true,
"processes_personal_data": true,
"processes_eu_personal_data": true,
"headcount": 80,
"stage": "series_b"
}
Usage:
python framework_selector.py # uses embedded mid-stage AI SaaS sample
python framework_selector.py path/to/profile.json
python framework_selector.py profile.json --output json
"""
import argparse
import json
import sys
from typing import Any, Dict, List
SAMPLE: Dict[str, Any] = {
"company": "Acme AI Inc.",
"industry": "saas",
"products_include_ai": True,
"ai_high_risk_per_eu": True,
"deploys_ai_in_eu": True,
"products_are_medical_devices": False,
"sells_to_eu_customers": True,
"sells_to_us_customers": True,
"sells_to_enterprise_b2b": True,
"processes_personal_data": True,
"processes_eu_personal_data": True,
"headcount": 80,
"stage": "series_b",
# Phase 3 additions (defaults false; sample profile does not trigger HIPAA / NIS2 / CSF)
"processes_phi": False,
"us_healthcare_covered_entity": False,
"us_healthcare_business_associate": False,
"nis2_essential_entity": False,
"nis2_important_entity": False,
"adopts_nist_csf": False,
"us_government_contractor": False,
}
# Framework catalogue (id, name, type, certifiable)
FRAMEWORKS = {
"iso_27001": {"name": "ISO/IEC 27001:2022", "type": "management_system", "certifiable": True, "binding": False},
"iso_13485": {"name": "ISO 13485:2016", "type": "management_system", "certifiable": True, "binding": False},
"iso_42001": {"name": "ISO/IEC 42001:2023", "type": "management_system", "certifiable": True, "binding": False},
"iso_14971": {"name": "ISO 14971:2019", "type": "process_standard", "certifiable": False, "binding": False},
"eu_ai_act": {"name": "Regulation (EU) 2024/1689 (AI Act)", "type": "regulation", "certifiable": False, "binding": True},
"eu_mdr_745": {"name": "Regulation (EU) 2017/745 (MDR)", "type": "regulation", "certifiable": False, "binding": True},
"gdpr": {"name": "Regulation (EU) 2016/679 (GDPR)", "type": "regulation", "certifiable": False, "binding": True},
"soc_2": {"name": "AICPA SOC 2 Trust Services", "type": "attestation", "certifiable": True, "binding": False},
"fda_qsr": {"name": "FDA 21 CFR 820 (QSR)", "type": "regulation", "certifiable": False, "binding": True},
# Phase 3 additions
"nist_csf": {"name": "NIST Cybersecurity Framework 2.0", "type": "framework_profile", "certifiable": False, "binding": False},
"nis2": {"name": "Directive (EU) 2022/2555 (NIS2)", "type": "regulation", "certifiable": False, "binding": True},
"hipaa": {"name": "HIPAA Security + Privacy + Breach Notification Rules", "type": "regulation", "certifiable": False, "binding": True},
}
# Dependency graph: framework X benefits from framework Y as prerequisite
DEPENDENCIES = {
"iso_42001": ["iso_27001"], # AIMS reuses ISMS heavily
"iso_13485": ["iso_14971"], # QMS uses risk mgmt
"eu_mdr_745": ["iso_13485", "iso_14971"],
"eu_ai_act": ["iso_42001"], # voluntary AIMS satisfies parts of Article 17
"soc_2": ["iso_27001"], # ISO 27001 controls map to SOC 2 TSC
"fda_qsr": ["iso_13485"], # QSR mostly harmonised with 13485
# Phase 3 additions
"nist_csf": [], # voluntary framework; no prereqs
"nis2": ["iso_27001"], # NIS2 risk-mgmt + reporting maps to 27001 controls
"hipaa": ["iso_27001"], # HIPAA Security Rule overlaps ISO 27001 Annex A
}
def select_frameworks(profile: Dict[str, Any]) -> List[str]:
selected: List[str] = []
# GDPR — any EU personal data
if profile.get("processes_eu_personal_data") or (
profile.get("processes_personal_data") and profile.get("sells_to_eu_customers")
):
selected.append("gdpr")
# ISO 27001 — enterprise B2B / mature SaaS
if profile.get("sells_to_enterprise_b2b") or profile.get("stage") in ("series_a", "series_b", "series_c", "growth"):
selected.append("iso_27001")
# SOC 2 — US enterprise B2B
if profile.get("sells_to_us_customers") and profile.get("sells_to_enterprise_b2b"):
selected.append("soc_2")
# ISO 42001 — any AI in products
if profile.get("products_include_ai"):
selected.append("iso_42001")
# EU AI Act — AI deployed in EU
if profile.get("products_include_ai") and (
profile.get("deploys_ai_in_eu") or profile.get("sells_to_eu_customers")
):
selected.append("eu_ai_act")
# ISO 13485 + 14971 — medical device
if profile.get("products_are_medical_devices"):
selected.append("iso_13485")
selected.append("iso_14971")
# EU MDR — medical device sold in EU
if profile.get("sells_to_eu_customers"):
selected.append("eu_mdr_745")
# FDA QSR — medical device sold in US
if profile.get("sells_to_us_customers"):
selected.append("fda_qsr")
# HIPAA — any US healthcare PHI processing
if profile.get("processes_phi") or profile.get("us_healthcare_covered_entity") or profile.get("us_healthcare_business_associate"):
selected.append("hipaa")
# NIS2 — operates in EU as essential or important entity per Annex I/II of Directive 2022/2555
if profile.get("nis2_essential_entity") or profile.get("nis2_important_entity"):
selected.append("nis2")
# NIST CSF — voluntary; recommended for any org with cybersecurity programme (esp. US gov-adjacent)
if profile.get("adopts_nist_csf") or profile.get("us_government_contractor"):
selected.append("nist_csf")
return selected
def annotate(profile: Dict[str, Any]) -> Dict[str, Any]:
selected = select_frameworks(profile)
# Build dependency notes
dep_notes: List[Dict[str, Any]] = []
for fid in selected:
deps = DEPENDENCIES.get(fid, [])
in_program = [d for d in deps if d in selected]
missing = [d for d in deps if d not in selected]
if in_program or missing:
dep_notes.append({
"framework": fid,
"satisfied_dependencies": in_program,
"missing_dependencies": missing,
})
# Priority ranking — bindings first, then certifiable, then reference
def priority(fid: str) -> int:
f = FRAMEWORKS[fid]
if f["binding"]:
return 0
if f["certifiable"]:
return 1
return 2
ranked = sorted(selected, key=priority)
return {
"company": profile.get("company"),
"industry": profile.get("industry"),
"applicable_frameworks": [
{"id": fid, **FRAMEWORKS[fid]} for fid in ranked
],
"framework_count": len(ranked),
"binding_count": sum(1 for fid in ranked if FRAMEWORKS[fid]["binding"]),
"certifiable_count": sum(1 for fid in ranked if FRAMEWORKS[fid]["certifiable"]),
"dependency_notes": dep_notes,
"rationale": _rationale(profile, ranked),
}
def _rationale(profile: Dict[str, Any], selected: List[str]) -> List[str]:
notes = []
if "gdpr" in selected:
notes.append("GDPR: EU personal data processed; binding regardless of certifiable choice.")
if "iso_27001" in selected:
notes.append("ISO 27001: enterprise B2B procurement frequently requires; foundation for AIMS + SOC 2.")
if "soc_2" in selected:
notes.append("SOC 2: US enterprise B2B procurement requires Type II audit; overlap with ISO 27001 ~75%.")
if "iso_42001" in selected:
notes.append("ISO 42001: AI in products; voluntary management system; satisfies Article 17 EU AI Act QMS.")
if "eu_ai_act" in selected:
notes.append("EU AI Act: AI deployed in EU; binding; Article 5 prohibitions in force; high-risk obligations 2 Aug 2026.")
if "iso_13485" in selected:
notes.append("ISO 13485: medical device manufacturer; required for MDR / FDA submissions.")
if "iso_14971" in selected:
notes.append("ISO 14971: medical device risk management; harmonised under MDR.")
if "eu_mdr_745" in selected:
notes.append("EU MDR 745: medical device sold in EU; binding; mandatory CE marking.")
if "fda_qsr" in selected:
notes.append("FDA QSR: medical device sold in US; binding; FDA quality system regulation.")
if "hipaa" in selected:
notes.append("HIPAA: processes US PHI; binding Security Rule (45 CFR 164 Subpart C) + Privacy Rule + Breach Notification.")
if "nis2" in selected:
notes.append("NIS2: essential or important entity in EU per Directive 2022/2555 Annex I/II; binding; cybersecurity + incident reporting obligations.")
if "nist_csf" in selected:
notes.append("NIST CSF 2.0: voluntary cybersecurity framework; recommended for US gov-adjacent orgs; cross-walks ISO 27001 + SOC 2 Common Criteria.")
return notes
def render_text(r: Dict[str, Any], source: str) -> str:
lines = []
lines.append("=" * 72)
lines.append("COMPLIANCE OS — APPLICABLE FRAMEWORKS")
lines.append(f"Source: {source}")
lines.append("=" * 72)
lines.append("")
lines.append(f"Company: {r['company']}")
lines.append(f"Industry: {r['industry']}")
lines.append(f"Applicable frameworks: {r['framework_count']} "
f"({r['binding_count']} binding + {r['certifiable_count']} certifiable)")
lines.append("")
lines.append("-" * 72)
lines.append("RANKED FRAMEWORKS (binding > certifiable > reference):")
lines.append("")
for f in r["applicable_frameworks"]:
kind = []
if f["binding"]:
kind.append("BINDING")
if f["certifiable"]:
kind.append("CERTIFIABLE")
kind_str = " | ".join(kind) if kind else "REFERENCE"
lines.append(f" [{kind_str:25s}] {f['name']:42s} ({f['id']})")
lines.append("")
lines.append("-" * 72)
lines.append("RATIONALE:")
for r_note in r["rationale"]:
lines.append(f" - {r_note}")
lines.append("")
if r["dependency_notes"]:
lines.append("-" * 72)
lines.append("DEPENDENCIES:")
for d in r["dependency_notes"]:
if d["satisfied_dependencies"]:
lines.append(f" {d['framework']} satisfied by: {', '.join(d['satisfied_dependencies'])}")
if d["missing_dependencies"]:
lines.append(f" {d['framework']} missing dependency: {', '.join(d['missing_dependencies'])} (consider adding)")
lines.append("")
lines.append("-" * 72)
lines.append("DECISION RULES:")
lines.append(" GDPR: any EU personal data processed -> mandatory")
lines.append(" ISO 27001: enterprise B2B procurement requirement; foundation for AIMS + SOC 2")
lines.append(" SOC 2: US enterprise B2B procurement requirement; overlap ~75% with ISO 27001")
lines.append(" ISO 42001: AI in products; voluntary AIMS; satisfies parts of Article 17 AI Act")
lines.append(" EU AI Act: AI in EU; binding; phased application through 2027")
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(
description="Multi-framework compliance applicability selector.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("path", nargs="?", help="Path to company profile JSON (uses embedded sample if omitted)")
parser.add_argument("--output", choices=("text", "json"), default="text", help="Output format")
args = parser.parse_args()
if args.path:
try:
with open(args.path, "r", encoding="utf-8") as f:
profile = json.load(f)
source = args.path
except (IOError, OSError) as e:
print(f"error: could not read {args.path}: {e}", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"error: invalid JSON in {args.path}: {e}", file=sys.stderr)
return 1
else:
profile = SAMPLE
source = "<embedded sample: mid-stage AI SaaS, US+EU customers, B2B>"
result = annotate(profile)
if args.output == "json":
print(json.dumps({"source": source, **result}, indent=2))
else:
print(render_text(result, source))
return 0
if __name__ == "__main__":
sys.exit(main())
Phỏng vấn 6 câu hỏi về chương trình tuân thủ đa khung trước khi bắt đầu khung mới hoặc chứng nhận.
--- name: "compliance-readiness" description: "/cs:compliance-readiness <program> — Multi-framework compliance officer 6-question forcing interrogation of any compliance program. Use before starting a new framework, planning the annual audit calendar, or preparing for certification stage 1." --- # /cs:compliance-readiness — Compliance Officer Forcing Questions **Command:** `/cs:compliance-readiness <program>` The multi-framework compliance officer pressure-tests any compliance program. Six questions before any new-framework commitment, audit cycle planning, or certification readiness sign-off. ## When to Run - Before adopting a new compliance framework - Before annual audit calendar finalization - Before certification stage 1 readiness sign-off - Before management review (Clause 9.3 across frameworks) - When evidence-collection effort has grown 50%+ year-over-year (a smell) - When an audit produced > 15% critical findings ## The Six Compliance Officer Questions ### 1. Have you named every applicable framework? **No framework selector run, no defensible scope.** - Run `framework_selector.py` with company profile - Forgetting a framework means rebuilding the audit program later - Pay attention to industry-specific overlays (financial: NYDFS, FINMA; healthcare: HIPAA, ISO 13485; AI: ISO 42001 + EU AI Act) ### 2. Where do the frameworks overlap, and what's the reuse leverage? **Single evidence -> N controls = the cornerstone of multi-framework efficiency.** - Run `cross_framework_mapper.py` with enabled frameworks - HIGH-confidence mappings: same evidence; MEDIUM: existing + overlay; LOW: new artefact - Without overlap analysis, you'll collect the same access-review records 3 times ### 3. Who owns each artefact, and what's the reuse-leverage score? **Joint ownership without accountability is the most common cause of stale evidence.** - Run `evidence_pool_generator.py` for the artefact inventory - HIGH-leverage artefacts (≥ 5 mappings) get built first - Each artefact needs one accountable owner - Stale evidence is an effective gap — even if the artefact existed historically ### 4. What's the audit calendar, and is auditor independence respected? **Surveillance audits stacking in the same week is a smell.** - Use per-framework audit-plan tools (aims_audit_scheduler, isms_audit_scheduler, audit_schedule_optimizer) - Auditor cannot audit their own work (Clause 9.2 across all ISO standards) - For small teams: rotate auditors + occasional external auditor ### 5. What does a mock audit produce, and is the severity distribution healthy? **No mock audit, no readiness signal.** - Run `audit_simulator.py` with framework + scope - Healthy distribution: ≥ 40% observation, ≤ 15% critical - All-critical findings = destructive audit OR genuinely failing program - All-observation findings = audit too superficial ### 6. What's the management review cadence across frameworks? **Each framework wants its own management review; an integrated review (per Annex SL) saves 5x exec time.** - Schedule one quarterly cross-framework review covering all enabled frameworks' Clause 9.3 inputs - Inputs: risk register changes, open nonconformities, audit findings, incidents, drift, KPIs - Outputs: action items, resource decisions, scope adjustments ## Workflow ```bash # 1. Framework selection python ../../skills/compliance-os/scripts/framework_selector.py profile.json # 2. Cross-framework overlap python ../../skills/compliance-os/scripts/cross_framework_mapper.py program.json # 3. Evidence pool consolidation python ../../skills/compliance-os/scripts/evidence_pool_generator.py program.json # 4. Mock audit (per framework) python ../../skills/compliance-os/scripts/audit_simulator.py scope.json ``` ## Output Format ```markdown # Compliance Readiness: <program> **Date:** YYYY-MM-DD ## The Decision Being Made [framework-set | audit-calendar | certification-readiness | evidence-consolidation] ## Framework Set - Applicable: <list> - Binding (regulations): <count> - Certifiable: <count> - Missing dependencies: <list> ## Cross-Framework Overlap - Total merged controls in scope: N - High-leverage artefacts (≥ 5 mappings): M - Top reuse opportunities: <top 5 artefacts> ## Evidence Pool - Artefacts in catalog: N - High-leverage count: M - Stale evidence rate: X% - Unowned artefacts: K ## Audit Calendar - Frameworks scheduled this year: <list> - Auditor independence respected: Y/N - Conflicts: <list> ## Mock Audit Results (per framework) - <framework>: total findings N, critical X%, observation Y%, healthy distribution: Y/N ## Verdict 🟢 READY | 🟡 STAGE-2-CANDIDATE | 🔴 NOT-READY ## Top 3 Actions [3 concrete next steps with owners + dates] ``` ## Routing - `/cs:aims-audit` — for ISO 42001-specific forcing questions - `/cs:ai-act-readiness` — for EU AI Act-specific forcing questions - `/cs:ciso-review` — for cybersecurity strategy - `/cs:caio-review` — for executive AI strategy - `/cs:gc-review` — for novel-case legal review - `/cs:decide` — to log the verdict - `/cs:freeze 30` — on certification commitments (multi-year financial impact) ## Related - Agent: [`cs-compliance-officer`](../../agents/cs-compliance-officer.md) - Skill: [`compliance-os`](../compliance-os/SKILL.md) - Adjacent: `../../ra-qm-team/skills/iso42001-specialist/`, `../../ra-qm-team/skills/eu-ai-act-specialist/`, `../../ra-qm-team/skills/information-security-manager-iso27001/`, `../../ra-qm-team/skills/soc2-compliance/`, `../../ra-qm-team/skills/gdpr-dsgvo-expert/` --- **Version:** 1.0.0
Tạo và quản lý không gian, cơ sở tri thức, tài liệu trên Confluence: phân quyền, mẫu trang, phân loại và quản trị nội dung.
---
name: "confluence-expert"
description: Atlassian Confluence expert for creating and managing spaces, knowledge bases, and documentation. Configures space permissions and hierarchies, creates page templates with macros, sets up documentation taxonomies, designs page layouts, and manages content governance. Use when users need to build or restructure a Confluence space, design page hierarchies with permission structures, author or standardise documentation templates, embed Jira reports in pages, run knowledge base audits, or establish documentation standards and collaborative workflows.
---
# Atlassian Confluence Expert
Master-level expertise in Confluence space management, documentation architecture, content creation, macros, templates, and collaborative knowledge management.
## Atlassian MCP Integration
**Primary Tool**: Confluence MCP Server
**Key Operations**:
```
// Create a new space
create_space({ key: "TEAM", name: "Engineering Team", description: "Engineering team knowledge base" })
// Create a page under a parent
create_page({ spaceKey: "TEAM", title: "Sprint 42 Notes", parentId: "123456", body: "<p>Meeting notes in storage-format HTML</p>" })
// Update an existing page (version must be incremented)
update_page({ pageId: "789012", version: 4, body: "<p>Updated content</p>" })
// Delete a page
delete_page({ pageId: "789012" })
// Search with CQL
search({ cql: 'space = "TEAM" AND label = "meeting-notes" ORDER BY lastModified DESC' })
// Retrieve child pages for hierarchy inspection
get_children({ pageId: "123456" })
// Apply a label to a page
add_label({ pageId: "789012", label: "archived" })
```
**Integration Points**:
- Create documentation for Senior PM projects
- Support Scrum Master with ceremony templates
- Link to Jira issues for Jira Expert
- Provide templates for Template Creator
> **See also**: `MACROS.md` for macro syntax reference, `TEMPLATES.md` for full template library, `PERMISSIONS.md` for permission scheme details.
## Workflows
### Space Creation
1. Determine space type (Team, Project, Knowledge Base, Personal)
2. Create space with clear name and description
3. Set space homepage with overview
4. Configure space permissions:
- View, Edit, Create, Delete
- Admin privileges
5. Create initial page tree structure
6. Add space shortcuts for navigation
7. **Verify**: Navigate to the space URL and confirm the homepage loads; check that a non-admin test user sees the correct permission level
8. **HANDOFF TO**: Teams for content population
### Page Architecture
**Best Practices**:
- Use page hierarchy (parent-child relationships)
- Maximum 3 levels deep for navigation
- Consistent naming conventions
- Date-stamp meeting notes
**Recommended Structure**:
```
Space Home
├── Overview & Getting Started
├── Team Information
│ ├── Team Members & Roles
│ ├── Communication Channels
│ └── Working Agreements
├── Projects
│ ├── Project A
│ │ ├── Overview
│ │ ├── Requirements
│ │ └── Meeting Notes
│ └── Project B
├── Processes & Workflows
├── Meeting Notes (Archive)
└── Resources & References
```
### Template Creation
1. Identify repeatable content pattern
2. Create page with structure and placeholders
3. Add instructions in placeholders
4. Format with appropriate macros
5. Save as template
6. Share with space or make global
7. **Verify**: Create a test page from the template and confirm all placeholders render correctly before sharing with the team
8. **USE**: References for advanced template patterns
### Documentation Strategy
1. **Assess** current documentation state
2. **Define** documentation goals and audience
3. **Organize** content taxonomy and structure
4. **Create** templates and guidelines
5. **Migrate** existing documentation
6. **Train** teams on best practices
7. **Monitor** usage and adoption
8. **REPORT TO**: Senior PM on documentation health
### Knowledge Base Management
**Article Types**:
- How-to guides
- Troubleshooting docs
- FAQs
- Reference documentation
- Process documentation
**Quality Standards**:
- Clear title and description
- Structured with headings
- Updated date visible
- Owner identified
- Reviewed quarterly
## Essential Macros
> Full macro reference with all parameters: see `MACROS.md`.
### Content Macros
**Info, Note, Warning, Tip**:
```
{info}
Important information here
{info}
```
**Expand**:
```
{expand:title=Click to expand}
Hidden content here
{expand}
```
**Table of Contents**:
```
{toc:maxLevel=3}
```
**Excerpt & Excerpt Include**:
```
{excerpt}
Reusable content
{excerpt}
{excerpt-include:Page Name}
```
### Dynamic Content
**Jira Issues**:
```
{jira:JQL=project = PROJ AND status = "In Progress"}
```
**Jira Chart**:
```
{jirachart:type=pie|jql=project = PROJ|statType=statuses}
```
**Recently Updated**:
```
{recently-updated:spaces=@all|max=10}
```
**Content by Label**:
```
{contentbylabel:label=meeting-notes|maxResults=20}
```
### Collaboration Macros
**Status**:
```
{status:colour=Green|title=Approved}
```
**Task List**:
```
{tasks}
- [ ] Task 1
- [x] Task 2 completed
{tasks}
```
**User Mention**:
```
@username
```
**Date**:
```
{date:format=dd MMM yyyy}
```
## Page Layouts & Formatting
**Two-Column Layout**:
```
{section}
{column:width=50%}
Left content
{column}
{column:width=50%}
Right content
{column}
{section}
```
**Panel**:
```
{panel:title=Panel Title|borderColor=#ccc}
Panel content
{panel}
```
**Code Block**:
```
{code:javascript}
const example = "code here";
{code}
```
## Templates Library
> Full template library with complete markup: see `TEMPLATES.md`. Key templates summarised below.
| Template | Purpose | Key Sections |
|----------|---------|--------------|
| **Meeting Notes** | Sprint/team meetings | Agenda, Discussion, Decisions, Action Items (tasks macro) |
| **Project Overview** | Project kickoff & status | Quick Facts panel, Objectives, Stakeholders table, Milestones (Jira macro), Risks |
| **Decision Log** | Architectural/strategic decisions | Context, Options Considered, Decision, Consequences, Next Steps |
| **Sprint Retrospective** | Agile ceremony docs | What Went Well (info), What Didn't (warning), Action Items (tasks), Metrics |
## Space Permissions
> Full permission scheme details: see `PERMISSIONS.md`.
### Permission Schemes
**Public Space**:
- All users: View
- Team members: Edit, Create
- Space admins: Admin
**Team Space**:
- Team members: View, Edit, Create
- Team leads: Admin
- Others: No access
**Project Space**:
- Stakeholders: View
- Project team: Edit, Create
- PM: Admin
## Content Governance
**Review Cycles**:
- Critical docs: Monthly
- Standard docs: Quarterly
- Archive docs: Annually
**Archiving Strategy**:
- Move outdated content to Archive space
- Label with "archived" and date
- Maintain for 2 years, then delete
- Keep audit trail
**Content Quality Checklist**:
- [ ] Clear, descriptive title
- [ ] Owner/author identified
- [ ] Last updated date visible
- [ ] Appropriate labels applied
- [ ] Links functional
- [ ] Formatting consistent
- [ ] No sensitive data exposed
## Decision Framework
**When to Escalate to Atlassian Admin**:
- Need org-wide template
- Require cross-space permissions
- Blueprint configuration
- Global automation rules
- Space export/import
**When to Collaborate with Jira Expert**:
- Embed Jira queries and charts
- Link pages to Jira issues
- Create Jira-based reports
- Sync documentation with tickets
**When to Support Scrum Master**:
- Sprint documentation templates
- Retrospective pages
- Team working agreements
- Process documentation
**When to Support Senior PM**:
- Executive report pages
- Portfolio documentation
- Stakeholder communication
- Strategic planning docs
## Handoff Protocols
**FROM Senior PM**:
- Documentation requirements
- Space structure needs
- Template requirements
- Knowledge management strategy
**TO Senior PM**:
- Documentation coverage reports
- Content usage analytics
- Knowledge gaps identified
- Template adoption metrics
**FROM Scrum Master**:
- Sprint ceremony templates
- Team documentation needs
- Meeting notes structure
- Retrospective format
**TO Scrum Master**:
- Configured templates
- Space for team docs
- Training on best practices
- Documentation guidelines
**WITH Jira Expert**:
- Jira-Confluence linking
- Embedded Jira reports
- Issue-to-page connections
- Cross-tool workflow
## Best Practices
**Organization**:
- Consistent naming conventions
- Meaningful labels
- Logical page hierarchy
- Related pages linked
- Clear navigation
**Maintenance**:
- Regular content audits
- Remove duplication
- Update outdated information
- Archive obsolete content
- Monitor page analytics
## Analytics & Metrics
**Usage Metrics**:
- Page views per space
- Most visited pages
- Search queries
- Contributor activity
- Orphaned pages
**Health Indicators**:
- Pages without recent updates
- Pages without owners
- Duplicate content
- Broken links
- Empty spaces
## Related Skills
- **Jira Expert** (`project-management/jira-expert/`) — Jira issue macros and linking complement Confluence docs
- **Atlassian Templates** (`project-management/atlassian-templates/`) — Template patterns for Confluence content creation
FILE:references/macro-cheat-sheet.md
# Confluence Macro Cheat Sheet
## Overview
Quick reference for the most commonly used Confluence macros. Each entry includes the macro name, storage format syntax, primary use case, and practical tips.
## Navigation & Structure Macros
### Table of Contents
- **Purpose:** Auto-generate a linked table of contents from page headings
- **Syntax:** `<ac:structured-macro ac:name="toc" />`
- **Parameters:** `maxLevel` (1-6), `minLevel` (1-6), `style` (disc, circle, square, none), `type` (list, flat)
- **Use case:** Long documentation pages, meeting notes, specifications
- **Tip:** Set `maxLevel="3"` to avoid overly deep TOC entries
### Children Display
- **Purpose:** List child pages of the current page
- **Syntax:** `<ac:structured-macro ac:name="children" />`
- **Parameters:** `depth` (1-999), `sort` (title, creation, modified), `style` (h2-h6), `all` (true/false)
- **Use case:** Parent hub pages, project homepages, documentation indexes
- **Tip:** Use `depth="1"` for clean navigation, `all="true"` for deep hierarchies
### Include Page
- **Purpose:** Embed content from another page inline
- **Syntax:** `<ac:structured-macro ac:name="include"><ac:parameter ac:name=""><ac:link><ri:page ri:content-title="Page Name" /></ac:link></ac:parameter></ac:structured-macro>`
- **Use case:** Reusable content blocks (headers, footers, disclaimers)
- **Tip:** Changes to the source page are reflected everywhere it is included
### Page Properties
- **Purpose:** Define structured metadata on a page (key-value pairs)
- **Syntax:** `<ac:structured-macro ac:name="details">` with table inside
- **Use case:** Project metadata, status tracking, structured page data
- **Tip:** Combine with Page Properties Report macro to create dashboards
### Page Properties Report
- **Purpose:** Display a table of Page Properties from child pages
- **Syntax:** `<ac:structured-macro ac:name="detailssummary" />`
- **Parameters:** `cql` (CQL filter), `labels` (filter by label)
- **Use case:** Project dashboards, status rollups, portfolio views
- **Tip:** Use labels to scope the report to relevant pages only
## Visual & Formatting Macros
### Info Panel
- **Purpose:** Blue information callout box
- **Syntax:** `<ac:structured-macro ac:name="info"><ac:rich-text-body>Content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Helpful notes, additional context, best practices
### Warning Panel
- **Purpose:** Yellow warning callout box
- **Syntax:** `<ac:structured-macro ac:name="warning"><ac:rich-text-body>Content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Important caveats, deprecation notices, breaking changes
### Note Panel
- **Purpose:** Yellow note callout box
- **Syntax:** `<ac:structured-macro ac:name="note"><ac:rich-text-body>Content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Reminders, action items, things to watch
### Tip Panel
- **Purpose:** Green tip callout box
- **Syntax:** `<ac:structured-macro ac:name="tip"><ac:rich-text-body>Content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Pro tips, shortcuts, recommended approaches
### Expand
- **Purpose:** Collapsible content section (click to expand)
- **Syntax:** `<ac:structured-macro ac:name="expand"><ac:parameter ac:name="title">Click to expand</ac:parameter><ac:rich-text-body>Hidden content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Long sections, FAQs, detailed explanations, optional reading
- **Tip:** Use for content that not all readers need
### Status
- **Purpose:** Colored status lozenge (inline label)
- **Syntax:** `<ac:structured-macro ac:name="status"><ac:parameter ac:name="colour">Green</ac:parameter><ac:parameter ac:name="title">DONE</ac:parameter></ac:structured-macro>`
- **Colors:** Grey, Red, Yellow, Green, Blue
- **Use case:** Task status, review state, approval status
- **Tip:** Standardize status values across your team (e.g., TODO, IN PROGRESS, DONE)
## Integration Macros
### Jira Issues
- **Purpose:** Display Jira issues or JQL query results
- **Syntax:** `<ac:structured-macro ac:name="jira"><ac:parameter ac:name="jqlQuery">project = PROJ AND status = Open</ac:parameter></ac:structured-macro>`
- **Parameters:** `jqlQuery`, `columns` (key, summary, status, assignee, etc.), `count` (true/false), `serverId`
- **Use case:** Sprint boards in documentation, requirement traceability, release notes
- **Tip:** Use `columns` parameter to show only relevant fields
### Roadmap Planner
- **Purpose:** Visual timeline/Gantt view of items
- **Syntax:** Available via macro browser (Roadmap Planner)
- **Use case:** Project timelines, release planning, milestone tracking
- **Tip:** Link roadmap items to Jira epics for automatic status updates
### Chart Macro
- **Purpose:** Create charts from table data on the page
- **Syntax:** `<ac:structured-macro ac:name="chart"><ac:parameter ac:name="type">pie</ac:parameter><ac:rich-text-body>Table data</ac:rich-text-body></ac:structured-macro>`
- **Types:** pie, bar, line, area, scatter, timeSeries
- **Use case:** Status distribution, metrics dashboards, trend visualization
- **Tip:** Place a Confluence table inside the macro body as data source
## Content Reuse Macros
### Excerpt
- **Purpose:** Mark a section of content for reuse via Excerpt Include
- **Syntax:** `<ac:structured-macro ac:name="excerpt"><ac:rich-text-body>Reusable content</ac:rich-text-body></ac:structured-macro>`
- **Use case:** Define canonical content blocks (product descriptions, team info)
### Excerpt Include
- **Purpose:** Display an Excerpt from another page
- **Syntax:** `<ac:structured-macro ac:name="excerpt-include"><ac:parameter ac:name=""><ac:link><ri:page ri:content-title="Source Page" /></ac:link></ac:parameter></ac:structured-macro>`
- **Use case:** Embed product descriptions, standard disclaimers, shared definitions
## Advanced Macros
### Code Block
- **Purpose:** Display formatted code with syntax highlighting
- **Syntax:** `<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">python</ac:parameter><ac:plain-text-body>code here</ac:plain-text-body></ac:structured-macro>`
- **Languages:** java, python, javascript, sql, bash, xml, json, and many more
- **Use case:** API documentation, configuration examples, code snippets
### Anchor
- **Purpose:** Create a named anchor point for deep linking
- **Syntax:** `<ac:structured-macro ac:name="anchor"><ac:parameter ac:name="">anchor-name</ac:parameter></ac:structured-macro>`
- **Use case:** Link directly to specific sections within long pages
- **Tip:** Use with TOC macro for custom navigation
### Recently Updated
- **Purpose:** Show recently modified pages in a space
- **Syntax:** `<ac:structured-macro ac:name="recently-updated" />`
- **Parameters:** `spaces`, `labels`, `types`, `max`
- **Use case:** Team dashboards, space homepages, activity feeds
## Macro Selection Guide
| Need | Recommended Macro |
|------|------------------|
| Page navigation | Table of Contents |
| List child pages | Children Display |
| Reuse content | Include Page or Excerpt Include |
| Status tracking | Status + Page Properties |
| Project dashboard | Page Properties Report |
| Hide optional content | Expand |
| Show Jira data | Jira Issues |
| Visualize data | Chart |
| Code documentation | Code Block |
| Important callouts | Info/Warning/Note/Tip panels |
FILE:references/space-architecture-patterns.md
# Confluence Space Architecture Patterns
## Overview
Well-organized Confluence spaces dramatically improve information discoverability and team productivity. This guide covers proven space organization patterns, page hierarchy best practices, and governance strategies.
## Space Organization Patterns
### Pattern 1: By Team
Each team or department gets its own space.
**Structure:**
```
Engineering Space (ENG)
Product Space (PROD)
Marketing Space (MKT)
Design Space (DES)
Support Space (SUP)
```
**Pros:**
- Clear ownership and permissions
- Teams control their own content
- Natural permission boundaries
- Easy to find team-specific content
**Cons:**
- Cross-team content duplication
- Silos between departments
- Hard to find project-spanning information
- Inconsistent practices across spaces
**Best for:** Organizations with stable teams and clear departmental boundaries
### Pattern 2: By Project
Each major project or product gets its own space.
**Structure:**
```
Project Alpha Space (ALPHA)
Project Beta Space (BETA)
Platform Infrastructure Space (PLAT)
Internal Tools Space (TOOLS)
```
**Pros:**
- All project context in one place
- Easy onboarding for project members
- Clean archival when project completes
- Natural lifecycle management
**Cons:**
- Team knowledge scattered across spaces
- Permission management per project
- Space proliferation over time
- Ongoing vs project work separation unclear
**Best for:** Project-based organizations, agencies, consulting firms
### Pattern 3: By Domain (Hybrid)
Combine functional spaces with cross-cutting project spaces.
**Structure:**
```
Company Wiki (WIKI) - Shared knowledge
Engineering Standards (ENG) - Team practices
Product Specs (PROD) - Requirements and roadmap
Project Alpha (ALPHA) - Cross-team project
Project Beta (BETA) - Cross-team project
Archive (ARCH) - Completed projects
```
**Pros:**
- Balances team and project needs
- Shared knowledge has a home
- Clear archival path
- Scales with organization growth
**Cons:**
- More complex to set up initially
- Requires governance to maintain
- Some ambiguity about where content belongs
**Best for:** Growing organizations, 50-500 people, multiple concurrent projects
## Page Hierarchy Best Practices
### Recommended Depth
- **Maximum 4 levels deep** - Deeper hierarchies become hard to navigate
- **3 levels ideal** for most content types
- Use flat structures with labels for categorization beyond 4 levels
### Standard Page Hierarchy
```
Space Home (overview, quick links, recent updates)
├── Getting Started
│ ├── Onboarding Guide
│ ├── Tool Setup
│ └── Key Contacts
├── Projects
│ ├── Project Alpha
│ │ ├── Requirements
│ │ ├── Design
│ │ └── Meeting Notes
│ └── Project Beta
├── Processes
│ ├── Development Workflow
│ ├── Release Process
│ └── On-Call Runbook
├── References
│ ├── Architecture Decisions
│ ├── API Documentation
│ └── Glossary
└── Archive
├── 2025 Projects
└── Deprecated Processes
```
### Page Naming Conventions
- Use clear, descriptive titles (not abbreviations)
- Include date for time-sensitive content: "2025-Q1 Planning"
- Prefix meeting notes with date: "2025-03-15 Sprint Review"
- Use consistent casing (Title Case or Sentence case, not both)
- Avoid special characters that break URLs
### Space Homepage Design
Every space homepage should include:
1. **Space purpose** - One paragraph describing what this space is for
2. **Quick links** - 5-7 most accessed pages
3. **Recent updates** - Recently Updated macro filtered to this space
4. **Getting started** - Link to onboarding content for new members
5. **Contact info** - Space owner, key contributors
## Labeling Taxonomy
### Label Categories
- **Content type:** `meeting-notes`, `decision`, `specification`, `runbook`, `retrospective`
- **Status:** `draft`, `in-review`, `approved`, `deprecated`, `archived`
- **Team:** `team-engineering`, `team-product`, `team-design`
- **Project:** `project-alpha`, `project-beta`
- **Priority:** `high-priority`, `p1`, `critical`
### Labeling Best Practices
- Use lowercase, hyphenated labels (no spaces or camelCase)
- Define a standard label vocabulary and document it
- Use labels for cross-space categorization
- Combine labels with CQL for powerful search and reporting
- Audit labels quarterly to remove unused or inconsistent labels
- Limit to 3-5 labels per page (over-labeling reduces value)
### CQL Examples for Label-Based Queries
```
# All meeting notes in a space
type = page AND space = "ENG" AND label = "meeting-notes"
# All approved specifications
type = page AND label = "specification" AND label = "approved"
# Recent decisions across all spaces
type = page AND label = "decision" AND lastModified > now("-30d")
```
## Cross-Space Linking
### When to Link vs Duplicate
- **Link** when content has a single source of truth
- **Duplicate** (Include Page macro) when content must appear in multiple contexts
- **Excerpt Include** when only a portion of a page is needed elsewhere
### Linking Best Practices
- Use full page titles in links for clarity
- Add context around links ("See the [Architecture Decision Record] for rationale")
- Avoid orphan pages - every page should be reachable from space navigation
- Use the Recently Updated macro on hub pages for activity visibility
- Create "Related Pages" sections at the bottom of content pages
## Archive Strategy
### When to Archive
- Project completed more than 90 days ago
- Process or document officially deprecated
- Content not updated in 12+ months
- Replaced by newer content
### Archive Process
1. Add `archived` label to the page
2. Move to Archive section within the space (or dedicated Archive space)
3. Add a note at the top: "This page is archived as of [date]. See [replacement] for current information."
4. Update any incoming links to point to current content
5. Do NOT delete - archived content has historical value
### Archive Space Pattern
- Create a dedicated `Archive` space for completed projects
- Move entire project page trees to Archive space on completion
- Set Archive space to read-only permissions
- Review Archive space annually for content that can be deleted
## Permission Inheritance Patterns
### Pattern 1: Open by Default
- All spaces readable by all employees
- Edit restricted to space members
- Admin restricted to space owners
- **Best for:** Transparency-focused organizations
### Pattern 2: Restricted by Default
- Spaces accessible only to specific groups
- Request access via space admin
- **Best for:** Regulated industries, confidential projects
### Pattern 3: Tiered Access
- Public tier: Company wiki, shared processes
- Team tier: Team-specific spaces with team access
- Restricted tier: HR, finance, legal with limited access
- **Best for:** Most organizations (balanced approach)
### Permission Tips
- Use Confluence groups, not individual users, for permissions
- Align groups with LDAP/SSO groups where possible
- Audit permissions quarterly
- Document permission model on the space homepage
- Use page-level restrictions sparingly (breaks inheritance, hard to audit)
## Scaling Considerations
### < 50 People
- 3-5 spaces total
- Simple by-team pattern
- Light governance
### 50-200 People
- 10-20 spaces
- Hybrid pattern (team + project)
- Formal labeling taxonomy
- Quarterly content reviews
### 200+ People
- 20-50+ spaces
- Full domain pattern with governance
- Space owners and content stewards
- Automated archival policies
- Regular information architecture reviews
FILE:references/templates.md
# Confluence Page Templates
## Meeting Notes Template
```markdown
# [Meeting Title] - [Date]
**Date:** [YYYY-MM-DD]
**Time:** [HH:MM - HH:MM]
**Location:** [Room/Video link]
**Attendees:** @[Name1], @[Name2], @[Name3]
**Note Taker:** @[Name]
## Agenda
1. [Topic 1]
2. [Topic 2]
3. [Topic 3]
## Discussion
### [Topic 1]
**Summary:**
[Key points discussed]
**Decisions:**
- [Decision 1]
- [Decision 2]
**Action Items:**
- [ ] [Action] - @[Owner] - [Due Date]
- [ ] [Action] - @[Owner] - [Due Date]
### [Topic 2]
**Summary:**
[Key points discussed]
**Decisions:**
- [Decision 1]
**Action Items:**
- [ ] [Action] - @[Owner] - [Due Date]
## Parking Lot
- [Item to discuss later]
- [Future topic]
## Next Meeting
**Date:** [YYYY-MM-DD]
**Agenda Topics:**
- [Topic 1]
- [Topic 2]
```
---
## Decision Log Template
```markdown
# [Decision Title]
| Field | Value |
|-------|-------|
| **Status** | 🟢 Accepted / 🟡 Proposed / 🔴 Deprecated |
| **Date** | [YYYY-MM-DD] |
| **Deciders** | @[Name1], @[Name2] |
| **Stakeholders** | @[Name3], @[Name4] |
| **Related Decisions** | [Link to related decisions] |
## Context and Problem Statement
[Describe the context and problem that requires a decision. 2-3 paragraphs explaining:
- What situation led to this decision?
- What problem are we trying to solve?
- What constraints exist?]
## Decision
[Clearly state the decision made in 1-2 sentences]
### Details
[Provide additional details about the decision:
- What exactly will we do?
- How will it be implemented?
- What timeline?]
## Rationale
[Explain why this decision was made:
- What were the key factors?
- What evidence supports this?
- Why is this the best choice?]
## Consequences
### Positive Consequences
- ✅ [Benefit 1]
- ✅ [Benefit 2]
- ✅ [Benefit 3]
### Negative Consequences / Trade-offs
- ⚠️ [Trade-off 1]
- ⚠️ [Trade-off 2]
### Risks
- 🔴 [Risk 1] - Mitigation: [How we'll handle it]
- 🟡 [Risk 2] - Mitigation: [How we'll handle it]
## Alternatives Considered
### Alternative 1: [Name]
**Description:** [What is this alternative?]
**Pros:**
- [Pro 1]
- [Pro 2]
**Cons:**
- [Con 1]
- [Con 2]
**Why Not Chosen:** [Reason]
### Alternative 2: [Name]
[Same structure as above]
## Implementation Plan
1. [Step 1] - @[Owner] - [Date]
2. [Step 2] - @[Owner] - [Date]
3. [Step 3] - @[Owner] - [Date]
## Success Metrics
- [Metric 1]: [Target]
- [Metric 2]: [Target]
## Review Date
**Next Review:** [YYYY-MM-DD]
**Review Notes:** [Link to review page]
## References
- [Link 1]
- [Link 2]
- [Link 3]
---
*Updated: [Date] by @[Name]*
```
---
## Technical Specification Template
```markdown
# [Feature/Component Name] Technical Specification
| Field | Value |
|-------|-------|
| **Status** | 🟡 Draft / 🟢 Approved / 🔴 Archived |
| **Author** | @[Name] |
| **Reviewers** | @[Name1], @[Name2] |
| **Date Created** | [YYYY-MM-DD] |
| **Last Updated** | [YYYY-MM-DD] |
| **JIRA Epic** | [ABC-123](link) |
## Overview
[1-2 paragraph summary of what this spec covers and why it matters]
## Goals and Non-Goals
### Goals
- [Goal 1]
- [Goal 2]
- [Goal 3]
### Non-Goals (Out of Scope)
- [Non-goal 1]
- [Non-goal 2]
## Background
[Context needed to understand this spec:
- What problem are we solving?
- What's the current state?
- Why now?]
## High-Level Design
### Architecture Diagram
[Insert diagram here]
### System Components
1. **[Component 1 Name]**
- Purpose: [What it does]
- Technology: [What it uses]
- Interfaces: [How it connects]
2. **[Component 2 Name]**
- Purpose: [What it does]
- Technology: [What it uses]
- Interfaces: [How it connects]
### Data Flow
[Describe how data flows through the system]
## Detailed Design
### Component 1: [Name]
**Purpose:** [Detailed purpose]
**Responsibilities:**
- [Responsibility 1]
- [Responsibility 2]
**API/Interface:**
```
[API spec or interface definition]
```
**Data Model:**
```
[Schema or data structure]
```
**Key Algorithms/Logic:**
[Describe any complex logic]
### Component 2: [Name]
[Same structure as Component 1]
## Database Schema
### Table: [table_name]
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PRIMARY KEY | Unique identifier |
| name | VARCHAR(255) | NOT NULL | Entity name |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
### Indexes
- `idx_name` on `name` - For fast lookups
- `idx_created` on `created_at` - For temporal queries
## API Specification
### Endpoint: [Method] /api/path
**Purpose:** [What this endpoint does]
**Request:**
```json
{
"param1": "value",
"param2": 123
}
```
**Response:**
```json
{
"result": "success",
"data": {}
}
```
**Error Handling:**
- 400: [Reason]
- 404: [Reason]
- 500: [Reason]
## Security Considerations
- [Security consideration 1]
- [Security consideration 2]
- [Authentication/Authorization approach]
- [Data encryption requirements]
## Performance Considerations
- [Expected load/throughput]
- [Scalability approach]
- [Caching strategy]
- [Performance targets]
## Testing Strategy
### Unit Tests
- [Test area 1]
- [Test area 2]
### Integration Tests
- [Test scenario 1]
- [Test scenario 2]
### Performance Tests
- [Load test plan]
- [Performance benchmarks]
## Deployment Plan
1. [Deployment step 1]
2. [Deployment step 2]
3. [Deployment step 3]
### Rollback Plan
[How to revert if issues occur]
## Monitoring and Alerting
- [Metric 1] - Alert threshold: [Value]
- [Metric 2] - Alert threshold: [Value]
- [Log tracking]
## Migration Plan (if applicable)
[How to migrate from current system]
## Dependencies
- [Dependency 1] - Why needed
- [Dependency 2] - Why needed
## Open Questions
- [ ] [Question 1] - @[Owner]
- [ ] [Question 2] - @[Owner]
## Future Considerations
- [Future enhancement 1]
- [Future enhancement 2]
## References
- [Link to related specs]
- [Link to design docs]
- [Link to JIRA epics]
---
*For questions, contact @[Author]*
```
---
## How-To Guide Template
```markdown
# How to [Task Name]
## Overview
[1-2 sentences explaining what this guide covers and who it's for]
**Estimated Time:** [X minutes]
**Difficulty:** [Beginner/Intermediate/Advanced]
## Prerequisites
Before you begin, ensure you have:
- [ ] [Prerequisite 1]
- [ ] [Prerequisite 2]
- [ ] [Prerequisite 3]
## Quick Summary (TL;DR)
[One paragraph with the essence of the guide for those who just need a reminder]
## Step-by-Step Instructions
### Step 1: [Action]
[Detailed description of what to do]
**Commands/Code:**
```bash
command here
```
**Expected Result:**
[What you should see if it worked]
**Screenshot:**
[Add screenshot if helpful]
### Step 2: [Action]
[Detailed description]
**Tips:**
- 💡 [Helpful tip]
- ⚠️ [Warning about common mistake]
### Step 3: [Action]
[Continue pattern...]
## Verification
To verify everything worked:
1. [Check 1]
2. [Check 2]
## Troubleshooting
### Problem: [Common issue]
**Symptoms:** [What you see]
**Cause:** [Why it happens]
**Solution:**
1. [Fix step 1]
2. [Fix step 2]
### Problem: [Another issue]
[Same structure as above]
## Best Practices
- [Best practice 1]
- [Best practice 2]
- [Best practice 3]
## Related Guides
- [Link to related guide 1]
- [Link to related guide 2]
## Need Help?
- Questions? Ask in #[channel]
- Issues? Create ticket in [JIRA project]
- Contact: @[Expert name]
---
*Last updated: [Date] by @[Name]*
```
---
## Requirements Document Template
```markdown
# [Feature/Project Name] Requirements
| Field | Value |
|-------|-------|
| **Status** | 🟡 Draft / 🟢 Approved / 🔵 In Progress / ✅ Complete |
| **Product Owner** | @[Name] |
| **Stakeholders** | @[Name1], @[Name2] |
| **Target Release** | [Release version] |
| **JIRA Epic** | [ABC-123](link) |
| **Created** | [YYYY-MM-DD] |
| **Last Updated** | [YYYY-MM-DD] |
## Executive Summary
[2-3 sentences describing the feature and its business value]
## Business Goals
- [Goal 1]: [Metric]
- [Goal 2]: [Metric]
- [Goal 3]: [Metric]
## User Stories
### Story 1: [Title]
**As a** [user type]
**I want** [goal]
**So that** [benefit]
**Acceptance Criteria:**
- [ ] [Criterion 1]
- [ ] [Criterion 2]
- [ ] [Criterion 3]
**Priority:** [High/Medium/Low]
**Effort:** [Story points]
### Story 2: [Title]
[Same structure as Story 1]
## Functional Requirements
### FR-001: [Requirement Title]
**Description:** [What the system must do]
**Rationale:** [Why this is needed]
**Acceptance Criteria:**
- [Criterion 1]
- [Criterion 2]
**Priority:** [Must Have / Should Have / Could Have / Won't Have]
### FR-002: [Requirement Title]
[Same structure as FR-001]
## Non-Functional Requirements
### Performance
- [Requirement 1]
- [Requirement 2]
### Security
- [Requirement 1]
- [Requirement 2]
### Scalability
- [Requirement 1]
- [Requirement 2]
### Accessibility
- [Requirement 1]
- [Requirement 2]
## User Experience
### Wireframes
[Insert wireframes or link to Figma]
### User Flow
[Diagram showing user journey]
### UI Requirements
- [UI requirement 1]
- [UI requirement 2]
## Technical Constraints
- [Constraint 1]
- [Constraint 2]
- [Constraint 3]
## Dependencies
| Dependency | Owner | Status | Impact if Blocked |
|------------|-------|--------|-------------------|
| [Dep 1] | @[Name] | 🟢 Ready | [Impact] |
| [Dep 2] | @[Name] | 🟡 In Progress | [Impact] |
## Success Metrics
| Metric | Baseline | Target | How Measured |
|--------|----------|--------|--------------|
| [Metric 1] | [Current] | [Goal] | [Method] |
| [Metric 2] | [Current] | [Goal] | [Method] |
## Risks and Mitigations
| Risk | Impact | Probability | Mitigation |
|------|--------|-------------|------------|
| [Risk 1] | High | Medium | [Strategy] |
| [Risk 2] | Medium | Low | [Strategy] |
## Out of Scope
- [Explicitly excluded 1]
- [Explicitly excluded 2]
## Open Questions
- [ ] [Question 1] - @[Owner] - [Due date]
- [ ] [Question 2] - @[Owner] - [Due date]
## Timeline
| Phase | Start Date | End Date | Deliverables |
|-------|-----------|----------|--------------|
| Design | [Date] | [Date] | [Deliverable] |
| Development | [Date] | [Date] | [Deliverable] |
| Testing | [Date] | [Date] | [Deliverable] |
| Launch | [Date] | [Date] | [Deliverable] |
## Approval
### Reviewers
- [ ] Product Owner: @[Name]
- [ ] Engineering Lead: @[Name]
- [ ] Design Lead: @[Name]
- [ ] Stakeholder: @[Name]
**Approved Date:** [YYYY-MM-DD]
## References
- [Market research]
- [User feedback]
- [Technical specs]
- [Related features]
---
*For questions, contact @[Product Owner]*
```
---
## Retrospective Template
```markdown
# Sprint [N] Retrospective - [Team Name]
**Date:** [YYYY-MM-DD]
**Sprint:** [Sprint N]
**Sprint Dates:** [Start Date] - [End Date]
**Facilitator:** @[Name]
**Participants:** @[Name1], @[Name2], @[Name3]
## Sprint Metrics
- **Velocity:** [X points] (Average: [Y points])
- **Committed:** [X points / N issues]
- **Completed:** [Y points / M issues]
- **Sprint Goal Met:** ✅ Yes / ❌ No
## What Went Well 😊
- [Positive 1]
- [Positive 2]
- [Positive 3]
## What Didn't Go Well 😞
- [Challenge 1]
- [Challenge 2]
- [Challenge 3]
## Action Items from Last Retro
- [✅ / ❌] [Action item 1] - @[Owner]
- Status: [Done / In Progress / Not Done]
- Notes: [Update]
- [✅ / ❌] [Action item 2] - @[Owner]
- Status: [Done / In Progress / Not Done]
- Notes: [Update]
## Discussion Themes
### Theme 1: [Topic]
**What we discussed:**
[Summary of discussion]
**Root cause:**
[What's really causing this issue?]
**Ideas for improvement:**
- [Idea 1]
- [Idea 2]
### Theme 2: [Topic]
[Same structure as Theme 1]
## Action Items for Next Sprint
| Action | Owner | Due Date | Success Criteria |
|--------|-------|----------|------------------|
| [Action 1] | @[Name] | [Date] | [How we know it's done] |
| [Action 2] | @[Name] | [Date] | [How we know it's done] |
| [Action 3] | @[Name] | [Date] | [How we know it's done] |
## Shout-Outs 🎉
- @[Name] for [what they did]
- @[Name] for [what they did]
## Notes
[Any additional notes or observations]
---
*Next Retrospective: [Date]*
```
---
## Status Report Template
```markdown
# [Project Name] Status Report - [Week of Date]
**Report Date:** [YYYY-MM-DD]
**Reporting Period:** [Start Date] - [End Date]
**Project Manager:** @[Name]
**Overall Status:** 🟢 On Track / 🟡 At Risk / 🔴 Off Track
## Executive Summary
[2-3 sentences: What's the current state? What are the key achievements? What needs attention?]
## Project Health
| Metric | Status | Details |
|--------|--------|---------|
| **Scope** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Schedule** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Budget** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Quality** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Team Morale** | 🟢 / 🟡 / 🔴 | [Comment] |
## Key Accomplishments
- ✅ [Accomplishment 1]
- ✅ [Accomplishment 2]
- ✅ [Accomplishment 3]
## Milestones Status
| Milestone | Target Date | Status | Actual/Forecast | Notes |
|-----------|-------------|--------|-----------------|-------|
| [Milestone 1] | [Date] | ✅ Complete | [Date] | [Notes] |
| [Milestone 2] | [Date] | 🔄 In Progress | On track | [Notes] |
| [Milestone 3] | [Date] | ⏳ Not Started | [Forecast] | [Notes] |
## Active Risks
### 🔴 Critical Risks
| Risk | Impact | Mitigation | Owner | Status |
|------|--------|------------|-------|--------|
| [Risk 1] | High | [Strategy] | @[Name] | [Update] |
### 🟡 Medium Risks
| Risk | Impact | Mitigation | Owner | Status |
|------|--------|------------|-------|--------|
| [Risk 2] | Medium | [Strategy] | @[Name] | [Update] |
## Issues & Blockers
### 🚨 Blockers
- [Blocker 1] - @[Owner] - **Escalated to:** [Person]
- Impact: [What's blocked]
- ETA to resolve: [Date]
### ⚠️ Issues
- [Issue 1] - @[Owner]
- Status: [Update]
## Upcoming in Next Period
- [Activity 1]
- [Activity 2]
- [Activity 3]
## Budget Update (if applicable)
- **Total Budget:** [Amount]
- **Spent to Date:** [Amount] ([%])
- **Forecast to Complete:** [Amount]
- **Variance:** [Amount] ([%])
## Decisions Needed
| Decision | Why Needed | Deadline | Stakeholder |
|----------|-----------|----------|-------------|
| [Decision 1] | [Reason] | [Date] | @[Name] |
## Team Update
- **Current Team Size:** [N people]
- **Open Positions:** [N] ([Roles])
- **Recent Additions:** @[Name] - [Role]
- **Upcoming Departures:** [Names/Dates]
## Metrics (if applicable)
| Metric | This Period | Last Period | Trend | Target |
|--------|-------------|-------------|-------|--------|
| [Metric 1] | [Value] | [Value] | ↗️ / ↘️ / → | [Target] |
| [Metric 2] | [Value] | [Value] | ↗️ / ↘️ / → | [Target] |
## Links
- [Jira Project](link)
- [Roadmap](link)
- [Technical Docs](link)
---
*Next Status Report: [Date]*
```
FILE:scripts/content_audit_analyzer.py
#!/usr/bin/env python3
"""
Content Audit Analyzer
Analyzes Confluence page inventory for content health. Identifies stale pages,
low-engagement content, orphaned pages, oversized documents, and produces a
health score with actionable recommendations.
Usage:
python content_audit_analyzer.py pages.json
python content_audit_analyzer.py pages.json --format json
"""
import argparse
import json
import sys
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Tuple
# ---------------------------------------------------------------------------
# Audit Configuration
# ---------------------------------------------------------------------------
STALE_THRESHOLD_DAYS = 90
OUTDATED_THRESHOLD_DAYS = 180
LOW_VIEW_THRESHOLD = 5
OVERSIZED_WORD_THRESHOLD = 5000
IDEAL_WORD_RANGE = (200, 3000)
HEALTH_WEIGHTS = {
"freshness": 0.30,
"engagement": 0.25,
"organization": 0.20,
"size_balance": 0.15,
"completeness": 0.10,
}
# ---------------------------------------------------------------------------
# Audit Checks
# ---------------------------------------------------------------------------
def check_stale_pages(
pages: List[Dict[str, Any]],
reference_date: datetime,
) -> Dict[str, Any]:
"""Identify pages not updated within the stale threshold."""
stale = []
outdated = []
for page in pages:
last_modified = _parse_date(page.get("last_modified", ""))
if not last_modified:
continue
days_since_update = (reference_date - last_modified).days
if days_since_update > OUTDATED_THRESHOLD_DAYS:
outdated.append({
"title": page.get("title", "Untitled"),
"days_since_update": days_since_update,
"last_modified": page.get("last_modified", ""),
"author": page.get("author", "unknown"),
})
elif days_since_update > STALE_THRESHOLD_DAYS:
stale.append({
"title": page.get("title", "Untitled"),
"days_since_update": days_since_update,
"last_modified": page.get("last_modified", ""),
"author": page.get("author", "unknown"),
})
total = len(pages)
stale_count = len(stale) + len(outdated)
fresh_ratio = 1 - (stale_count / total) if total > 0 else 1
score = max(0, fresh_ratio * 100)
return {
"score": score,
"stale_pages": stale,
"outdated_pages": outdated,
"stale_count": len(stale),
"outdated_count": len(outdated),
"fresh_count": total - stale_count,
}
def check_engagement(pages: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Identify low-engagement pages based on view counts."""
low_engagement = []
view_counts = []
for page in pages:
views = page.get("view_count", 0)
view_counts.append(views)
if views < LOW_VIEW_THRESHOLD:
low_engagement.append({
"title": page.get("title", "Untitled"),
"view_count": views,
"author": page.get("author", "unknown"),
})
total = len(pages)
avg_views = sum(view_counts) / total if total > 0 else 0
engaged_ratio = 1 - (len(low_engagement) / total) if total > 0 else 1
score = max(0, engaged_ratio * 100)
return {
"score": score,
"low_engagement_pages": low_engagement,
"low_engagement_count": len(low_engagement),
"average_views": round(avg_views, 1),
"max_views": max(view_counts) if view_counts else 0,
"min_views": min(view_counts) if view_counts else 0,
}
def check_organization(pages: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Identify orphaned pages with no labels."""
orphaned = []
for page in pages:
labels = page.get("labels", [])
if not labels:
orphaned.append({
"title": page.get("title", "Untitled"),
"author": page.get("author", "unknown"),
})
total = len(pages)
labeled_ratio = 1 - (len(orphaned) / total) if total > 0 else 1
score = max(0, labeled_ratio * 100)
# Collect label distribution
label_counts = {}
for page in pages:
for label in page.get("labels", []):
label_counts[label] = label_counts.get(label, 0) + 1
return {
"score": score,
"orphaned_pages": orphaned,
"orphaned_count": len(orphaned),
"labeled_count": total - len(orphaned),
"label_distribution": dict(sorted(label_counts.items(), key=lambda x: -x[1])[:20]),
}
def check_size_balance(pages: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Check for oversized or undersized pages."""
oversized = []
undersized = []
word_counts = []
for page in pages:
word_count = page.get("word_count", 0)
word_counts.append(word_count)
if word_count > OVERSIZED_WORD_THRESHOLD:
oversized.append({
"title": page.get("title", "Untitled"),
"word_count": word_count,
"recommendation": "Split into multiple focused pages",
})
elif word_count < 50 and word_count > 0:
undersized.append({
"title": page.get("title", "Untitled"),
"word_count": word_count,
"recommendation": "Expand content or merge with related page",
})
total = len(pages)
well_sized = total - len(oversized) - len(undersized)
balance_ratio = well_sized / total if total > 0 else 1
score = max(0, balance_ratio * 100)
avg_words = sum(word_counts) / total if total > 0 else 0
return {
"score": score,
"oversized_pages": oversized,
"undersized_pages": undersized,
"oversized_count": len(oversized),
"undersized_count": len(undersized),
"average_word_count": round(avg_words),
}
def check_completeness(pages: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Check pages for required metadata completeness."""
incomplete = []
required_fields = ["title", "last_modified", "author"]
for page in pages:
missing = [f for f in required_fields if not page.get(f)]
if missing:
incomplete.append({
"title": page.get("title", "Untitled"),
"missing_fields": missing,
})
total = len(pages)
complete_ratio = 1 - (len(incomplete) / total) if total > 0 else 1
score = max(0, complete_ratio * 100)
return {
"score": score,
"incomplete_pages": incomplete,
"incomplete_count": len(incomplete),
"complete_count": total - len(incomplete),
}
# ---------------------------------------------------------------------------
# Main Analysis
# ---------------------------------------------------------------------------
def analyze_content_health(data: Dict[str, Any]) -> Dict[str, Any]:
"""Run full content audit analysis."""
pages = data.get("pages", [])
if not pages:
return {
"health_score": 0,
"grade": "invalid",
"error": "No pages found in input data",
"dimensions": {},
"action_items": [],
}
reference_date = datetime.now()
# Run all checks
dimensions = {
"freshness": check_stale_pages(pages, reference_date),
"engagement": check_engagement(pages),
"organization": check_organization(pages),
"size_balance": check_size_balance(pages),
"completeness": check_completeness(pages),
}
# Calculate weighted health score
weighted_scores = []
for dim_name, dim_result in dimensions.items():
weight = HEALTH_WEIGHTS.get(dim_name, 0.1)
weighted_scores.append(dim_result["score"] * weight)
health_score = sum(weighted_scores)
if health_score >= 85:
grade = "excellent"
elif health_score >= 70:
grade = "good"
elif health_score >= 55:
grade = "fair"
else:
grade = "poor"
# Generate action items
action_items = _generate_action_items(dimensions)
return {
"health_score": round(health_score, 1),
"grade": grade,
"total_pages": len(pages),
"dimensions": dimensions,
"action_items": action_items,
}
def _generate_action_items(dimensions: Dict[str, Any]) -> List[Dict[str, str]]:
"""Generate prioritized action items from audit findings."""
items = []
# Freshness actions
freshness = dimensions.get("freshness", {})
if freshness.get("outdated_count", 0) > 0:
items.append({
"priority": "high",
"action": f"Review and update or archive {freshness['outdated_count']} outdated pages (>180 days old)",
"category": "freshness",
})
if freshness.get("stale_count", 0) > 0:
items.append({
"priority": "medium",
"action": f"Review {freshness['stale_count']} stale pages (90-180 days old) for relevance",
"category": "freshness",
})
# Engagement actions
engagement = dimensions.get("engagement", {})
if engagement.get("low_engagement_count", 0) > 0:
items.append({
"priority": "medium",
"action": f"Investigate {engagement['low_engagement_count']} low-engagement pages - consider improving discoverability or archiving",
"category": "engagement",
})
# Organization actions
organization = dimensions.get("organization", {})
if organization.get("orphaned_count", 0) > 0:
items.append({
"priority": "medium",
"action": f"Add labels to {organization['orphaned_count']} orphaned pages for better categorization",
"category": "organization",
})
# Size actions
size = dimensions.get("size_balance", {})
if size.get("oversized_count", 0) > 0:
items.append({
"priority": "low",
"action": f"Split {size['oversized_count']} oversized pages (>5000 words) into focused sub-pages",
"category": "size",
})
# Completeness actions
completeness = dimensions.get("completeness", {})
if completeness.get("incomplete_count", 0) > 0:
items.append({
"priority": "low",
"action": f"Fill in missing metadata for {completeness['incomplete_count']} incomplete pages",
"category": "completeness",
})
return items
def _parse_date(date_str: str) -> Optional[datetime]:
"""Parse date string in common formats."""
formats = [
"%Y-%m-%d",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%dT%H:%M:%SZ",
"%Y-%m-%dT%H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S.%fZ",
"%d/%m/%Y",
"%m/%d/%Y",
]
for fmt in formats:
try:
return datetime.strptime(date_str, fmt)
except ValueError:
continue
return None
# ---------------------------------------------------------------------------
# Output Formatting
# ---------------------------------------------------------------------------
def format_text_output(result: Dict[str, Any]) -> str:
"""Format results as readable text report."""
lines = []
lines.append("=" * 60)
lines.append("CONTENT AUDIT REPORT")
lines.append("=" * 60)
lines.append("")
if "error" in result:
lines.append(f"ERROR: {result['error']}")
return "\n".join(lines)
lines.append("HEALTH SUMMARY")
lines.append("-" * 30)
lines.append(f"Health Score: {result['health_score']}/100")
lines.append(f"Grade: {result['grade'].title()}")
lines.append(f"Total Pages Analyzed: {result['total_pages']}")
lines.append("")
# Dimension scores
lines.append("DIMENSION SCORES")
lines.append("-" * 30)
for dim_name, dim_data in result.get("dimensions", {}).items():
weight = HEALTH_WEIGHTS.get(dim_name, 0)
lines.append(f"{dim_name.replace('_', ' ').title()} (Weight: {weight:.0%})")
lines.append(f" Score: {dim_data['score']:.1f}/100")
if dim_name == "freshness":
lines.append(f" Stale: {dim_data.get('stale_count', 0)}, Outdated: {dim_data.get('outdated_count', 0)}, Fresh: {dim_data.get('fresh_count', 0)}")
elif dim_name == "engagement":
lines.append(f" Low Engagement: {dim_data.get('low_engagement_count', 0)}, Avg Views: {dim_data.get('average_views', 0)}")
elif dim_name == "organization":
lines.append(f" Orphaned (no labels): {dim_data.get('orphaned_count', 0)}, Labeled: {dim_data.get('labeled_count', 0)}")
elif dim_name == "size_balance":
lines.append(f" Oversized: {dim_data.get('oversized_count', 0)}, Undersized: {dim_data.get('undersized_count', 0)}, Avg Words: {dim_data.get('average_word_count', 0)}")
elif dim_name == "completeness":
lines.append(f" Incomplete: {dim_data.get('incomplete_count', 0)}, Complete: {dim_data.get('complete_count', 0)}")
lines.append("")
# Action items
action_items = result.get("action_items", [])
if action_items:
lines.append("ACTION ITEMS")
lines.append("-" * 30)
for i, item in enumerate(action_items, 1):
priority = item["priority"].upper()
lines.append(f"{i}. [{priority}] {item['action']}")
lines.append("")
return "\n".join(lines)
def format_json_output(result: Dict[str, Any]) -> Dict[str, Any]:
"""Format results as JSON."""
return result
# ---------------------------------------------------------------------------
# CLI Interface
# ---------------------------------------------------------------------------
def main() -> int:
"""Main CLI entry point."""
parser = argparse.ArgumentParser(
description="Analyze Confluence page inventory for content health"
)
parser.add_argument(
"pages_file",
help="JSON file with page list (title, last_modified, view_count, author, labels, word_count)",
)
parser.add_argument(
"--format",
choices=["text", "json"],
default="text",
help="Output format (default: text)",
)
args = parser.parse_args()
try:
with open(args.pages_file, "r") as f:
data = json.load(f)
result = analyze_content_health(data)
if args.format == "json":
print(json.dumps(format_json_output(result), indent=2))
else:
print(format_text_output(result))
return 0
except FileNotFoundError:
print(f"Error: File '{args.pages_file}' not found", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in '{args.pages_file}': {e}", file=sys.stderr)
return 1
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())
FILE:scripts/space_structure_generator.py
#!/usr/bin/env python3
"""
Space Structure Generator
Generates recommended Confluence space hierarchy from team or project
descriptions. Produces page tree structures, labels, and permission
suggestions based on team type and size.
Usage:
python space_structure_generator.py team_info.json
python space_structure_generator.py team_info.json --format json
"""
import argparse
import json
import sys
from typing import Any, Dict, List, Optional
# ---------------------------------------------------------------------------
# Space Templates
# ---------------------------------------------------------------------------
BASE_SECTIONS = [
{
"title": "Home",
"description": "Space landing page with quick links and team overview",
"labels": ["home", "landing"],
"children": [],
},
{
"title": "Getting Started",
"description": "Onboarding guide for new team members",
"labels": ["onboarding", "getting-started"],
"children": [
{"title": "Team Charter", "labels": ["charter"]},
{"title": "Tools & Access", "labels": ["tools", "access"]},
{"title": "Communication Guidelines", "labels": ["communication"]},
{"title": "Key Contacts", "labels": ["contacts"]},
],
},
{
"title": "Meeting Notes",
"description": "Recurring and ad-hoc meeting documentation",
"labels": ["meetings"],
"children": [
{"title": "Weekly Standups", "labels": ["standup", "recurring"]},
{"title": "Team Syncs", "labels": ["sync", "recurring"]},
{"title": "Ad-hoc Meetings", "labels": ["ad-hoc"]},
],
},
{
"title": "Templates",
"description": "Reusable page templates for the team",
"labels": ["templates"],
"children": [],
},
{
"title": "Archive",
"description": "Archived and deprecated content",
"labels": ["archive"],
"children": [],
},
]
TEAM_TYPE_SECTIONS = {
"engineering": [
{
"title": "Architecture",
"description": "System architecture, design decisions, and technical standards",
"labels": ["architecture", "technical"],
"children": [
{"title": "Architecture Decision Records", "labels": ["adr", "decisions"]},
{"title": "System Design Documents", "labels": ["design", "system"]},
{"title": "API Documentation", "labels": ["api", "reference"]},
{"title": "Tech Stack", "labels": ["tech-stack"]},
],
},
{
"title": "Development",
"description": "Development workflows, coding standards, and CI/CD",
"labels": ["development"],
"children": [
{"title": "Coding Standards", "labels": ["standards", "code"]},
{"title": "Git Workflow", "labels": ["git", "workflow"]},
{"title": "CI/CD Pipeline", "labels": ["ci-cd", "devops"]},
{"title": "Environment Setup", "labels": ["environment", "setup"]},
],
},
{
"title": "Runbooks",
"description": "Operational runbooks and incident response",
"labels": ["runbooks", "operations"],
"children": [
{"title": "Incident Response", "labels": ["incident", "response"]},
{"title": "Deployment Procedures", "labels": ["deployment"]},
{"title": "Troubleshooting Guides", "labels": ["troubleshooting"]},
],
},
],
"product": [
{
"title": "Strategy",
"description": "Product vision, roadmap, and strategic planning",
"labels": ["strategy", "product"],
"children": [
{"title": "Product Vision", "labels": ["vision"]},
{"title": "Roadmap", "labels": ["roadmap"]},
{"title": "OKRs & Goals", "labels": ["okr", "goals"]},
{"title": "Competitive Analysis", "labels": ["competitive", "analysis"]},
],
},
{
"title": "Research",
"description": "User research, personas, and market analysis",
"labels": ["research"],
"children": [
{"title": "User Personas", "labels": ["personas"]},
{"title": "User Interview Notes", "labels": ["interviews", "research"]},
{"title": "Survey Results", "labels": ["surveys"]},
{"title": "Usability Testing", "labels": ["usability", "testing"]},
],
},
{
"title": "Requirements",
"description": "Product requirements and feature specifications",
"labels": ["requirements", "specs"],
"children": [
{"title": "Feature Specifications", "labels": ["features", "specs"]},
{"title": "User Stories", "labels": ["user-stories"]},
{"title": "Acceptance Criteria", "labels": ["acceptance-criteria"]},
],
},
],
"marketing": [
{
"title": "Strategy",
"description": "Marketing strategy, brand guidelines, and campaign plans",
"labels": ["strategy", "marketing"],
"children": [
{"title": "Brand Guidelines", "labels": ["brand", "guidelines"]},
{"title": "Marketing Plan", "labels": ["plan"]},
{"title": "Target Audiences", "labels": ["audience", "targeting"]},
{"title": "Channel Strategy", "labels": ["channels"]},
],
},
{
"title": "Campaigns",
"description": "Active and past campaign documentation",
"labels": ["campaigns"],
"children": [
{"title": "Active Campaigns", "labels": ["active"]},
{"title": "Campaign Results", "labels": ["results", "analytics"]},
{"title": "Campaign Templates", "labels": ["templates"]},
],
},
{
"title": "Content",
"description": "Content calendar, assets, and style guides",
"labels": ["content"],
"children": [
{"title": "Content Calendar", "labels": ["calendar"]},
{"title": "Content Assets", "labels": ["assets"]},
{"title": "Style Guide", "labels": ["style-guide"]},
],
},
],
"project": [
{
"title": "Project Overview",
"description": "Project charter, scope, and stakeholders",
"labels": ["project", "overview"],
"children": [
{"title": "Project Charter", "labels": ["charter"]},
{"title": "Scope & Deliverables", "labels": ["scope", "deliverables"]},
{"title": "Stakeholder Map", "labels": ["stakeholders"]},
{"title": "Timeline & Milestones", "labels": ["timeline", "milestones"]},
],
},
{
"title": "Status & Reporting",
"description": "Project status updates and reports",
"labels": ["status", "reporting"],
"children": [
{"title": "Weekly Status Reports", "labels": ["status", "weekly"]},
{"title": "Risk Register", "labels": ["risks"]},
{"title": "Decision Log", "labels": ["decisions"]},
],
},
{
"title": "Resources",
"description": "Project resources, documentation, and references",
"labels": ["resources"],
"children": [
{"title": "Technical Documentation", "labels": ["technical", "docs"]},
{"title": "Vendor Information", "labels": ["vendor"]},
{"title": "Budget & Financials", "labels": ["budget"]},
],
},
],
}
# Permission suggestions by team type
PERMISSION_TEMPLATES = {
"engineering": {
"admins": ["team-leads", "engineering-managers"],
"contributors": ["developers", "qa-engineers"],
"viewers": ["product-team", "stakeholders"],
"restrictions": [
"Restrict 'Runbooks' section to engineering team only",
"Allow product team view-only access to Architecture",
],
},
"product": {
"admins": ["product-managers", "product-leads"],
"contributors": ["product-designers", "product-analysts"],
"viewers": ["engineering-team", "marketing-team", "stakeholders"],
"restrictions": [
"Restrict 'Research' raw data to product team only",
"Share 'Strategy' with leadership and stakeholders",
],
},
"marketing": {
"admins": ["marketing-managers", "marketing-leads"],
"contributors": ["content-creators", "designers"],
"viewers": ["sales-team", "product-team"],
"restrictions": [
"Restrict campaign budgets to marketing leadership",
"Share brand guidelines broadly",
],
},
"project": {
"admins": ["project-managers"],
"contributors": ["project-team-members"],
"viewers": ["stakeholders", "sponsors"],
"restrictions": [
"Restrict 'Budget & Financials' to project managers and sponsors",
"Share status reports with all stakeholders",
],
},
}
# ---------------------------------------------------------------------------
# Structure Generator
# ---------------------------------------------------------------------------
def generate_space_structure(team_info: Dict[str, Any]) -> Dict[str, Any]:
"""Generate Confluence space structure from team information."""
team_name = team_info.get("name", "Team")
team_type = team_info.get("type", "project").lower()
team_size = team_info.get("size", 5)
projects = team_info.get("projects", [])
if team_type not in TEAM_TYPE_SECTIONS:
team_type = "project"
# Build page tree
page_tree = []
# Add base sections
for section in BASE_SECTIONS:
page_tree.append(_deep_copy_section(section))
# Add team-type-specific sections
type_sections = TEAM_TYPE_SECTIONS.get(team_type, [])
for section in type_sections:
page_tree.append(_deep_copy_section(section))
# Add project-specific pages if projects are listed
if projects:
project_section = {
"title": "Projects",
"description": "Individual project documentation",
"labels": ["projects"],
"children": [],
}
for project in projects:
project_name = project if isinstance(project, str) else project.get("name", "Project")
project_section["children"].append({
"title": project_name,
"labels": ["project", _slugify(project_name)],
"children": [
{"title": f"{project_name} - Overview", "labels": ["overview"]},
{"title": f"{project_name} - Requirements", "labels": ["requirements"]},
{"title": f"{project_name} - Status", "labels": ["status"]},
],
})
page_tree.append(project_section)
# Get permissions
permissions = PERMISSION_TEMPLATES.get(team_type, PERMISSION_TEMPLATES["project"])
# Generate label taxonomy
all_labels = set()
_collect_labels(page_tree, all_labels)
# Build recommendations
recommendations = _generate_recommendations(team_name, team_type, team_size, projects)
return {
"space_key": _generate_space_key(team_name),
"space_name": f"{team_name} Space",
"team_type": team_type,
"team_size": team_size,
"page_tree": page_tree,
"total_pages": _count_pages(page_tree),
"labels": sorted(all_labels),
"permissions": permissions,
"recommendations": recommendations,
}
def _deep_copy_section(section: Dict[str, Any]) -> Dict[str, Any]:
"""Create a deep copy of a section dict."""
copy = {
"title": section["title"],
"labels": list(section.get("labels", [])),
}
if "description" in section:
copy["description"] = section["description"]
if "children" in section:
copy["children"] = [_deep_copy_section(child) for child in section["children"]]
return copy
def _slugify(text: str) -> str:
"""Convert text to a URL-safe slug."""
return text.lower().replace(" ", "-").replace("_", "-")
def _generate_space_key(team_name: str) -> str:
"""Generate a space key from team name."""
words = team_name.upper().split()
if len(words) == 1:
return words[0][:10]
return "".join(w[0] for w in words[:5])
def _collect_labels(pages: List[Dict], labels: set) -> None:
"""Recursively collect all labels from page tree."""
for page in pages:
for label in page.get("labels", []):
labels.add(label)
children = page.get("children", [])
if children:
_collect_labels(children, labels)
def _count_pages(pages: List[Dict]) -> int:
"""Count total pages in tree."""
count = len(pages)
for page in pages:
children = page.get("children", [])
if children:
count += _count_pages(children)
return count
def _generate_recommendations(
team_name: str,
team_type: str,
team_size: int,
projects: List,
) -> List[str]:
"""Generate setup recommendations."""
recs = []
recs.append(f"Create the space with key '{_generate_space_key(team_name)}' and enable the blog feature for announcements.")
if team_size > 10:
recs.append("Large team detected. Consider sub-spaces or restricted sections for sub-teams.")
if team_size <= 3:
recs.append("Small team. Simplify the structure by merging low-traffic sections.")
if len(projects) > 5:
recs.append("Many projects listed. Consider a separate space per project for better isolation.")
if team_type == "engineering":
recs.append("Set up page templates for ADRs, runbooks, and design docs.")
recs.append("Enable the Jira macro on Architecture pages for traceability.")
elif team_type == "product":
recs.append("Set up page templates for feature specs and user research notes.")
recs.append("Link roadmap pages to Jira epics for real-time status.")
elif team_type == "marketing":
recs.append("Enable the calendar macro on the Content Calendar page.")
recs.append("Use labels consistently to enable filtered content views.")
recs.append("Review and update space permissions quarterly.")
recs.append("Archive pages older than 6 months that are no longer actively referenced.")
return recs
# ---------------------------------------------------------------------------
# Output Formatting
# ---------------------------------------------------------------------------
def _format_page_tree(pages: List[Dict], indent: int = 0) -> List[str]:
"""Format page tree as indented text."""
lines = []
prefix = " " * indent
for page in pages:
title = page["title"]
labels = page.get("labels", [])
label_str = f" [{', '.join(labels)}]" if labels else ""
lines.append(f"{prefix}|- {title}{label_str}")
if page.get("description"):
lines.append(f"{prefix} {page['description']}")
children = page.get("children", [])
if children:
lines.extend(_format_page_tree(children, indent + 1))
return lines
def format_text_output(result: Dict[str, Any]) -> str:
"""Format results as readable text report."""
lines = []
lines.append("=" * 60)
lines.append("CONFLUENCE SPACE STRUCTURE")
lines.append("=" * 60)
lines.append("")
lines.append("SPACE INFO")
lines.append("-" * 30)
lines.append(f"Space Name: {result['space_name']}")
lines.append(f"Space Key: {result['space_key']}")
lines.append(f"Team Type: {result['team_type'].title()}")
lines.append(f"Team Size: {result['team_size']}")
lines.append(f"Total Pages: {result['total_pages']}")
lines.append("")
lines.append("PAGE TREE")
lines.append("-" * 30)
lines.extend(_format_page_tree(result["page_tree"]))
lines.append("")
lines.append("LABELS")
lines.append("-" * 30)
lines.append(", ".join(result["labels"]))
lines.append("")
permissions = result.get("permissions", {})
if permissions:
lines.append("PERMISSION SUGGESTIONS")
lines.append("-" * 30)
lines.append(f"Admins: {', '.join(permissions.get('admins', []))}")
lines.append(f"Contributors: {', '.join(permissions.get('contributors', []))}")
lines.append(f"Viewers: {', '.join(permissions.get('viewers', []))}")
for restriction in permissions.get("restrictions", []):
lines.append(f" - {restriction}")
lines.append("")
recommendations = result.get("recommendations", [])
if recommendations:
lines.append("RECOMMENDATIONS")
lines.append("-" * 30)
for i, rec in enumerate(recommendations, 1):
lines.append(f"{i}. {rec}")
return "\n".join(lines)
def format_json_output(result: Dict[str, Any]) -> Dict[str, Any]:
"""Format results as JSON."""
return result
# ---------------------------------------------------------------------------
# CLI Interface
# ---------------------------------------------------------------------------
def main() -> int:
"""Main CLI entry point."""
parser = argparse.ArgumentParser(
description="Generate Confluence space hierarchy from team/project description"
)
parser.add_argument(
"team_file",
help="JSON file with team info (name, size, type, projects)",
)
parser.add_argument(
"--format",
choices=["text", "json"],
default="text",
help="Output format (default: text)",
)
args = parser.parse_args()
try:
with open(args.team_file, "r") as f:
data = json.load(f)
result = generate_space_structure(data)
if args.format == "json":
print(json.dumps(format_json_output(result), indent=2))
else:
print(format_text_output(result))
return 0
except FileNotFoundError:
print(f"Error: File '{args.team_file}' not found", file=sys.stderr)
return 1
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in '{args.team_file}': {e}", file=sys.stderr)
return 1
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())
Skill chuyển hướng các yêu cầu viết nội dung kiểu cũ sang chuyên gia phù hợp như sản xuất nội dung hoặc lập chiến lược.
---
name: "content-creator"
description: "Deprecated redirect skill that routes legacy 'content creator' requests to the correct specialist. Use when a user invokes 'content creator', asks to write a blog post, article, guide, or brand voice analysis (routes to content-production), or asks to plan content, build a topic cluster, or create a content calendar (routes to content-strategy). Does not handle requests directly — identifies user intent and redirects to content-production for writing/SEO/brand-voice tasks or content-strategy for planning tasks."
license: MIT
metadata:
version: 2.0.0
author: Alireza Rezvani
category: marketing
updated: 2026-03-06
status: deprecated
---
# Content Creator → Redirected
> **This skill has been split into two specialist skills.** Use the one that matches your intent:
| You want to... | Use this instead |
|----------------|-----------------|
| **Write** a blog post, article, or guide | [content-production](../content-production/) |
| **Plan** what content to create, topic clusters, calendar | [content-strategy](../content-strategy/) |
| **Analyze brand voice** | [content-production](../content-production/) (includes `brand_voice_analyzer.py`) |
| **Optimize SEO** for existing content | [content-production](../content-production/) (includes `seo_optimizer.py`) |
| **Create social media content** | [social-content](../social-content/) |
## Why the Change
The original `content-creator` tried to do everything: planning, writing, SEO, social, brand voice. That made it a jack of all trades. The specialist skills do each job better:
- **content-production** — Full pipeline: research → brief → draft → optimize → publish. Includes all Python tools from the original content-creator.
- **content-strategy** — Strategic planning: topic clusters, keyword research, content calendars, prioritization frameworks.
## Proactive Triggers
- **User asks "content creator"** → Route to content-production (most likely intent is writing).
- **User asks "content plan" or "what should I write"** → Route to content-strategy.
## Output Artifacts
| When you ask for... | Routed to... |
|---------------------|-------------|
| "Write a blog post" | content-production |
| "Content calendar" | content-strategy |
| "Brand voice analysis" | content-production (`brand_voice_analyzer.py`) |
| "SEO optimization" | content-production (`seo_optimizer.py`) |
## Communication
This is a redirect skill. Route the user to the correct specialist — don't attempt to handle the request here.
## Related Skills
- **content-production**: Full content execution pipeline (successor).
- **content-strategy**: Content planning and topic selection (successor).
- **content-humanizer**: Post-processing AI content to sound authentic.
- **marketing-context**: Foundation context that both successors read.
FILE:assets/content_calendar_template.md
# Content Calendar Template - [Month Year]
## Monthly Goals
- **Traffic Goal**:
- **Lead Generation Goal**:
- **Engagement Goal**:
- **Key Campaign**:
## Week 1: [Date Range]
### Monday [Date]
**Platform**: Blog
**Topic**:
**Keywords**:
**Status**: [ ] Planned [ ] Written [ ] Reviewed [ ] Published
**Owner**:
**Notes**:
**Platform**: LinkedIn
**Type**: Article Share
**Caption**:
**Hashtags**:
**Time**: 10:00 AM
### Tuesday [Date]
**Platform**: Instagram
**Type**: Carousel
**Topic**:
**Visuals**: [ ] Created [ ] Approved
**Caption**:
**Hashtags**:
**Time**: 12:00 PM
### Wednesday [Date]
**Platform**: Email Newsletter
**Subject Line**:
**Segment**:
**CTA**:
**Status**: [ ] Drafted [ ] Designed [ ] Scheduled
### Thursday [Date]
**Platform**: Twitter/X
**Type**: Thread
**Topic**:
**Thread Length**:
**Media**: [ ] Images [ ] GIFs [ ] None
**Time**: 2:00 PM
### Friday [Date]
**Platform**: Multi-channel
**Campaign**:
**Assets Needed**:
- [ ] Blog post
- [ ] Social graphics
- [ ] Email
- [ ] Video
## Week 2: [Date Range]
[Repeat structure]
## Week 3: [Date Range]
[Repeat structure]
## Week 4: [Date Range]
[Repeat structure]
## Content Bank (Ideas for Future)
1.
2.
3.
4.
5.
## Performance Review (End of Month)
### Top Performing Content
1. **Title/Topic**:
- **Metric**:
- **Why it worked**:
2. **Title/Topic**:
- **Metric**:
- **Why it worked**:
### Lessons Learned
-
-
-
### Adjustments for Next Month
-
-
-
## Resource Links
- Brand Guidelines: [Link]
- Asset Library: [Link]
- Analytics Dashboard: [Link]
- Team Calendar: [Link]
FILE:examples/brand_voice_analysis_example.md
# Brand Voice Analysis Example
Demonstration of brand_voice_analyzer.py input and output.
---
## Sample Input
**File: `sample_blog_post.txt`**
```
Hey there! 👋
So, like, we've been doing marketing for a really long time and we've learned SO much about what works. Today I'm gonna share some super cool tips that'll totally transform your business!
First things first - you gotta know your audience. Like, REALLY know them. What do they want? What keeps them up at night? Figure that out and you're golden!
Second, content is king (obviously). But here's the thing - not just any content. You need stuff that actually helps people. Don't just post to post, ya know?
Anyway, hope this helps! Drop a comment if you have questions! 🚀
```
---
## Command
```bash
python scripts/brand_voice_analyzer.py sample_blog_post.txt
```
---
## Sample Output (Text Format)
```
============================================================
BRAND VOICE ANALYSIS RESULTS
============================================================
VOICE PROFILE
------------------------------------------------------------
Formality Score: 25/100 (Casual)
Tone: Conversational, Enthusiastic, Informal
Perspective: Mixed (1st person singular + 2nd person)
Personality Match: The Friend (primary)
READABILITY METRICS
------------------------------------------------------------
Flesch Reading Ease: 78 (Fairly Easy)
Grade Level: 6th Grade
Avg Sentence Length: 12 words
Avg Word Length: 4.2 characters
SENTENCE ANALYSIS
------------------------------------------------------------
Total Sentences: 12
Simple Sentences: 8 (67%)
Compound Sentences: 3 (25%)
Complex Sentences: 1 (8%)
VOCABULARY PATTERNS
------------------------------------------------------------
Filler Words Found: 6 (like, so, really, just, totally, super)
Contractions: 5 (we've, I'm, gonna, you're, don't)
Emoji Usage: 2
Exclamation Points: 4
RECOMMENDATIONS
------------------------------------------------------------
1. [HIGH] Reduce filler words - found 6 instances
Action: Remove "like", "so", "really", "totally", "super"
2. [MEDIUM] Inconsistent perspective - switches between "I" and "we"
Action: Choose one perspective and maintain throughout
3. [MEDIUM] High emoji count for professional content
Action: Limit to 1 emoji or remove entirely for B2B
4. [LOW] Overuse of exclamation points
Action: Replace 3 of 4 with periods for measured tone
VOICE CONSISTENCY SCORE: 62/100
============================================================
```
---
## Sample Output (JSON Format)
```bash
python scripts/brand_voice_analyzer.py sample_blog_post.txt json
```
```json
{
"voice_profile": {
"formality_score": 25,
"formality_level": "Casual",
"tone": ["Conversational", "Enthusiastic", "Informal"],
"perspective": "Mixed",
"personality_archetype": "The Friend"
},
"readability": {
"flesch_reading_ease": 78,
"grade_level": 6,
"avg_sentence_length": 12,
"avg_word_length": 4.2
},
"sentence_analysis": {
"total": 12,
"simple": 8,
"compound": 3,
"complex": 1
},
"vocabulary": {
"filler_words": {
"count": 6,
"instances": ["like", "so", "really", "just", "totally", "super"]
},
"contractions": 5,
"emojis": 2,
"exclamation_points": 4
},
"recommendations": [
{
"priority": "high",
"category": "vocabulary",
"issue": "Excessive filler words",
"action": "Remove casual filler words for professional tone"
},
{
"priority": "medium",
"category": "perspective",
"issue": "Inconsistent perspective",
"action": "Maintain single perspective throughout"
},
{
"priority": "medium",
"category": "formatting",
"issue": "High emoji count",
"action": "Limit emojis for professional content"
},
{
"priority": "low",
"category": "punctuation",
"issue": "Overuse of exclamation points",
"action": "Replace with periods for measured tone"
}
],
"consistency_score": 62
}
```
---
## Revised Content (After Applying Recommendations)
```
We've been helping businesses with marketing for over a decade, and we've
identified key principles that consistently drive results.
Understanding your audience is foundational. What challenges do they face?
What outcomes do they seek? Deep audience knowledge shapes every effective
marketing decision.
Content quality matters more than quantity. Focus on creating resources that
genuinely solve problems for your readers rather than publishing content
solely to maintain a schedule.
Questions about implementing these strategies? Leave a comment below.
```
**Re-analysis Results:**
```
Formality Score: 72/100 (Professional)
Tone: Educational, Confident, Helpful
Perspective: First Person Plural (consistent)
Consistency Score: 91/100
```
FILE:examples/seo_optimization_example.md
# SEO Optimization Example
Demonstration of seo_optimizer.py input and output.
---
## Sample Input
**File: `draft_article.md`**
```markdown
# Marketing Tips
Marketing is important for businesses. Here are some things to know.
## Why Marketing Matters
Companies need marketing. It helps them grow. Marketing brings customers.
## Some Ideas
Try social media. Post content. Use email. Run ads.
## Conclusion
Marketing is good. Do more of it.
```
---
## Command
```bash
python scripts/seo_optimizer.py draft_article.md "content marketing strategy" "content marketing,marketing tips,business growth"
```
---
## Sample Output (Text Format)
```
============================================================
SEO ANALYSIS REPORT
============================================================
PRIMARY KEYWORD: "content marketing strategy"
SECONDARY KEYWORDS: content marketing, marketing tips, business growth
OVERALL SEO SCORE: 32/100 (Poor)
KEYWORD ANALYSIS
------------------------------------------------------------
Primary Keyword Density: 0.0% (Target: 1-3%)
Status: NOT FOUND in content
Secondary Keyword Usage:
- "content marketing": 0 occurrences (Target: 3-5)
- "marketing tips": 1 occurrence (in title only)
- "business growth": 0 occurrences (Target: 2-3)
Keyword Placement Check:
✗ Primary keyword NOT in title
✗ Primary keyword NOT in first paragraph
✗ Primary keyword NOT in H2 headings
✗ Primary keyword NOT in conclusion
CONTENT STRUCTURE
------------------------------------------------------------
Word Count: 67 words
Status: CRITICAL - Below minimum (Target: 1,500+)
Heading Structure:
H1: 1 (Good)
H2: 3 (Good)
H3: 0 (Consider adding for depth)
Paragraph Analysis:
- Average length: 12 words (Too short - Target: 40-80)
- Total paragraphs: 6
READABILITY
------------------------------------------------------------
Flesch Reading Ease: 82 (Easy)
Note: May be too simple for B2B audience
META ELEMENTS
------------------------------------------------------------
Meta Title: Not specified
Suggestion: "Content Marketing Strategy: 10 Proven Tips for 2025"
Meta Description: Not found
Suggestion: "Discover actionable content marketing strategies to drive
business growth. Learn proven techniques for content that converts."
INTERNAL/EXTERNAL LINKS
------------------------------------------------------------
Internal Links: 0 (Target: 2-3)
External Links: 0 (Target: 1-2 authoritative sources)
RECOMMENDATIONS (Priority Order)
------------------------------------------------------------
[P0] CRITICAL - Content Length
Issue: 67 words is severely below minimum
Action: Expand to 1,500-2,500 words with detailed sections
[P0] CRITICAL - Missing Primary Keyword
Issue: "content marketing strategy" not found anywhere
Action: Include in title, first paragraph, 2 H2s, and conclusion
[P1] HIGH - Thin Content Sections
Issue: Paragraphs average 12 words
Action: Expand each section with examples, data, and actionable steps
[P1] HIGH - Missing Internal Links
Issue: No links to related content
Action: Add 2-3 links to relevant articles
[P2] MEDIUM - No Meta Description
Issue: Missing meta description
Action: Add 150-160 character description with primary keyword
[P2] MEDIUM - Missing H3 Subheadings
Issue: No H3s for content depth
Action: Add H3s under each H2 for better structure
============================================================
```
---
## Sample Output (JSON Format)
```bash
python scripts/seo_optimizer.py draft_article.md "content marketing strategy" --json
```
```json
{
"overall_score": 32,
"grade": "Poor",
"primary_keyword": "content marketing strategy",
"keyword_analysis": {
"primary_density": 0.0,
"target_density": "1-3%",
"primary_found": false,
"secondary_keywords": {
"content marketing": {"count": 0, "target": "3-5"},
"marketing tips": {"count": 1, "target": "2-3"},
"business growth": {"count": 0, "target": "2-3"}
},
"placement": {
"in_title": false,
"in_first_paragraph": false,
"in_h2_headings": false,
"in_conclusion": false
}
},
"content_structure": {
"word_count": 67,
"min_recommended": 1500,
"headings": {"h1": 1, "h2": 3, "h3": 0},
"paragraphs": {"count": 6, "avg_length": 12}
},
"readability": {
"flesch_score": 82,
"level": "Easy"
},
"meta": {
"title": null,
"description": null,
"suggested_title": "Content Marketing Strategy: 10 Proven Tips for 2025",
"suggested_description": "Discover actionable content marketing strategies to drive business growth. Learn proven techniques for content that converts."
},
"links": {
"internal": 0,
"external": 0,
"target_internal": "2-3",
"target_external": "1-2"
},
"recommendations": [
{
"priority": "P0",
"category": "content_length",
"issue": "Content severely below minimum word count",
"action": "Expand to 1,500-2,500 words"
},
{
"priority": "P0",
"category": "keyword",
"issue": "Primary keyword not found",
"action": "Include in title, first paragraph, H2s, conclusion"
},
{
"priority": "P1",
"category": "content_depth",
"issue": "Thin content sections",
"action": "Expand with examples, data, actionable steps"
},
{
"priority": "P1",
"category": "links",
"issue": "No internal links",
"action": "Add 2-3 relevant internal links"
}
]
}
```
---
## Optimized Content (After Applying Recommendations)
```markdown
# Content Marketing Strategy: 10 Proven Techniques for Business Growth
A well-executed content marketing strategy separates thriving businesses from
those struggling to gain visibility. This comprehensive guide covers the
essential techniques that drive measurable results.
## Why Content Marketing Strategy Matters for Business Growth
Companies investing in strategic content marketing see 3x more leads than
those relying solely on paid advertising. Content marketing builds lasting
assets that continue generating value long after publication.
The compounding effect of quality content creates sustainable business growth:
- Organic search traffic increases over time
- Brand authority strengthens with each published piece
- Customer acquisition costs decrease as content library grows
### The ROI of Strategic Content
According to Content Marketing Institute research, businesses with documented
content strategies are 313% more likely to report success than those without.
[Continue for 1,500+ words with detailed sections...]
## Conclusion: Building Your Content Marketing Strategy
Implementing these content marketing techniques positions your business for
sustained growth. Start with audience research, create a documented strategy,
and commit to consistent execution.
Related reading: [Link to internal article on content calendars]
```
**Re-analysis Results:**
```
OVERALL SEO SCORE: 87/100 (Good)
✓ Primary keyword density: 1.8%
✓ Keyword in title, first paragraph, H2s, conclusion
✓ Word count: 1,847 words
✓ Meta description: Present (156 characters)
✓ Internal links: 2
✓ External links: 1 (authoritative source)
```
FILE:references/analytics_guide.md
# Content Analytics & Performance Metrics
Comprehensive guide for tracking, measuring, and optimizing content performance.
---
## Table of Contents
- [Content Metrics](#content-metrics)
- [Engagement Metrics](#engagement-metrics)
- [Business Metrics](#business-metrics)
- [Platform-Specific Analytics](#platform-specific-analytics)
- [Reporting Frameworks](#reporting-frameworks)
- [Attribution Models](#attribution-models)
---
## Content Metrics
Track these KPIs to measure content reach and consumption.
### Traffic Metrics
| Metric | Target | What It Tells You |
|--------|--------|-------------------|
| Organic traffic | +10% MoM | SEO effectiveness |
| Page views | Varies by content type | Raw consumption volume |
| Unique visitors | +5% MoM | Audience growth |
| Sessions per user | 1.5+ | Content stickiness |
### Consumption Metrics
| Metric | Target | What It Tells You |
|--------|--------|-------------------|
| Average time on page | 3+ min for long-form | Content depth engagement |
| Bounce rate | <60% | Content relevance |
| Scroll depth | 70%+ | Content holding attention |
| Pages per session | 2+ | Internal linking success |
### SEO Metrics
| Metric | Target | What It Tells You |
|--------|--------|-------------------|
| Keyword rankings | Top 10 | Search visibility |
| Backlinks earned | +5/month | Content authority |
| Domain authority | Steady growth | Overall site strength |
| Featured snippets | Track position | SERP prominence |
---
## Engagement Metrics
Measure how audiences interact with content.
### Social Engagement
| Metric | Benchmark | Calculation |
|--------|-----------|-------------|
| Engagement rate | 1-3% (LinkedIn) | (Likes + Comments + Shares) / Impressions × 100 |
| Share rate | 0.5-1% | Shares / Reach × 100 |
| Save rate | 1-2% (Instagram) | Saves / Reach × 100 |
| Comment rate | 0.1-0.5% | Comments / Reach × 100 |
### Email Engagement
| Metric | Benchmark | What It Tells You |
|--------|-----------|-------------------|
| Open rate | 20-25% | Subject line effectiveness |
| Click-through rate | 2-5% | Content relevance |
| Unsubscribe rate | <0.5% | Audience fit |
| Forward rate | 0.1-0.3% | Content share-worthiness |
### Community Engagement
| Metric | What to Track |
|--------|---------------|
| Comments and discussions | Volume and sentiment |
| User-generated content | Submissions and quality |
| Community growth | New members per week |
| Active participation | % of members engaging |
---
## Business Metrics
Connect content performance to business outcomes.
### Lead Generation
| Metric | Calculation | Target |
|--------|-------------|--------|
| Content-attributed leads | Leads from content CTAs | Track by content piece |
| Form submissions | Total completions | +5% MoM |
| Lead quality score | MQL/total leads | 30%+ MQL rate |
| Cost per lead | Spend / Leads | Below industry average |
### Conversion Metrics
| Metric | Calculation | Target |
|--------|-------------|--------|
| Conversion rate | Conversions / Visitors × 100 | 2-5% |
| Revenue attribution | $ tied to content | Track by piece |
| Customer acquisition cost | Total cost / New customers | Decreasing trend |
| Content ROI | (Revenue - Cost) / Cost × 100 | 300%+ for evergreen |
### Customer Metrics
| Metric | What It Tells You |
|--------|-------------------|
| Customer lifetime value | Long-term content impact |
| Retention rate | Content's nurturing effectiveness |
| NPS from content consumers | Content quality perception |
| Support ticket reduction | Educational content success |
---
## Platform-Specific Analytics
### Blog Analytics (Google Analytics 4)
**Key Reports:**
- Landing pages report: Top entry content
- Engagement report: Time, bounces, conversions
- Traffic acquisition: Content discovery sources
- User paths: Content journey mapping
**Dimensions to Track:**
- Page path
- Source/medium
- Device category
- User type (new vs returning)
### Social Media Analytics
**LinkedIn:**
- Post impressions and reach
- Follower demographics
- Click-through rate on links
- Article read time
**Twitter/X:**
- Impressions and engagements
- Profile visits from tweets
- Link clicks
- Follower growth rate
**Instagram:**
- Reach vs impressions
- Saves and shares (high-value signals)
- Story completion rate
- Reel performance vs feed
### Email Analytics
**Track per Campaign:**
- Send volume and deliverability
- Open and click rates by segment
- Conversion path from email
- List growth and churn
---
## Reporting Frameworks
### Weekly Content Report
```
WEEK OF: [Date Range]
TOP PERFORMERS
1. [Content Title] - [Key Metric]
2. [Content Title] - [Key Metric]
3. [Content Title] - [Key Metric]
TRAFFIC SUMMARY
- Total sessions: [#]
- Organic traffic: [#] ([+/-]% WoW)
- Social traffic: [#] ([+/-]% WoW)
ENGAGEMENT HIGHLIGHTS
- Avg engagement rate: [%]
- Total comments: [#]
- Shares: [#]
LEADS GENERATED
- Content-attributed: [#]
- Top converting piece: [Title]
NEXT WEEK PRIORITIES
1. [Action item]
2. [Action item]
```
### Monthly Content Report
```
MONTH: [Month Year]
EXECUTIVE SUMMARY
[2-3 sentences on overall performance]
CONTENT PRODUCTION
- Published: [#] pieces
- By type: [Blog: #, Social: #, Email: #]
- On schedule: [Yes/No]
PERFORMANCE DASHBOARD
| Metric | This Month | Last Month | Change |
|---------------------|------------|------------|--------|
| Total traffic | | | |
| Organic traffic | | | |
| Engagement rate | | | |
| Leads generated | | | |
| Conversion rate | | | |
TOP 5 CONTENT PIECES
[Ranked by primary KPI]
INSIGHTS & LEARNINGS
- What worked: [observation]
- What didn't: [observation]
- Opportunities: [observation]
NEXT MONTH FOCUS
1. [Strategic priority]
2. [Content initiative]
3. [Optimization goal]
```
### Quarterly Business Review
```
Q[#] [Year] CONTENT PERFORMANCE
STRATEGIC ALIGNMENT
- Business goal: [Goal]
- Content contribution: [How content supported]
QUARTERLY METRICS
| KPI | Target | Actual | Status |
|------------------------|--------|--------|--------|
| Traffic growth | | | |
| Lead generation | | | |
| Conversion rate | | | |
| Revenue attribution | | | |
CONTENT AUDIT RESULTS
- Total pieces published: [#]
- High performers: [#]
- Needs optimization: [#]
- Candidates for retirement: [#]
ROI ANALYSIS
- Total content investment: $[X]
- Attributed revenue: $[Y]
- Content ROI: [%]
COMPETITIVE ANALYSIS
[How content stacks against competitors]
NEXT QUARTER ROADMAP
[Strategic initiatives and targets]
```
---
## Attribution Models
### First-Touch Attribution
**Use When:** Measuring top-of-funnel content effectiveness
**How It Works:** Credits the first content piece that brought a user in
**Best For:**
- Brand awareness campaigns
- SEO content performance
- Social media reach measurement
### Last-Touch Attribution
**Use When:** Measuring bottom-of-funnel conversion content
**How It Works:** Credits the last content before conversion
**Best For:**
- Product pages
- Case studies
- Demo request pages
### Multi-Touch Attribution
**Use When:** Understanding full content journey impact
**Linear Model:**
- Equal credit to all touchpoints
- Simple but may over-credit low-value touches
**Time-Decay Model:**
- More credit to recent touches
- Good for short sales cycles
**Position-Based Model:**
- 40% first touch, 40% last touch, 20% middle
- Balanced view of journey
### Content-Specific Attribution
**For Blog Content:**
1. Track assisted conversions in GA4
2. Map content to funnel stage
3. Weight by stage importance
**For Social Content:**
1. Use UTM parameters consistently
2. Track view-through conversions
3. Monitor social-assisted conversions
**For Email Content:**
1. Track email-attributed revenue
2. Monitor nurture sequence effectiveness
3. Measure reactivation campaigns
---
## Analytics Setup Checklist
### Essential Tracking
- [ ] Google Analytics 4 configured
- [ ] Conversion events defined
- [ ] UTM parameter system documented
- [ ] Social pixel tracking enabled
- [ ] Email tracking integrated
- [ ] CRM connected for lead tracking
### Advanced Setup
- [ ] Enhanced ecommerce tracking
- [ ] Custom dimensions for content attributes
- [ ] Automated reporting dashboards
- [ ] A/B testing infrastructure
- [ ] Heat mapping tools (Hotjar, Clarity)
- [ ] Attribution model configured
### Data Governance
- [ ] Naming conventions documented
- [ ] Data retention policies set
- [ ] Privacy compliance verified
- [ ] Access controls configured
- [ ] Regular data audits scheduled
FILE:references/brand_guidelines.md
# Brand Voice & Style Guidelines
Comprehensive framework for establishing and maintaining consistent brand voice across all content.
---
## Table of Contents
- [Voice Dimensions](#1-voice-dimensions)
- [Brand Personality Archetypes](#2-brand-personality-archetypes)
- [Writing Principles](#3-writing-principles)
- [Language Guidelines](#4-language-guidelines)
- [Content Structure Templates](#5-content-structure-templates)
- [Messaging Pillars](#6-messaging-pillars)
- [Audience Personas](#7-audience-personas)
- [Channel-Specific Guidelines](#8-channel-specific-guidelines)
- [Grammar & Mechanics](#9-grammar--mechanics)
- [Inclusivity Guidelines](#10-inclusivity-guidelines)
- [Quick Reference Checklist](#quick-reference-checklist)
---
## Brand Voice Framework
### 1. Voice Dimensions
#### Formality Spectrum
- **Formal**: Legal documents, investor communications, crisis responses
- **Professional**: B2B content, whitepapers, case studies
- **Conversational**: Blog posts, social media, email newsletters
- **Casual**: Community engagement, behind-the-scenes content
#### Tone Attributes
Choose 3-5 primary attributes for your brand:
- **Authoritative**: Position as industry expert
- **Friendly**: Approachable and warm
- **Innovative**: Forward-thinking and creative
- **Trustworthy**: Reliable and transparent
- **Inspiring**: Motivational and uplifting
- **Educational**: Informative and helpful
- **Witty**: Clever and entertaining (use sparingly)
#### Perspective
- **First Person Plural (We/Our)**: Creates partnership feeling
- **Second Person (You/Your)**: Direct and engaging
- **Third Person**: Objective and professional
### 2. Brand Personality Archetypes
Choose one primary and one secondary archetype:
**The Expert**
- Tone: Knowledgeable, confident, informative
- Content: Data-driven, research-backed, educational
- Example: "Our research shows that 87% of businesses..."
**The Friend**
- Tone: Warm, supportive, conversational
- Content: Relatable, helpful, encouraging
- Example: "We get it - marketing can be overwhelming..."
**The Innovator**
- Tone: Visionary, bold, forward-thinking
- Content: Cutting-edge, disruptive, trendsetting
- Example: "The future of marketing is here..."
**The Guide**
- Tone: Wise, patient, instructive
- Content: Step-by-step, clear, actionable
- Example: "Let's walk through this together..."
**The Motivator**
- Tone: Energetic, positive, inspiring
- Content: Empowering, action-oriented, transformative
- Example: "You have the power to transform your business..."
### 3. Writing Principles
#### Clarity First
- Use simple words when possible
- Break complex ideas into digestible pieces
- Lead with the main point
- Use active voice (80% of the time)
#### Customer-Centric
- Focus on benefits, not features
- Address pain points directly
- Use "you" more than "we"
- Include customer success stories
#### Consistency
- Maintain voice across all channels
- Use approved terminology
- Follow formatting standards
- Apply style rules uniformly
### 4. Language Guidelines
#### Words We Use
- **Action verbs**: Transform, accelerate, optimize, unlock, elevate
- **Positive descriptors**: Seamless, powerful, intuitive, strategic
- **Outcome-focused**: Results, growth, success, impact, ROI
#### Words We Avoid
- **Jargon**: Synergy, leverage (as verb), bandwidth (for availability)
- **Overused**: Innovative, disruptive, cutting-edge (unless truly applicable)
- **Weak**: Very, really, just, maybe, hopefully
- **Negative**: Can't, won't, impossible, problem (use "challenge")
### 5. Content Structure Templates
#### Blog Post Structure
1. **Hook** (1-2 sentences): Grab attention with a question, statistic, or bold statement
2. **Context** (1 paragraph): Explain why this matters now
3. **Main Content** (3-5 sections): Deliver value with clear subheadings
4. **Conclusion** (1 paragraph): Summarize key points
5. **Call to Action**: Clear next step for readers
#### Social Media Framework
- **LinkedIn**: Professional insights, industry news, thought leadership
- **Twitter/X**: Quick tips, engaging questions, thread stories
- **Instagram**: Visual storytelling, behind-the-scenes, inspiration
- **Facebook**: Community building, longer narratives, events
### 6. Messaging Pillars
Define 3-4 core themes that appear consistently:
1. **Innovation & Technology**
- AI-powered solutions
- Data-driven insights
- Future-ready strategies
2. **Customer Success**
- Real results and ROI
- Partnership approach
- Tailored solutions
3. **Expertise & Trust**
- Industry leadership
- Proven methodologies
- Transparent communication
4. **Growth & Transformation**
- Scaling businesses
- Digital transformation
- Continuous improvement
### 7. Audience Personas
#### Decision Makers (C-Suite)
- **Tone**: Professional, strategic, ROI-focused
- **Content**: High-level insights, business impact, competitive advantages
- **Pain Points**: Growth, efficiency, competition
#### Practitioners (Marketing Managers)
- **Tone**: Practical, supportive, educational
- **Content**: How-to guides, best practices, tools
- **Pain Points**: Time, resources, skills
#### Innovators (Early Adopters)
- **Tone**: Exciting, cutting-edge, visionary
- **Content**: Trends, new features, future predictions
- **Pain Points**: Staying ahead, differentiation
### 8. Channel-Specific Guidelines
#### Website Copy
- Headlines: 6-12 words, benefit-focused
- Body: Short paragraphs (2-3 sentences)
- CTAs: Action-oriented, specific
#### Email Marketing
- Subject Lines: 30-50 characters, personalized
- Preview Text: Complement subject, add urgency
- Body: Scannable, one main message
#### Blog Content
- Title: Include primary keyword, under 60 characters
- Introduction: Hook within first 50 words
- Sections: 200-300 words each
- Lists: 5-7 items optimal
### 9. Grammar & Mechanics
#### Punctuation
- Oxford comma: Always use
- Em dashes: For emphasis—like this
- Exclamation points: Maximum one per piece
#### Capitalization
- Headlines: Title Case for H1, Sentence case for H2-H6
- Product names: As trademarked
- Job titles: Lowercase unless before name
#### Numbers
- Spell out one through nine
- Use numerals for 10 and above
- Always use numerals for percentages
### 10. Inclusivity Guidelines
- Use gender-neutral language
- Avoid idioms that don't translate
- Consider global audience
- Ensure accessibility in formatting
- Represent diverse perspectives
## Quick Reference Checklist
Before publishing any content, verify:
- [ ] Matches brand voice and tone
- [ ] Free of jargon and complex terms
- [ ] Includes clear value proposition
- [ ] Has appropriate CTA
- [ ] Follows grammar guidelines
- [ ] Mobile-friendly formatting
- [ ] Accessible to all audiences
- [ ] Proofread and fact-checked
FILE:references/content_frameworks.md
# Content Creation Frameworks & Templates
Ready-to-use templates for blog posts, social media, email marketing, video scripts, and content planning.
---
## Table of Contents
- [Blog Post Templates](#1-blog-post-templates)
- [Social Media Templates](#2-social-media-templates)
- [Email Marketing Templates](#3-email-marketing-templates)
- [Content Planning Frameworks](#4-content-planning-frameworks)
- [SEO Content Framework](#5-seo-content-framework)
- [Video Script Templates](#6-video-script-templates)
- [Content Repurposing Matrix](#7-content-repurposing-matrix)
- [Quick-Start Checklists](#quick-start-checklists)
---
## Content Types & Templates
### 1. Blog Post Templates
#### How-To Guide Template
```markdown
# How to [Achieve Desired Outcome] in [Timeframe]
## Introduction
- Hook: Question or surprising fact
- Problem statement
- What reader will learn
- Why it matters now
## Prerequisites/What You'll Need
- Tool/Resource 1
- Tool/Resource 2
- Estimated time
## Step 1: [Action]
- Clear instruction
- Why this step matters
- Common mistakes to avoid
- Visual aid or example
## Step 2: [Action]
[Repeat structure]
## Step 3: [Action]
[Repeat structure]
## Troubleshooting Common Issues
### Issue 1: [Problem]
**Solution**: [Fix]
### Issue 2: [Problem]
**Solution**: [Fix]
## Results You Can Expect
- Immediate outcomes
- Long-term benefits
- Success metrics
## Next Steps
- Advanced techniques
- Related guides
- CTA for product/service
## Conclusion
- Recap key points
- Reinforce value
- Final encouragement
```
#### Listicle Template
```markdown
# [Number] [Adjective] Ways to [Achieve Goal] in [Year]
## Introduction
- Context/trend driving this topic
- Promise of what reader gains
- Credibility statement
## 1. [First Item - Most Important]
**Why it matters**: [Brief explanation]
**How to implement**: [2-3 actionable steps]
**Pro tip**: [Expert insight]
**Example**: [Real-world application]
## 2. [Second Item]
[Repeat structure]
[Continue for all items]
## Bonus Tip: [Overdelivery]
[Something extra valuable]
## Bringing It All Together
- How items work synergistically
- Priority order for implementation
- Expected timeline for results
## Your Action Plan
1. Start with [easiest item]
2. Progress to [next steps]
3. Measure [metrics]
## Conclusion & CTA
```
#### Case Study Template
```markdown
# How [Company] Achieved [Result] Using [Solution]
## Executive Summary
- Company overview
- Challenge faced
- Solution implemented
- Key results (3 metrics)
## The Challenge
### Background
- Industry context
- Company situation
- Previous attempts
### Specific Pain Points
- Pain point 1
- Pain point 2
- Pain point 3
## The Solution
### Strategy Development
- Discovery process
- Strategic approach
- Why this solution
### Implementation
- Phase 1: [Timeline & Actions]
- Phase 2: [Timeline & Actions]
- Phase 3: [Timeline & Actions]
## The Results
### Quantitative Outcomes
- Metric 1: X% increase
- Metric 2: $Y saved
- Metric 3: Z improvement
### Qualitative Benefits
- Team feedback
- Customer response
- Market position
## Key Takeaways
1. Lesson learned
2. Best practice discovered
3. Unexpected benefit
## Achieving Similar Results
- Prerequisite conditions
- Implementation roadmap
- Success factors
## CTA: Start Your Success Story
```
#### Thought Leadership Template
```markdown
# [Provocative Statement About Industry Future]
## The Current State
- Industry snapshot
- Prevailing wisdom
- Why status quo is insufficient
## The Emerging Trend
### What's Changing
- Driver 1: [Technology/Market/Behavior]
- Driver 2: [Technology/Market/Behavior]
- Driver 3: [Technology/Market/Behavior]
### Evidence & Examples
- Data point 1
- Case example
- Expert validation
## Implications for [Industry]
### Short-term (6-12 months)
- Immediate adjustments needed
- Quick wins available
- Risks of inaction
### Long-term (2-5 years)
- Fundamental shifts
- New opportunities
- Competitive landscape
## Strategic Recommendations
### For Leaders
- Strategic priorities
- Investment areas
- Organizational changes
### For Practitioners
- Skill development
- Process adaptation
- Tool adoption
## The Path Forward
- Call for industry action
- Your organization's role
- Next steps for readers
## Join the Conversation
- Thought-provoking question
- Invitation to share perspectives
- CTA for deeper engagement
```
### 2. Social Media Templates
#### LinkedIn Post Framework
```
🎯 Hook/Pattern Interrupt
Context paragraph explaining the situation or challenge.
Key insight or lesson learned:
• Bullet point 1 (specific detail)
• Bullet point 2 (measurable outcome)
• Bullet point 3 (unexpected discovery)
Brief story or example that illustrates the point.
Takeaway message with clear value.
Question to encourage engagement?
#Hashtag1 #Hashtag2 #Hashtag3
```
#### Twitter/X Thread Template
```
1/ Bold opening statement or question that stops the scroll
2/ Context - why this matters right now
3/ Problem most people face
4/ Conventional solution (and why it falls short)
5/ Better approach - introduction
6/ Step 1 of better approach
• Specific action
• Why it works
7/ Step 2 of better approach
[Continue pattern]
8/ Real example or case study
9/ Common objection addressed
10/ Results you can expect
11/ One powerful tip most people miss
12/ Recap in 3 key points:
- Point 1
- Point 2
- Point 3
13/ CTA: If you found this helpful, [action]
14/ P.S. - Bonus insight or resource
```
#### Instagram Caption Template
```
[Attention-grabbing first line - appears in preview]
[Story or relatable scenario - 2-3 sentences]
Here's what I learned:
[Key insight or lesson]
3 things that changed everything:
1️⃣ [First point]
2️⃣ [Second point]
3️⃣ [Third point]
[Call-out or question to audience]
Drop a [emoji] if you've experienced this too!
What's your biggest challenge with [topic]? Let me know below 👇
-
#hashtag1 #hashtag2 #hashtag3 #hashtag4 #hashtag5
[10-30 relevant hashtags total]
```
### 3. Email Marketing Templates
#### Newsletter Template
```
Subject: [Benefit] + [Urgency/Curiosity]
Preview: [Complements subject, doesn't repeat]
Hi [Name],
[Personal observation or timely hook - 1-2 sentences]
[Transition to main topic - why reading this matters]
## Main Content Section
[Key points in scannable format]
• Point 1: [Benefit-focused]
• Point 2: [Specific example]
• Point 3: [Actionable tip]
[Brief elaboration on most important point - 2-3 sentences]
## Resource of the Week
[Title with link]
[One sentence on why it's valuable]
## Quick Win You Can Implement Today
[Specific, actionable tip - 2-3 steps max]
[Closing thought or question]
[Signature]
[Name]
P.S. [Additional value or soft CTA]
```
#### Promotional Email Template
```
Subject: [Specific benefit] by [deadline/timeframe]
Preview: [Scarcity or exclusivity element]
Hi [Name],
[Acknowledge pain point or aspiration]
[Agitate - why this problem persists]
I've got something that can help:
[Solution introduction - what it is]
Here's what you get:
✓ Benefit 1 (not feature)
✓ Benefit 2 (not feature)
✓ Benefit 3 (not feature)
[Social proof - testimonial or results]
[Handle main objection]
[Clear CTA button: "Get Started" / "Claim Yours"]
[Urgency element - deadline or limited availability]
[Signature]
P.S. [Reinforce urgency or add bonus]
```
### 4. Content Planning Frameworks
#### Content Pillar Strategy
```
Pillar 1: Educational (40%)
- How-to guides
- Tutorials
- Best practices
- Tips & tricks
Pillar 2: Inspirational (25%)
- Success stories
- Case studies
- Transformations
- Vision pieces
Pillar 3: Conversational (25%)
- Behind-the-scenes
- Team spotlights
- Q&As
- Polls/questions
Pillar 4: Promotional (10%)
- Product updates
- Offers
- Event announcements
- CTAs
```
#### Monthly Content Calendar Structure
```
Week 1:
- Monday: Educational (blog post)
- Wednesday: Inspirational (social)
- Friday: Conversational (email)
Week 2:
- Monday: Educational (video/guide)
- Wednesday: Case study
- Friday: Curated content
Week 3:
- Monday: Educational (infographic)
- Wednesday: Behind-the-scenes
- Friday: Community spotlight
Week 4:
- Monday: Monthly roundup
- Wednesday: Thought leadership
- Friday: Promotional
```
### 5. SEO Content Framework
#### SEO-Optimized Article Structure
```
URL: /primary-keyword-secondary-keyword
Title Tag: Primary Keyword - Secondary Benefit | Brand
Meta Description: Action verb + primary keyword + benefit + CTA (155 chars)
# H1: Primary Keyword + Unique Angle
Introduction (50-100 words)
- Include primary keyword in first 100 words
- State what reader will learn
- Why it matters
## H2: Secondary Keyword Variation 1
[Content with LSI keywords naturally integrated]
### H3: Specific subtopic
- Detail point 1
- Detail point 2
- Detail point 3
## H2: Secondary Keyword Variation 2
[Content continues...]
## H2: Related Questions (FAQ Schema)
### Question 1?
[Concise answer with keyword]
### Question 2?
[Concise answer with keyword]
## Conclusion
- Recap main points
- Include primary keyword
- Clear next action
Internal Links: 2-3 relevant articles
External Links: 1-2 authoritative sources
```
### 6. Video Script Templates
#### Educational Video Script
```
[0-5 seconds: Hook]
"What if I told you [surprising statement]?"
[5-15 seconds: Introduction]
"Hi, I'm [Name] and today we're solving [problem]"
[15-30 seconds: Context]
- Why this matters
- What you'll learn
- What you'll achieve
[30 seconds - 2 minutes: Main Content]
Section 1: [Key Point]
- Explanation
- Example
- Visual aid
Section 2: [Key Point]
[Repeat structure]
Section 3: [Key Point]
[Repeat structure]
[Final 15-30 seconds]
- Quick recap
- Call to action
- End screen elements
```
### 7. Content Repurposing Matrix
```
Original: Blog Post (2000 words)
├── Social Media
│ ├── 5 Twitter posts (key quotes)
│ ├── 1 LinkedIn article (executive summary)
│ ├── 3 Instagram carousels (main points)
│ └── 1 Facebook post (intro + link)
├── Email
│ └── Newsletter feature (summary + CTA)
├── Video
│ ├── YouTube explainer (script from post)
│ └── TikTok/Reels (quick tips)
├── Audio
│ └── Podcast talking points
└── Visual
├── Infographic (data points)
└── Slide deck (presentation)
```
## Quick-Start Checklists
### Pre-Publishing Checklist
- [ ] Keyword research completed
- [ ] Title under 60 characters
- [ ] Meta description written (155 chars)
- [ ] Headers properly structured (H1, H2, H3)
- [ ] Internal links added (2-3)
- [ ] Images optimized with alt text
- [ ] CTA included and clear
- [ ] Proofread and fact-checked
- [ ] Mobile preview checked
### Content Quality Checklist
- [ ] Addresses specific audience need
- [ ] Provides unique value/perspective
- [ ] Includes actionable takeaways
- [ ] Uses appropriate brand voice
- [ ] Contains supporting data/examples
- [ ] Free of jargon and complex terms
- [ ] Scannable format (bullets, headers)
- [ ] Engaging hook in introduction
- [ ] Clear conclusion and next steps
FILE:references/social_media_optimization.md
# Social Media Optimization Guide
Platform-specific best practices, algorithm factors, content optimization strategies, and analytics frameworks.
---
## Table of Contents
- [Platform-Specific Best Practices](#platform-specific-best-practices)
- [LinkedIn](#linkedin)
- [Twitter/X](#twitterx)
- [Instagram](#instagram)
- [Facebook](#facebook)
- [TikTok](#tiktok)
- [Content Optimization Strategies](#content-optimization-strategies)
- [Hashtag Strategy](#hashtag-strategy)
- [Visual Content Optimization](#visual-content-optimization)
- [Caption Writing Formulas](#caption-writing-formulas)
- [Engagement Tactics](#engagement-tactics)
- [Analytics & KPIs](#analytics--kpis)
- [Content Calendar Planning](#content-calendar-planning)
- [Crisis Management Protocol](#crisis-management-protocol)
- [Tool Stack Recommendations](#tool-stack-recommendations)
- [Compliance & Best Practices](#compliance--best-practices)
---
## Platform-Specific Best Practices
### LinkedIn
**Audience**: B2B professionals, decision-makers, thought leaders
**Best Times**: Tuesday-Thursday, 8-10 AM and 5-6 PM
**Optimal Length**: 1,300-2,000 characters for posts
#### Content Formats
- **Text Posts**: 1,300 characters optimal, use line breaks
- **Articles**: 1,900-2,000 words, include 5+ images
- **Videos**: 30 seconds - 10 minutes, native upload preferred
- **Documents**: PDF carousels, 10-15 slides
- **Polls**: 4 options max, 1-2 week duration
#### Optimization Tips
- First 2 lines are crucial (shown in preview)
- Use emoji sparingly for visual breaks
- Include 3-5 relevant hashtags
- Tag people and companies when relevant
- Native video gets 5x more engagement
- Post consistently (3-5x per week optimal)
#### Algorithm Factors
- Dwell time (time spent reading)
- Comments valued over likes
- Early engagement (first hour) crucial
- Creator mode boosts reach
- Replies to comments increase visibility
### Twitter/X
**Audience**: News junkies, tech enthusiasts, real-time conversation
**Best Times**: Weekdays 9-10 AM and 7-9 PM
**Optimal Length**: 100-250 characters
#### Content Formats
- **Single Tweets**: 250 characters, 1-2 hashtags
- **Threads**: 5-15 tweets, numbered format
- **Images**: 16:9 ratio, up to 4 per tweet
- **Videos**: Up to 2:20, square or landscape
- **Polls**: 2-4 options, 5 minutes - 7 days
#### Optimization Tips
- Front-load important information
- Use threads for complex topics
- Include visuals (2-3x more engagement)
- Retweet with comment > regular RT
- Schedule threads for consistency
- Engage genuinely with replies
#### Algorithm Factors
- Engagement rate (likes, RTs, replies)
- Relationship (mutual follows prioritized)
- Recency over evergreen
- Topic relevance to user interests
- Link posts receive less reach
### Instagram
**Audience**: Visual-first, millennials & Gen Z, lifestyle focused
**Best Times**: Weekdays 11 AM - 1 PM and 7-9 PM
**Optimal Length**: 138-150 characters shown in preview
#### Content Formats
- **Feed Posts**: Square (1:1) or vertical (4:5)
- **Stories**: 15 seconds max, vertical (9:16)
- **Reels**: 15-90 seconds, vertical (9:16)
- **Carousels**: 2-10 images/videos
- **IGTV/Video**: 1-60 minutes
#### Optimization Tips
- First sentence crucial (caption preview)
- Use up to 30 hashtags (5-10 in caption, rest in comment)
- Carousel posts get highest engagement
- Stories with polls/questions boost views
- Reels get maximum organic reach
- Post consistently (1-2 feed posts daily)
#### Algorithm Factors
- Relationship (DMs, comments, tags)
- Interest (based on past interactions)
- Timeliness (newer posts prioritized)
- Frequency of app usage
- Time spent on posts (saves valuable)
### Facebook
**Audience**: Broad demographic, community-focused, local businesses
**Best Times**: Wednesday-Friday, 11 AM - 2 PM
**Optimal Length**: 50-80 characters for posts
#### Content Formats
- **Text Posts**: 50-80 characters optimal
- **Images**: 1200x630px for links
- **Videos**: 1-3 minutes, square format
- **Stories**: Same as Instagram
- **Live Videos**: Minimum 10 minutes
#### Optimization Tips
- Native video gets priority
- Ask questions to boost comments
- Share to relevant groups
- Use Facebook Creator Studio
- Tag locations for local reach
- Post 1-2 times per day max
#### Algorithm Factors
- Meaningful interactions (comments > reactions)
- Video completion rate
- Friends and family prioritized
- Group posts get high visibility
- Live videos get 6x engagement
### TikTok
**Audience**: Gen Z, entertainment-focused, trend-driven
**Best Times**: 6-10 AM and 7-11 PM
**Optimal Length**: 15-30 seconds
#### Content Formats
- **Videos**: 15 seconds - 10 minutes
- **Aspect Ratio**: 9:16 vertical
- **Sounds**: Trending audio crucial
- **Effects**: Filters and transitions
#### Optimization Tips
- Hook viewers in first 3 seconds
- Use trending sounds and hashtags
- Create content for FYP, not followers
- Post 1-4 times daily
- Engage with comments quickly
- Jump on trends within 24-48 hours
#### Algorithm Factors
- Completion rate most important
- Shares and saves valued
- Comment engagement
- Following similar creators
- Time spent on app
## Content Optimization Strategies
### Hashtag Strategy
#### Research Methods
1. **Competitor Analysis**: Study successful competitors
2. **Platform Search**: Use native search for suggestions
3. **Hashtag Tools**: RiteTag, Hashtagify, All Hashtag
4. **Trending Topics**: Monitor daily/weekly trends
5. **Brand Hashtags**: Create unique campaign tags
#### Hashtag Mix Formula
- 30% High-volume (1M+ posts)
- 40% Medium-volume (100K-1M posts)
- 30% Low-volume/Niche (<100K posts)
#### Platform-Specific Guidelines
- **Instagram**: 10-30 hashtags (mix in caption and first comment)
- **LinkedIn**: 3-5 professional hashtags
- **Twitter**: 1-2 hashtags max
- **Facebook**: 1-3 hashtags
- **TikTok**: 3-5 trending + niche tags
### Visual Content Optimization
#### Image Best Practices
- **Resolution**: Minimum 1080px width
- **File Size**: Under 5MB for faster loading
- **Alt Text**: Always include for accessibility
- **Branding**: Consistent filters/overlays
- **Text Overlay**: Less than 20% of image
#### Video Optimization
- **Captions**: Always include (85% watch without sound)
- **Thumbnail**: Custom, eye-catching
- **Length**: Platform-specific optimal duration
- **Format**: MP4 for best compatibility
- **Aspect Ratio**: Vertical for stories/reels, square for feed
### Caption Writing Formulas
#### AIDA Formula
- **Attention**: Hook in first line
- **Interest**: Expand on the hook
- **Desire**: Benefits and value
- **Action**: Clear CTA
#### PAS Formula
- **Problem**: Identify pain point
- **Agitate**: Emphasize consequences
- **Solution**: Present your answer
#### Before-After-Bridge
- **Before**: Current situation
- **After**: Desired outcome
- **Bridge**: How to get there
### Engagement Tactics
#### Conversation Starters
- Ask open-ended questions
- Create polls and surveys
- "Fill in the blank" posts
- "This or that" choices
- Caption contests
- Opinion requests
#### Community Building
- Respond to comments within 2 hours
- Like and reply to user comments
- Share user-generated content
- Create branded hashtags
- Host Q&A sessions
- Run challenges or contests
### Analytics & KPIs
#### Vanity Metrics (Track but don't obsess)
- Follower count
- Like count
- View count
#### Performance Metrics (Focus here)
- Engagement rate: (Likes + Comments + Shares) / Reach × 100
- Click-through rate: Clicks / Impressions × 100
- Conversion rate: Conversions / Clicks × 100
- Share/Save rate: Shares / Reach × 100
#### Business Metrics (Ultimate goal)
- Website traffic from social
- Lead generation
- Sales attribution
- Customer acquisition cost
- Customer lifetime value
### Content Calendar Planning
#### Weekly Posting Schedule Template
```
Monday: Motivational (Quote/Inspiration)
Tuesday: Educational (How-to/Tips)
Wednesday: Promotional (Product/Service)
Thursday: Engaging (Poll/Question)
Friday: Fun (Behind-scenes/Casual)
Saturday: User-Generated Content
Sunday: Curated Content/Rest
```
#### Monthly Theme Structure
- Week 1: Awareness content
- Week 2: Consideration content
- Week 3: Decision content
- Week 4: Retention/Community
### Crisis Management Protocol
#### Response Timeline
- **0-15 minutes**: Acknowledge awareness
- **15-60 minutes**: Gather facts
- **1-2 hours**: Official response
- **24 hours**: Follow-up update
- **48-72 hours**: Resolution summary
#### Response Guidelines
1. Acknowledge quickly
2. Take responsibility if appropriate
3. Show empathy
4. Provide facts only
5. Outline action steps
6. Follow up publicly
## Tool Stack Recommendations
### Content Creation
- **Design**: Canva, Adobe Creative Suite
- **Video**: CapCut, InShot, Adobe Premiere
- **Copy**: Grammarly, Hemingway Editor
- **AI Assistance**: ChatGPT, Claude, Jasper
### Scheduling & Management
- **All-in-One**: Hootsuite, Buffer, Sprout Social
- **Visual-First**: Later, Planoly
- **Enterprise**: Sprinklr, Khoros
- **Free Options**: Meta Business Suite, TweetDeck
### Analytics & Monitoring
- **Native**: Platform Insights/Analytics
- **Third-Party**: Socialbakers, Brandwatch
- **Listening**: Mention, Brand24
- **Competitor Analysis**: Social Blade, Rival IQ
### Influencer & UGC
- **Discovery**: AspireIQ, GRIN
- **Management**: CreatorIQ, Klear
- **UGC Curation**: TINT, Stackla
- **Rights Management**: Rights Manager
## Compliance & Best Practices
### Legal Considerations
- Include #ad or #sponsored for paid partnerships
- Respect copyright and attribution
- Follow GDPR for data collection
- Comply with platform terms of service
- Get permission for UGC usage
### Accessibility Guidelines
- Add alt text to all images
- Include captions on videos
- Use CamelCase for hashtags (#LikeThis)
- Avoid text-only images
- Ensure color contrast compliance
### Brand Safety
- Moderate comments regularly
- Set up keyword filters
- Have crisis management plan
- Monitor brand mentions
- Establish posting permissions
Quy trình sản xuất nội dung trọn vẹn, từ chủ đề đến bài viết sẵn sàng đăng như blog, bài báo, hướng dẫn.
---
name: "content-production"
description: "Full content production pipeline — takes a topic from blank page to published-ready piece. Use when you need to execute content: write a blog post, article, or guide end-to-end. Triggers: 'write a post about', 'draft an article', 'create content for', 'help me write', 'I need a blog post'. NOT for content strategy or calendar planning (use content-strategy). NOT for repurposing existing content (use content-repurposing). NOT for social captions only."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: marketing
updated: 2026-03-06
---
# Content Production
You are an expert content producer with deep experience across B2B SaaS, developer tools, and technical audiences. Your goal is to take a topic from zero to a finished, optimized piece that ranks, converts, and actually gets read.
This is the execution engine — not the strategy layer. You're here to build, not plan.
## Before Starting
**Check for context first:**
If `marketing-context.md` exists, read it before asking questions. It contains brand voice, target audience, keyword targets, and writing examples. Use what's there — only ask for what's missing.
Gather this context (ask in one shot, don't drip):
### What you need
- **Topic / working title** — what are we writing about?
- **Target keyword** — primary search term (if SEO matters)
- **Audience** — who reads this and what do they already know?
- **Goal** — inform, convert, build authority, drive trial?
- **Approximate length** — 800 words? 2,000 words? Long-form?
- **Existing content** — do we have pieces this should link to?
If the topic is vague ("write about AI"), push back: "Give me the specific angle — who's the reader, what problem are they solving?"
## How This Skill Works
Three modes. Start at whichever fits:
### Mode 1: Research & Brief
You have a topic but no content yet. Do the research, map the competitive landscape, define the angle, and produce a content brief before writing a word.
### Mode 2: Draft
Brief exists (either provided or from Mode 1). Write the full piece — intro, body, conclusion, headers — following the brief's structure and targeting parameters.
### Mode 3: Optimize & Polish
Draft exists. Run the full optimization pass: SEO signals, readability, structure audit, meta tags, internal links, quality gates. Output a publish-ready version.
You can run all 3 in sequence or jump directly to any mode.
---
## Mode 1: Research & Brief
### Step 1 — Competitive Content Analysis
Before writing, understand what already ranks. For the target keyword:
1. Identify the top 5-10 ranking pieces
2. Map their angles: Are they listicles? How-tos? Opinion pieces? Comparisons?
3. Find the gap: What's missing from the existing content? What angle is underserved?
4. Check search intent: Is the person trying to learn, compare, buy, or solve a specific problem?
**Intent signals:**
| SERP Pattern | Intent | What to write |
|---|---|---|
| "What is / How to" dominate | Informational | Comprehensive guide or explainer |
| Product pages, reviews | Commercial | Comparison or buyer's guide |
| News, updates | Navigational/news | Skip unless you have unique angle |
| Forum results (Reddit, Quora) | Discovery | Opinionated piece with real perspective |
### Step 2 — Source Gathering
Collect 3-5 credible, citable sources before drafting. Prioritize:
- Original research (studies, surveys, reports)
- Official documentation
- Expert quotes you can attribute
- Data with specific numbers (not vague claims)
**Rule:** If you can't cite a specific number, don't make a vague claim. "Studies show" is a red flag. Find the actual study.
### Step 3 — Produce the Content Brief
Fill in the [Content Brief Template](templates/content-brief-template.md). The brief defines:
- Target keyword + secondary keywords
- Reader profile and their job-to-be-done
- Angle and unique point of view
- Required sections and H2 structure
- Key claims to prove
- Internal links to include
- Competitive pieces to beat
See [references/content-brief-guide.md](references/content-brief-guide.md) for how to write a brief that actually produces better drafts.
---
## Mode 2: Draft
You have a brief. Now write.
### Outline First
Build the header skeleton before filling in prose. A good outline:
- Has a hook-worthy H1 (keyword-included, curiosity-driving)
- Has 4-7 H2 sections that follow a logical progression
- Uses H3s sparingly — only when a section genuinely needs subdivision
- Ends with a CTA-adjacent conclusion
Don't over-engineer the outline. If you're stuck on structure for more than 5 minutes, start writing and restructure later.
### Intro Principles
The intro has one job: make the reader believe this piece will answer their question. Get there in 3-4 sentences.
Formula that works:
1. Name the problem or situation the reader is in
2. Name what this piece does about it
3. Optionally: give them a reason to trust you on this topic
**What to avoid:**
- Starting with "In today's digital landscape..." (everyone does this)
- Starting with a question unless it's genuinely sharp
- Burying the point under 3 sentences of context-setting
### Section-by-Section Approach
For each H2 section:
1. State the main point in the first sentence (don't save it for the end)
2. Prove it with an example, stat, or comparison
3. Add one actionable takeaway before moving on
Readers skim. Every section should deliver value on its own.
### Conclusion
Three elements:
1. Summary of the core argument (1-2 sentences)
2. The single most important thing to do next
3. CTA (if relevant to the goal)
Don't pad the conclusion. If it's done, it's done.
---
## Mode 3: Optimize & Polish
Draft exists. Run this in order.
### SEO Pass
- **Title tag**: Contains primary keyword, under 60 characters, curiosity-driving
- **H1**: Different from title tag, keyword-rich, reads naturally
- **H2s**: At least 2-3 contain secondary keywords or related phrases
- **First paragraph**: Primary keyword appears in first 100 words
- **Image alt text**: Descriptive, includes keyword where natural
- **URL slug**: Short, keyword-first, no stop words
### Readability Pass
Run `scripts/content_scorer.py` on the draft. Target score: 70+.
Manual checks:
- Average sentence length: aim for 15-20 words, mix it up
- No paragraph over 4 sentences (web readers need air)
- No jargon without explanation (for non-expert audiences)
- Active voice: find passive constructions and flip them
### Structure Audit
- Does the intro deliver on the headline's promise?
- Is every H2 section earning its place? (Cut if not)
- Are there at least 2 examples or concrete illustrations?
- Does the conclusion feel earned?
### Internal Links
Add 2-4 internal links minimum:
- Link from high-traffic existing pages to this piece
- Link from this piece to related existing content
- Anchor text should describe the destination, not be generic ("click here" is useless)
### Meta Tags
Write:
- **Meta description**: 150-160 characters, includes keyword, ends with action or hook
- **OG title / OG description**: Can differ from meta, optimized for social sharing
- **Canonical URL**: Set it, even if obvious
### Quality Gates — Don't Publish Until These Pass
See [references/optimization-checklist.md](references/optimization-checklist.md) for the full pre-publish checklist.
Core gates:
- [ ] Primary keyword appears naturally 3-5x (not stuffed)
- [ ] Every factual claim has a source or is clearly labeled as opinion
- [ ] At least one image, table, or visual element breaks up text
- [ ] Intro doesn't start with a cliché
- [ ] All internal links work
- [ ] Readability score ≥ 70
- [ ] Word count is within 10% of target
---
## Proactive Triggers
Flag these without being asked:
- **Thin content risk** — If the target keyword has high-authority competitors with 2,000+ word pieces, a 600-word post won't rank. Surface this upfront, before drafting starts.
- **Keyword cannibalization** — If existing content already targets this keyword, flag it. Publishing a second piece splits authority instead of building it.
- **Intent mismatch** — If the requested angle doesn't match search intent (e.g., writing a brand awareness piece for a transactional keyword), call it out. The piece will get traffic that doesn't convert.
- **Missing sources** — If the draft contains claims like "many companies" or "studies show" without citation, flag each one before the piece ships.
- **CTA/goal disconnect** — If the piece's goal is "drive trial signups" but there's no CTA, or the CTA is buried at paragraph 12, flag it.
---
## Output Artifacts
| When you ask for... | You get... |
|---|---|
| Research & brief | Completed content brief: keyword targets, audience, angle, H2 structure, sources, competitive gaps |
| Full draft | Complete article with H1, H2s, intro, body, conclusion, and inline source markers |
| SEO optimization | Annotated draft with title tag, meta description, keyword placement audit, and OG copy |
| Readability audit | Scorer output + specific sentence-level edits flagged |
| Publish checklist | Completed gate checklist with pass/fail on each item |
---
## Communication
All output follows the structured standard:
- **Bottom line first** — answer before explanation
- **What + Why + How** — every finding includes all three
- **Actions have owners and deadlines** — no "we should probably..."
- **Confidence tagging** — 🟢 verified / 🟡 medium / 🔴 assumed
When reviewing drafts: flag issues → explain impact → give specific fix. Don't just say "improve readability." Say: "Paragraph 3 averages 32 words per sentence. Break the second sentence into two."
---
## Related Skills
- **content-strategy**: Use when deciding *what* to write — topics, calendar, pillar structure. NOT for writing the actual piece (that's this skill).
- **content-humanizer**: Use after drafting when the piece sounds robotic or AI-generated. Run this before the optimization pass.
- **ai-seo**: Use when optimizing specifically for AI search citation (ChatGPT, Perplexity, AI Overviews) in addition to traditional SEO.
- **copywriting**: Use for landing pages, CTAs, and conversion copy. NOT for long-form content (that's this skill).
- **seo-audit**: Use when auditing an existing content library for SEO gaps. NOT for single-piece production.
FILE:references/ai-citation-readiness.md
# AI Citation Readiness
How to optimize content so AI platforms (Perplexity, ChatGPT, Google AI Overviews, Claude) cite your pages in their answers. This is the emerging "second SEO" — ranking in AI-generated answers, not just Google blue links.
## Why this matters
AI answer engines extract passages from web content and present them as citations. Content that's structured for extraction gets cited more often. This is independent of traditional SEO — a page can rank #1 on Google but never get cited by AI because it's not formatted for extraction.
## The 5 AI citation signals
### 1. Answer-first paragraphs
The first 40-60 words after each H2 must directly answer the section's implied question. AI platforms extract these opening passages as citation candidates.
**Bad (builds up to the answer):**
```
There are many factors to consider when choosing a framework.
Performance, ecosystem, and learning curve all play a role.
After evaluating several options, React remains the best choice
for most teams in 2026.
```
**Good (answer first):**
```
React is the best frontend framework for most teams in 2026.
It has the largest ecosystem (4.2M weekly npm downloads),
the most hiring demand, and the best balance of performance
and developer experience.
```
### 2. Passage-level citability
Structure content in self-contained 120-180 word chunks that make sense when extracted in isolation. Each chunk should:
- State a clear claim
- Provide supporting evidence
- Cite a source
- Work as a standalone answer
### 3. Entity clarity
Use full entity names on first reference, then consistent abbreviations. AI models need unambiguous entity references to match queries.
**Bad:** "The framework's new feature improves DX significantly."
**Good:** "React 19's Server Components improve developer experience (DX) by reducing client-side JavaScript by 40%."
### 4. Q&A formatting
Include explicit question-and-answer patterns. These directly match how users query AI platforms.
```markdown
## How much does React hosting cost?
React hosting ranges from $0 (Vercel/Netlify free tier) to $20-50/month
for production apps with custom domains and CI/CD. Static sites built
with React are effectively free to host.
```
### 5. Freshness signals
AI platforms prefer recently updated content. Include:
- `dateModified` in JSON-LD or frontmatter
- "Last updated: [date]" visible on page
- Update frequency: evergreen content should be refreshed every 6-12 months
## Scoring for content_quality_gates.py
```
AI Citation Readiness checks:
Answer-first paragraphs at H2 → pass/fail (check first 60 words)
Passage length 120-180 words → pass/warn/fail
Entity clarity (no ambiguous "it") → pass/warn (heuristic)
Q&A section present → pass/fail
Freshness signal present → pass/fail
```
## What NOT to do
- Don't stuff FAQ schema on every page — use it only when genuine Q&A exists
- Don't write for extraction at the expense of human readability
- Don't fabricate statistics to make passages more "citable"
- Don't keyword-stuff entity names — use them naturally
FILE:references/content-brief-guide.md
# Content Brief Guide
A brief isn't a writing assignment. It's a contract between the strategist and the writer — and when you're both the same person, it's still the contract between your thinking brain and your writing brain. Skip it and you'll rewrite. Do it right and the draft almost writes itself.
---
## Why Briefs Fail (and How to Fix Them)
Most briefs are too vague. They say "write about email marketing" without telling the writer:
- What's the specific angle?
- Who's the reader?
- What keywords matter?
- What tone?
- What should the reader do after?
The result: a draft that misses the mark on every axis.
**The fix:** Every field in the brief should be specific enough that two different writers would produce the same piece.
---
## The Most Important Field: Angle
The angle is the single most critical field in the brief. It's your differentiated take — not just "write about email marketing" but "why most email open rate benchmarks are useless and what to measure instead."
**A good angle is:**
- One sentence
- Opinionated (takes a position)
- Different from what already ranks
- Grounded in something you actually know or have data on
**A weak angle is:**
- "Comprehensive guide to email marketing"
- "Everything you need to know about..."
- "Best practices for..."
If your angle sounds like a Wikipedia article, it's not an angle.
---
## Keyword Targeting: What Actually Matters
You don't need to stuff the brief with 20 keywords. You need:
1. **One primary keyword** — the main search term this piece is targeting. Every SEO decision flows from this.
2. **2-4 secondary keywords** — related phrases that appear naturally. These expand coverage without forcing it.
**How to find secondary keywords:**
- Look at "People Also Ask" on the SERP for your primary term
- Check what related terms appear in the top-ranking articles
- Use autocomplete on the search bar for your primary term
**Common mistake:** Targeting a keyword that's informational (someone learning) with a piece that's commercial (someone buying). Match intent or waste the effort.
---
## The Competitive Gap: Finding the Opening
Before writing the brief's angle, look at what's ranking. You're not copying them — you're finding what they missed.
**Gap patterns to look for:**
| Pattern | What It Means | Opportunity |
|---|---|---|
| All top pieces are listicles | No deep explanation exists | Write the definitive guide |
| Top pieces are outdated (2+ years old) | Information is stale | Write the current-year version with updated data |
| Top pieces are generic (no real examples) | Theory without practice | Write a practitioner piece with real cases |
| Top pieces are all from the same POV | Perspective monopoly | Write the contrarian or underdog angle |
| Top pieces are very long but shallow | Word count without depth | Write shorter but genuinely useful |
The gap is your angle. Find it before you brief.
---
## Structure: H2s Are the Real Deliverable
Writers often write vague outlines. "Introduction. Section 1. Conclusion." That's not a structure — that's a placeholder.
Good H2s do three things:
1. **Promise value** — the reader knows what they'll learn
2. **Follow logic** — each section flows from the previous
3. **Hit keywords** — secondary terms appear naturally
**Building the H2 structure:**
- Write the outline as if you're writing the table of contents for a useful reference book
- Each H2 should be a complete thought ("How to Write Subject Lines That Get Opened" not "Subject Lines")
- Sequence matters: don't put "Advanced Tactics" before "Why This Matters"
**The rule of 5:** Most blog posts need 4-6 H2s. Fewer and it's shallow. More and it's scattered.
---
## Sources: Non-Negotiable Before Drafting
Writers who draft without sources invent claims. Then those claims go live on your website.
**Minimum brief requirement:** 3 sources with specific data points or quotes identified.
**Source quality hierarchy:**
1. Original research (surveys, studies, experiments you conducted)
2. Credible third-party research (academic papers, industry reports from named organizations)
3. Expert quotes (attributed, verifiable)
4. Strong case studies with specific metrics
5. Official documentation or standards
**Red flag sources:** Anything that cites "a study" without naming it. Anything more than 5 years old in a fast-moving category. Competitor blog posts (they're also making stuff up).
---
## Internal Linking: Plan It Before, Not After
Most writers add internal links as an afterthought. This produces one problem: they link to whatever they remember, not what's most valuable.
The brief should specify:
- 2-3 existing pieces this article should link to (and what anchor text to use)
- 1-2 existing pages that should link back to this article once published
This prevents both orphaned content and missed link equity.
---
## Success Criteria: If You Don't Define It, You Can't Measure It
Every brief should answer: how will we know this piece worked?
Not vague ("gets traffic") — specific:
- Ranks in top 5 for [keyword] within [timeframe]
- Drives X leads per month
- Achieves X% conversion rate on the CTA
- Gets cited / linked by [type of site]
Define it now so you don't change the definition later.
---
## Brief Anti-Patterns
| Anti-pattern | Problem | Fix |
|---|---|---|
| "Write a comprehensive guide" | No angle, no differentiation | Define the specific take |
| Missing audience definition | Writer guesses; often wrong | Name the exact reader job title and pain |
| No sources listed | Writer invents facts | Find 3 sources before briefing |
| Vague keyword ("marketing") | No SEO targeting | Get specific: "email marketing for B2B SaaS" |
| H2s that are just topic labels | No promise, no structure | Rewrite as complete-thought headers |
| No internal links specified | Orphaned content | List 2-3 links before writing |
| No success criteria | Can't evaluate performance | Define at least one measurable outcome |
FILE:references/content-templates.md
# Content Templates — Auto-Selection Guide
12 content templates with selection logic. The LLM should detect topic intent and recommend the right template before writing.
## Selection matrix
| User intent | Template | Target length | Best for |
|---|---|---|---|
| "How do I..." | How-to guide | 1,500-3,000 words | Step-by-step processes |
| "Best X for Y" / "Top N" | Listicle | 2,000-4,000 words | Comparison/curation |
| "X increased revenue by Y%" | Case study | 1,500-2,500 words | Social proof, sales enablement |
| "X vs Y" | Comparison | 2,000-3,500 words | Decision-stage buyers |
| "Complete guide to X" | Pillar page | 3,000-5,000 words | Topical authority hub |
| "Is X worth it?" | Product review | 1,500-2,500 words | Affiliate, purchase intent |
| "The future of X" | Thought leadership | 1,200-2,000 words | Brand authority |
| "Experts say about X" | Roundup | 2,000-3,500 words | Link building, authority |
| "How to build X step by step" | Tutorial | 2,000-4,000 words | Technical audiences |
| "What happened with X" | News analysis | 800-1,500 words | Timeliness, trending topics |
| "[Data] shows that..." | Data research | 1,500-3,000 words | Original research, link magnets |
| "What is X?" | FAQ / knowledge base | 1,000-2,000 words | Informational, featured snippets |
## Template structures
### How-to guide
```
H1: How to [Action] [Object] (in [Timeframe])
H2: What You'll Need / Prerequisites
H2: Step 1: [First action]
H2: Step 2: [Second action]
...
H2: Common Mistakes to Avoid
H2: FAQ
```
### Listicle
```
H1: [N] Best [Category] for [Audience] in [Year]
H2: Quick Comparison Table
H2: 1. [Item] — Best for [Use Case]
H3: Key Features | H3: Pricing | H3: Who It's For
H2: 2. [Item] — Best for [Use Case]
...
H2: How We Evaluated
H2: FAQ
```
### Case study
```
H1: How [Company] [Achieved Result] with [Method/Product]
H2: The Challenge
H2: The Approach
H2: The Results (with metrics)
H2: Key Takeaways
H2: What's Next
```
### Comparison
```
H1: [X] vs [Y]: Which Is Better for [Use Case]?
H2: Quick Verdict (answer-first)
H2: Comparison Table
H2: [X] — Strengths and Weaknesses
H2: [Y] — Strengths and Weaknesses
H2: When to Choose [X]
H2: When to Choose [Y]
H2: FAQ
```
### Pillar page
```
H1: The Complete Guide to [Topic] ([Year])
H2: What Is [Topic]?
H2: Why [Topic] Matters
H2: [Subtopic 1] (links to cluster article)
H2: [Subtopic 2]
...
H2: Getting Started
H2: FAQ
H2: Further Reading (internal links to cluster)
```
## Auto-selection logic
```
IF user says "how to" or "step by step" → How-to guide
IF user says "best" or "top" + number → Listicle
IF user provides metrics/results data → Case study
IF user says "vs" or "compare" → Comparison
IF user says "complete guide" or "everything about" → Pillar page
IF user says "review" or "worth it" → Product review
IF user asks "what is" or implies definition → FAQ / knowledge base
IF user provides original data → Data research
IF user mentions recent event → News analysis
ELSE → ask user to clarify intent, suggest 2-3 options
```
## Quality checklist (applies to all templates)
- [ ] Answer-first paragraph at every H2
- [ ] Title 50-60 characters
- [ ] Meta description 150-160 characters
- [ ] No heading skips (H1→H2→H3 only)
- [ ] All statistics sourced
- [ ] All images have alt text
- [ ] Internal links ≥ 3
- [ ] External links ≥ 2 (to authoritative sources)
- [ ] CTA present (but not self-promotional beyond 1 mention)
FILE:references/optimization-checklist.md
# Pre-Publish Optimization Checklist
Run this before every piece goes live. Each section is a gate — fail a gate, fix it before moving on.
---
## Gate 1: SEO Signals
### Title & Headers
- [ ] H1 contains primary keyword (naturally, not forced)
- [ ] H1 is ≤70 characters
- [ ] At least 2 H2s contain secondary keywords or related phrases
- [ ] No two H2s are duplicates or near-duplicates
- [ ] H1 differs from the title tag (they can overlap but shouldn't be identical)
### Keyword Presence
- [ ] Primary keyword appears in the first 100 words
- [ ] Primary keyword appears 3-5 times total (not more — stuffing tanks rankings)
- [ ] Keyword variations appear naturally throughout
- [ ] No keyword stuffing (reading it aloud sounds natural)
### Meta & Technical
- [ ] Title tag: 50-60 characters, keyword-first where possible
- [ ] Meta description: 150-160 characters, includes keyword, ends with hook or action
- [ ] URL slug: short, keyword-first, lowercase, hyphens not underscores
- [ ] Canonical URL is set
- [ ] OG title and OG description written for social sharing
### Images & Media
- [ ] At least one image present
- [ ] All images have descriptive alt text (keyword included where natural)
- [ ] Images are compressed (under 200KB each)
- [ ] Image filenames are descriptive (not IMG_4832.jpg)
---
## Gate 2: Readability
### Score
- [ ] Flesch Reading Ease score ≥ 60 (aim for 60-70 for professional audience; 70+ for general)
- [ ] Run `scripts/content_scorer.py` — overall score ≥ 70
### Sentence & Paragraph Structure
- [ ] Average sentence length ≤ 20 words
- [ ] No single paragraph exceeds 4 sentences
- [ ] No sentence exceeds 35 words (check and break if found)
- [ ] Sentence length varies — not all short, not all long
### Voice & Clarity
- [ ] Active voice dominant (passive voice < 20% of sentences)
- [ ] No weasel words ("very," "really," "quite," "somewhat")
- [ ] No jargon without explanation (for non-expert audiences)
- [ ] All acronyms spelled out on first use
- [ ] Contractions used where natural (improves readability)
---
## Gate 3: Structure & Content Quality
### Opening
- [ ] Intro is ≤150 words
- [ ] Intro does not start with "In today's..." or "Welcome to..."
- [ ] Intro names the reader's problem or situation within the first 2 sentences
- [ ] Intro clearly signals what the reader will get from this piece
- [ ] No false promise in the intro (piece delivers what it hints at)
### Body
- [ ] Every H2 section leads with its main point (buried leads = reader drop-off)
- [ ] At least 2 concrete examples, case studies, or data points
- [ ] All statistics and specific claims have citations or are labeled as estimates
- [ ] No fluff paragraphs (every paragraph earns its place — if removing it changes nothing, cut it)
- [ ] Visual break (table, list, callout, image) at least every 400 words
### Conclusion
- [ ] Conclusion ≤150 words
- [ ] Summarizes the core argument (not just "in conclusion...")
- [ ] Includes one clear next step or CTA
- [ ] Doesn't introduce new arguments or ideas
---
## Gate 4: Internal Linking
- [ ] 2-4 internal links to existing content on the site
- [ ] Anchor text describes the destination (not "click here" or "this article")
- [ ] Links tested and confirmed working (no 404s)
- [ ] No excessive linking to the same page multiple times
- [ ] At least one high-traffic page links to this piece (plan this before publishing)
---
## Gate 5: Factual Accuracy
- [ ] Every statistic cited with source (year + organization)
- [ ] All external links go to credible sources (not competitors, not thin content)
- [ ] No claims made without evidence or without "in my experience" qualifier
- [ ] All product/feature mentions are accurate (check with product team if needed)
- [ ] Quotes are attributed correctly and not paraphrased beyond recognition
- [ ] No outdated information — check date-sensitive claims (pricing, regulations, stats)
---
## Gate 6: Brand & Voice
- [ ] Matches brand voice (check `marketing-context.md` if available)
- [ ] Consistent POV throughout (first person, second person, or third — pick one)
- [ ] Consistent tense (present or past — don't mix)
- [ ] No off-brand claims (anything that overpromises, contradicts other content, or sounds unlike us)
- [ ] CTA aligns with piece goal (don't pitch demo on an informational piece for beginners)
---
## Gate 7: Final Readthrough
Run a final read-aloud. Catch what scanning misses.
- [ ] Read the full piece aloud — anything that makes you stumble, fix it
- [ ] The piece flows — section to section makes sense without re-reading
- [ ] The headline still feels earned after reading the piece
- [ ] You'd share this piece yourself (if not, it's not done)
- [ ] No placeholder text, formatting artifacts, or draft notes left in
---
## Scoring Summary
| Gate | Status | Notes |
|---|---|---|
| SEO Signals | ✅ / ❌ | |
| Readability | ✅ / ❌ | |
| Structure & Quality | ✅ / ❌ | |
| Internal Linking | ✅ / ❌ | |
| Factual Accuracy | ✅ / ❌ | |
| Brand & Voice | ✅ / ❌ | |
| Final Readthrough | ✅ / ❌ | |
**Publish only when all 7 gates are green.**
If you're skipping a gate, document why. Conscious tradeoffs are fine. Unconscious shortcuts aren't.
FILE:scripts/brand_voice_analyzer.py
#!/usr/bin/env python3
"""
Brand Voice Analyzer - Analyzes content to establish and maintain brand voice consistency
"""
import re
from typing import Dict, List, Tuple
import json
class BrandVoiceAnalyzer:
def __init__(self):
self.voice_dimensions = {
'formality': {
'formal': ['hereby', 'therefore', 'furthermore', 'pursuant', 'regarding'],
'casual': ['hey', 'cool', 'awesome', 'stuff', 'yeah', 'gonna']
},
'tone': {
'professional': ['expertise', 'solution', 'optimize', 'leverage', 'strategic'],
'friendly': ['happy', 'excited', 'love', 'enjoy', 'together', 'share']
},
'perspective': {
'authoritative': ['proven', 'research shows', 'experts agree', 'data indicates'],
'conversational': ['you might', 'let\'s explore', 'we think', 'imagine if']
}
}
def analyze_text(self, text: str) -> Dict:
"""Analyze text for brand voice characteristics"""
text_lower = text.lower()
word_count = len(text.split())
results = {
'word_count': word_count,
'readability_score': self._calculate_readability(text),
'voice_profile': {},
'sentence_analysis': self._analyze_sentences(text),
'recommendations': []
}
# Analyze voice dimensions
for dimension, categories in self.voice_dimensions.items():
dim_scores = {}
for category, keywords in categories.items():
score = sum(1 for keyword in keywords if keyword in text_lower)
dim_scores[category] = score
# Determine dominant voice
if sum(dim_scores.values()) > 0:
dominant = max(dim_scores, key=dim_scores.get)
results['voice_profile'][dimension] = {
'dominant': dominant,
'scores': dim_scores
}
# Generate recommendations
results['recommendations'] = self._generate_recommendations(results)
return results
def _calculate_readability(self, text: str) -> float:
"""Calculate Flesch Reading Ease score"""
sentences = re.split(r'[.!?]+', text)
words = text.split()
syllables = sum(self._count_syllables(word) for word in words)
if len(sentences) == 0 or len(words) == 0:
return 0
avg_sentence_length = len(words) / len(sentences)
avg_syllables_per_word = syllables / len(words)
# Flesch Reading Ease formula
score = 206.835 - 1.015 * avg_sentence_length - 84.6 * avg_syllables_per_word
return max(0, min(100, score))
def _count_syllables(self, word: str) -> int:
"""Count syllables in a word (simplified)"""
word = word.lower()
vowels = 'aeiou'
syllable_count = 0
previous_was_vowel = False
for char in word:
is_vowel = char in vowels
if is_vowel and not previous_was_vowel:
syllable_count += 1
previous_was_vowel = is_vowel
# Adjust for silent e
if word.endswith('e'):
syllable_count -= 1
return max(1, syllable_count)
def _analyze_sentences(self, text: str) -> Dict:
"""Analyze sentence structure"""
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
if not sentences:
return {'average_length': 0, 'variety': 'low'}
lengths = [len(s.split()) for s in sentences]
avg_length = sum(lengths) / len(lengths) if lengths else 0
# Calculate variety
if len(set(lengths)) < 3:
variety = 'low'
elif len(set(lengths)) < 5:
variety = 'medium'
else:
variety = 'high'
return {
'average_length': round(avg_length, 1),
'variety': variety,
'count': len(sentences)
}
def _generate_recommendations(self, analysis: Dict) -> List[str]:
"""Generate recommendations based on analysis"""
recommendations = []
# Readability recommendations
if analysis['readability_score'] < 30:
recommendations.append("Consider simplifying language for better readability")
elif analysis['readability_score'] > 70:
recommendations.append("Content is very easy to read - consider if this matches your audience")
# Sentence variety
if analysis['sentence_analysis']['variety'] == 'low':
recommendations.append("Vary sentence length for better flow and engagement")
# Voice consistency
if analysis['voice_profile']:
recommendations.append("Maintain consistent voice across all content")
return recommendations
def analyze_content(content: str, output_format: str = 'json') -> str:
"""Main function to analyze content"""
analyzer = BrandVoiceAnalyzer()
results = analyzer.analyze_text(content)
if output_format == 'json':
return json.dumps(results, indent=2)
else:
# Human-readable format
output = [
f"=== Brand Voice Analysis ===",
f"Word Count: {results['word_count']}",
f"Readability Score: {results['readability_score']:.1f}/100",
f"",
f"Voice Profile:"
]
for dimension, profile in results['voice_profile'].items():
output.append(f" {dimension.title()}: {profile['dominant']}")
output.extend([
f"",
f"Sentence Analysis:",
f" Average Length: {results['sentence_analysis']['average_length']} words",
f" Variety: {results['sentence_analysis']['variety']}",
f" Total Sentences: {results['sentence_analysis']['count']}",
f"",
f"Recommendations:"
])
for rec in results['recommendations']:
output.append(f" • {rec}")
return '\n'.join(output)
if __name__ == "__main__":
import sys
import argparse
parser = argparse.ArgumentParser(
description="Brand Voice Analyzer - Analyzes content to establish and maintain brand voice consistency"
)
parser.add_argument(
"file", nargs="?", default=None,
help="Text file to analyze"
)
parser.add_argument(
"--format", choices=["json", "text"], default="text",
help="Output format (default: text)"
)
args = parser.parse_args()
if args.file:
with open(args.file, 'r') as f:
content = f.read()
print(analyze_content(content, args.format))
else:
print("Usage: python brand_voice_analyzer.py <file> [--format json|text]")
FILE:scripts/content_quality_gates.py
#!/usr/bin/env python3
"""
content_quality_gates.py — Non-negotiable quality checks before publishing.
Hard stops that BLOCK publication. These aren't suggestions — they're rules.
Inspired by the quality gate pattern used in high-traction content tools.
Gates (all must pass):
1. Heading hierarchy: H1 → H2 → H3 only (no skips, no H4+ without H3)
2. No paragraphs > 150 words (wall of text)
3. All images/figures have alt text references
4. Source citations: any statistic must have a [source] marker
5. Title length: 50-60 characters
6. Meta description: 150-160 characters (if present)
7. No self-promotional mentions beyond 1
8. dateModified or "Updated" marker present for evergreen content
Usage:
python content_quality_gates.py article.md
python content_quality_gates.py article.md --json
python content_quality_gates.py --demo
Score bands (from the gate results):
All pass → PUBLISH (ready to ship)
1-2 warnings → TARGET (fix specific items)
Any gate failure → BLOCK (fix before publishing)
"""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
HEADING_RE = re.compile(r"^(#{1,6})\s+(.+)$", re.MULTILINE)
STAT_RE = re.compile(r"\b\d+(?:\.\d+)?%|\$\d+|\d+(?:,\d{3})+|\d+x\b", re.IGNORECASE)
SOURCE_RE = re.compile(r"\[(?:source|citation|ref|via|from)\b.*?\]|\(https?://\S+\)", re.IGNORECASE)
IMAGE_RE = re.compile(r"!\[([^\]]*)\]\(", re.MULTILINE)
TITLE_RE = re.compile(r"^#\s+(.+)$", re.MULTILINE)
META_DESC_RE = re.compile(r"^description:\s*[\"']?(.+?)[\"']?\s*$", re.MULTILINE)
SELF_PROMO_RE = re.compile(r"\b(?:our product|we offer|sign up|try free|get started|our platform|our solution)\b", re.IGNORECASE)
DATE_RE = re.compile(r"(?:updated|modified|reviewed|published).*?\d{4}", re.IGNORECASE)
FRONTMATTER_DATE_RE = re.compile(r"^(?:date_?modified|updated|last_updated):\s*\d{4}", re.MULTILINE)
DEMO_CONTENT = """---
title: "How to Optimize Your Landing Page for Conversions"
description: "Learn the 7 proven techniques to boost landing page conversion rates by 40% or more."
dateModified: 2026-03-15
---
# How to Optimize Your Landing Page for Conversions
Landing pages are the backbone of any digital marketing campaign. Getting them right means more leads, more sales, and better ROI on every dollar you spend on ads.
## Start With a Clear Value Proposition
Your headline should communicate the core benefit in under 10 words. According to a study by Marketing Experiments, clarity beats persuasion by 104% in headline tests [source: marketingexperiments.com].
The subheadline expands on the promise. Keep it under 25 words.
## Optimize Your Form Length
Fewer fields mean higher conversions. HubSpot found that reducing form fields from 4 to 3 increased conversions by 50% [source: HubSpot 2025 Benchmark Report].
### When to Use Long Forms
Long forms work for high-value B2B offers where lead quality matters more than volume. The key is progressive profiling — ask for more information over time, not all at once.
## Add Social Proof Above the Fold
Show logos, testimonials, or user counts where visitors can see them without scrolling. 72% of consumers say positive reviews increase their trust [source: BrightLocal 2025].

## Test Your CTA Button
The button text matters more than the color. "Get My Free Guide" outperforms "Submit" by 3x on average.
Our platform makes A/B testing effortless — try it free today.
## Measure and Iterate
Track these metrics weekly: conversion rate, bounce rate, time on page, scroll depth. Set up goals in Google Analytics 4 and review them every Friday.
"""
def check_heading_hierarchy(text):
"""Gate 1: H1 → H2 → H3 only, no skips."""
findings = []
headings = [(m.start(), len(m.group(1)), m.group(2)) for m in HEADING_RE.finditer(text)]
prev_level = 0
for _, level, title in headings:
if level > prev_level + 1 and prev_level > 0:
findings.append(f"Heading skip: H{prev_level} → H{level} at '{title[:40]}'. Don't skip levels.")
prev_level = level
return {"gate": "heading-hierarchy", "passed": len(findings) == 0, "findings": findings}
def check_paragraph_length(text):
"""Gate 2: No paragraph > 150 words."""
findings = []
body = re.sub(r"^---.*?---\s*", "", text, count=1, flags=re.DOTALL)
paragraphs = re.split(r"\n\s*\n", body)
for i, para in enumerate(paragraphs, 1):
para = para.strip()
if not para or para.startswith("#") or para.startswith("```") or para.startswith("|"):
continue
words = len(para.split())
if words > 150:
findings.append(f"Paragraph {i}: {words} words (max 150). Break it up.")
return {"gate": "paragraph-length", "passed": len(findings) == 0, "findings": findings}
def check_image_alt_text(text):
"""Gate 3: All images have alt text."""
findings = []
for m in IMAGE_RE.finditer(text):
alt = m.group(1).strip()
if not alt:
findings.append(f"Image missing alt text:  — add descriptive alt.")
return {"gate": "image-alt-text", "passed": len(findings) == 0, "findings": findings}
def check_source_citations(text):
"""Gate 4: Statistics must have source markers."""
findings = []
body = re.sub(r"^---.*?---\s*", "", text, count=1, flags=re.DOTALL)
lines = body.splitlines()
for i, line in enumerate(lines, 1):
if line.strip().startswith("#") or line.strip().startswith("```"):
continue
stats = STAT_RE.findall(line)
if stats and not SOURCE_RE.search(line):
stat_str = ", ".join(stats[:3])
findings.append(f"Line {i}: statistic ({stat_str}) without [source] marker.")
return {"gate": "source-citations", "passed": len(findings) == 0, "findings": findings}
def check_title_length(text):
"""Gate 5: Title 50-60 characters."""
findings = []
m = TITLE_RE.search(text)
if m:
title = m.group(1).strip()
length = len(title)
if length < 50:
findings.append(f"Title too short: {length} chars (aim for 50-60). Title: '{title}'")
elif length > 60:
findings.append(f"Title too long: {length} chars (aim for 50-60). Title: '{title}'")
else:
findings.append("No H1 title found.")
return {"gate": "title-length", "passed": len(findings) == 0, "findings": findings}
def check_meta_description(text):
"""Gate 6: Meta description 150-160 chars (if present)."""
findings = []
m = META_DESC_RE.search(text)
if m:
desc = m.group(1).strip()
length = len(desc)
if length < 150:
findings.append(f"Meta description too short: {length} chars (aim for 150-160).")
elif length > 160:
findings.append(f"Meta description too long: {length} chars (aim for 150-160). Will be truncated.")
return {"gate": "meta-description", "passed": len(findings) == 0, "findings": findings}
def check_self_promotion(text):
"""Gate 7: Max 1 self-promotional mention."""
findings = []
matches = SELF_PROMO_RE.findall(text)
if len(matches) > 1:
findings.append(f"{len(matches)} self-promotional mentions found (max 1): {', '.join(matches[:5])}")
return {"gate": "self-promotion", "passed": len(findings) == 0, "findings": findings}
def check_freshness(text):
"""Gate 8: dateModified or update marker present."""
findings = []
has_date = bool(FRONTMATTER_DATE_RE.search(text)) or bool(DATE_RE.search(text))
if not has_date:
findings.append("No dateModified or 'Updated' marker. Evergreen content needs freshness signals.")
return {"gate": "freshness-signal", "passed": len(findings) == 0, "findings": findings}
ALL_GATES = [
check_heading_hierarchy,
check_paragraph_length,
check_image_alt_text,
check_source_citations,
check_title_length,
check_meta_description,
check_self_promotion,
check_freshness,
]
def run_gates(text):
results = [gate(text) for gate in ALL_GATES]
passed = sum(1 for r in results if r["passed"])
failed = [r for r in results if not r["passed"]]
total = len(results)
if len(failed) == 0:
verdict = "PUBLISH"
elif all(len(r["findings"]) <= 1 for r in failed) and len(failed) <= 2:
verdict = "TARGET"
else:
verdict = "BLOCK"
return {
"status": "ok",
"gates_passed": passed,
"gates_total": total,
"verdict": verdict,
"results": results,
}
def main():
p = argparse.ArgumentParser(
description="Non-negotiable quality gates for content publishing.",
epilog="All gates must pass before publishing. Run with --demo for a sample article.",
)
p.add_argument("file", nargs="?", help="Markdown file to check")
p.add_argument("--json", action="store_true", help="JSON output")
p.add_argument("--demo", action="store_true", help="Run with demo content")
args = p.parse_args()
if args.demo:
text = DEMO_CONTENT
elif args.file:
path = Path(args.file)
if not path.exists():
print(f"[error] {path} not found", file=sys.stderr)
sys.exit(1)
text = path.read_text(encoding="utf-8", errors="replace")
else:
p.print_help()
sys.exit(0)
result = run_gates(text)
if args.json:
print(json.dumps(result, indent=2))
return
print(f"Content Quality Gates — {result['gates_passed']}/{result['gates_total']} passed")
print(f"Verdict: {result['verdict']}")
print()
for r in result["results"]:
icon = "✅" if r["passed"] else "❌"
print(f" {icon} {r['gate']}")
for f in r["findings"]:
print(f" → {f}")
print()
if result["verdict"] == "PUBLISH":
print(" All gates pass. Ready to publish.")
elif result["verdict"] == "TARGET":
print(" Minor issues. Fix the flagged items, then publish.")
else:
print(" BLOCKED. Fix all gate failures before publishing.")
if __name__ == "__main__":
main()
FILE:scripts/content_scorer.py
#!/usr/bin/env python3
"""content_scorer.py — scores content 0-100 on readability, SEO, structure, and engagement."""
import sys
import re
import json
import math
from collections import Counter
# ── Sample content for zero-config demo run ──────────────────────────────────
SAMPLE_CONTENT = """
Title: How to Reduce Churn in SaaS: 7 Proven Tactics That Actually Work
Introduction
Most SaaS companies discover their churn problem too late — after the customer has already left. By then, the damage is done. In this guide, you'll learn seven tactics to reduce churn before it happens, backed by data from 200+ SaaS companies.
## Why Customers Churn (It's Not What You Think)
Customers don't churn because your product is bad. They churn because they never saw value. A study by Mixpanel found that 60% of users who churn never completed onboarding. That's a product adoption problem, not a satisfaction problem.
Fix the adoption gap first. Everything else is downstream.
## Tactic 1: Instrument Your Activation Funnel
You can't fix what you can't see. Start by identifying your activation event — the moment users first experience your product's core value. For Slack, it's sending 2,000 messages. For Dropbox, it's saving a first file.
Map the funnel from signup to activation. Find where users drop off. That's your highest-leverage intervention point.
## Tactic 2: Segment Your Churn by Cohort
Not all churn is equal. A user who churns in week one is a different problem than a user who churns in month six. Cohort analysis breaks this apart.
Compare cohorts by: acquisition channel, onboarding path, company size, and feature usage. You'll find that certain cohorts churn 3-4x more than others. Focus retention efforts on your best cohorts first — don't try to save everyone.
## Tactic 3: Build a Customer Health Score
A health score is a composite signal that predicts churn before it happens. Common inputs include: login frequency, feature adoption rate, support ticket volume, and NPS response.
Weight each signal by its correlation with retention in your historical data. A score below 40 should trigger a customer success outreach. Don't wait for the cancellation request.
## Conclusion
Churn is a lagging indicator. By the time you see it, the problem happened weeks ago. Build systems that surface early signals — activation gaps, usage drops, health score declines — and act on them before customers decide to leave.
Start with one tactic. Instrument your activation funnel this week.
"""
SAMPLE_KEYWORD = "reduce churn"
SAMPLE_TITLE = "How to Reduce Churn in SaaS: 7 Proven Tactics That Actually Work"
# ── Scoring functions ─────────────────────────────────────────────────────────
def count_syllables(word: str) -> int:
"""Approximate syllable count using vowel-group heuristic."""
word = word.lower().strip(".,!?;:")
if not word:
return 0
vowels = "aeiouy"
count = 0
prev_vowel = False
for ch in word:
is_vowel = ch in vowels
if is_vowel and not prev_vowel:
count += 1
prev_vowel = is_vowel
# Adjust for silent e
if word.endswith("e") and len(word) > 2:
count = max(1, count - 1)
return max(1, count)
def flesch_reading_ease(text: str) -> float:
"""
Flesch Reading Ease score.
206.835 - 1.015 * (words/sentences) - 84.6 * (syllables/words)
Higher = easier. Target: 60-70 for professional content.
"""
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
n_sentences = max(1, len(sentences))
words = re.findall(r'\b[a-zA-Z]+\b', text)
n_words = max(1, len(words))
n_syllables = sum(count_syllables(w) for w in words)
asl = n_words / n_sentences # avg sentence length
asw = n_syllables / n_words # avg syllables per word
score = 206.835 - (1.015 * asl) - (84.6 * asw)
return round(max(0.0, min(100.0, score)), 1)
def score_readability(text: str) -> dict:
"""Score readability 0-25 (25% of total)."""
fre = flesch_reading_ease(text)
# FRE → points (target 60-70 for B2B)
if fre >= 65:
fre_points = 15
elif fre >= 55:
fre_points = 12
elif fre >= 45:
fre_points = 8
elif fre >= 35:
fre_points = 4
else:
fre_points = 0
# Sentence length variance
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if len(s.split()) > 2]
lengths = [len(s.split()) for s in sentences]
if len(lengths) > 1:
mean_len = sum(lengths) / len(lengths)
variance = sum((l - mean_len) ** 2 for l in lengths) / len(lengths)
std_dev = math.sqrt(variance)
variance_points = min(10, int(std_dev)) # good variance = high std dev
else:
variance_points = 0
total = min(25, fre_points + variance_points)
return {
"score": total,
"max": 25,
"flesch_reading_ease": fre,
"sentence_length_std_dev": round(math.sqrt(variance) if len(lengths) > 1 else 0, 1)
}
def score_seo(text: str, title: str = "", keyword: str = "") -> dict:
"""Score SEO signals 0-25 (25% of total)."""
text_lower = text.lower()
title_lower = title.lower()
keyword_lower = keyword.lower()
points = 0
signals = {}
# Title contains keyword
if keyword_lower and keyword_lower in title_lower:
points += 7
signals["keyword_in_title"] = True
else:
signals["keyword_in_title"] = False
# Keyword in first 100 words
first_100 = " ".join(re.findall(r'\b\w+\b', text_lower)[:100])
if keyword_lower and keyword_lower in first_100:
points += 5
signals["keyword_in_intro"] = True
else:
signals["keyword_in_intro"] = False
# Keyword density (target 0.5-2%)
words = re.findall(r'\b\w+\b', text_lower)
n_words = max(1, len(words))
kw_words = keyword_lower.split()
kw_count = 0
for i in range(len(words) - len(kw_words) + 1):
if words[i:i+len(kw_words)] == kw_words:
kw_count += 1
density = (kw_count * len(kw_words)) / n_words * 100
signals["keyword_density_pct"] = round(density, 2)
signals["keyword_occurrences"] = kw_count
if 0.5 <= density <= 2.5:
points += 5
elif kw_count > 0:
points += 2
# H2 headings present
h2_count = len(re.findall(r'^## .+', text, re.MULTILINE))
signals["h2_count"] = h2_count
if h2_count >= 3:
points += 5
elif h2_count >= 1:
points += 2
# Title length
signals["title_length"] = len(title)
if 30 <= len(title) <= 65:
points += 3
total = min(25, points)
return {"score": total, "max": 25, **signals}
def score_structure(text: str) -> dict:
"""Score structure 0-25 (25% of total)."""
points = 0
signals = {}
lines = text.strip().split('\n')
# Intro: first non-empty paragraph
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
signals["paragraph_count"] = len(paragraphs)
# Has intro (first paragraph isn't a heading)
if paragraphs and not paragraphs[0].startswith('#'):
intro_words = len(paragraphs[0].split())
signals["intro_word_count"] = intro_words
if 30 <= intro_words <= 200:
points += 7
elif intro_words > 0:
points += 3
else:
signals["intro_word_count"] = 0
# Has H2 sections
h2s = [l for l in lines if l.startswith('## ')]
signals["h2_count"] = len(h2s)
if len(h2s) >= 4:
points += 8
elif len(h2s) >= 2:
points += 5
elif len(h2s) >= 1:
points += 2
# Has conclusion (last substantial paragraph)
last_para = paragraphs[-1] if paragraphs else ""
conclusion_words = len(last_para.split())
signals["conclusion_word_count"] = conclusion_words
conclusion_signals = ['conclusion', 'summary', 'final', 'start ', 'next step', 'action']
if any(sig in last_para.lower() for sig in conclusion_signals) and conclusion_words >= 20:
points += 7
elif conclusion_words >= 30:
points += 4
# Average paragraph length (web = shorter is better)
para_lengths = [len(p.split()) for p in paragraphs if not p.startswith('#')]
if para_lengths:
avg_para_len = sum(para_lengths) / len(para_lengths)
signals["avg_paragraph_word_count"] = round(avg_para_len, 1)
if avg_para_len <= 80:
points += 3
else:
signals["avg_paragraph_word_count"] = 0
total = min(25, points)
return {"score": total, "max": 25, **signals}
def score_engagement(text: str) -> dict:
"""Score engagement signals 0-25 (25% of total)."""
points = 0
signals = {}
text_lower = text.lower()
# Questions (engage readers, prompt thought)
question_count = len(re.findall(r'\?', text))
signals["question_count"] = question_count
if question_count >= 3:
points += 6
elif question_count >= 1:
points += 3
# Specific numbers / data points
number_count = len(re.findall(r'\b\d+(?:\.\d+)?%?\b', text))
signals["numbers_and_stats"] = number_count
if number_count >= 5:
points += 7
elif number_count >= 2:
points += 4
elif number_count >= 1:
points += 2
# Example signals
example_phrases = ['for example', 'for instance', 'such as', 'like ', 'e.g.', 'case study',
'imagine', 'consider', 'let\'s say', 'here\'s', 'specifically']
example_count = sum(text_lower.count(p) for p in example_phrases)
signals["example_signals"] = example_count
if example_count >= 3:
points += 6
elif example_count >= 1:
points += 3
# Lists (bulleted or numbered)
list_items = len(re.findall(r'^\s*[-*•]\s+.+|^\s*\d+\.\s+.+', text, re.MULTILINE))
signals["list_items"] = list_items
if list_items >= 5:
points += 6
elif list_items >= 2:
points += 3
total = min(25, points)
return {"score": total, "max": 25, **signals}
# ── Main ──────────────────────────────────────────────────────────────────────
def score_content(text: str, title: str = "", keyword: str = "") -> dict:
readability = score_readability(text)
seo = score_seo(text, title, keyword)
structure = score_structure(text)
engagement = score_engagement(text)
total = readability["score"] + seo["score"] + structure["score"] + engagement["score"]
grade = "D"
if total >= 90:
grade = "A+"
elif total >= 80:
grade = "A"
elif total >= 70:
grade = "B"
elif total >= 60:
grade = "C"
return {
"total_score": total,
"grade": grade,
"sections": {
"readability": readability,
"seo": seo,
"structure": structure,
"engagement": engagement,
}
}
def print_report(result: dict, title: str, keyword: str) -> None:
total = result["total_score"]
grade = result["grade"]
s = result["sections"]
bar_filled = int(total / 5)
bar = "█" * bar_filled + "░" * (20 - bar_filled)
print()
print("╔══════════════════════════════════════════╗")
print("║ CONTENT SCORER — REPORT ║")
print("╚══════════════════════════════════════════╝")
print(f" Title: {title[:55] or '(not provided)'}")
print(f" Keyword: {keyword or '(not provided)'}")
print()
print(f" TOTAL SCORE: {total}/100 [{grade}]")
print(f" [{bar}]")
print()
print(" ── Section Breakdown ──────────────────────")
sections = [
("Readability", s["readability"]),
("SEO Signals", s["seo"]),
("Structure", s["structure"]),
("Engagement", s["engagement"]),
]
for label, section in sections:
sc = section["score"]
mx = section["max"]
bar2_filled = int(sc / mx * 10)
bar2 = "█" * bar2_filled + "░" * (10 - bar2_filled)
print(f" {label:<14} {sc:>2}/{mx} [{bar2}]")
print()
print(" ── Key Signals ────────────────────────────")
r = s["readability"]
print(f" Flesch Reading Ease: {r['flesch_reading_ease']} (target: 60-70)")
print(f" Sentence length StDev: {r['sentence_length_std_dev']} (higher = more varied)")
seo_d = s["seo"]
print(f" Keyword in title: {'✅' if seo_d.get('keyword_in_title') else '❌'}")
print(f" Keyword in intro: {'✅' if seo_d.get('keyword_in_intro') else '❌'}")
print(f" Keyword density: {seo_d.get('keyword_density_pct', 0)}% (target: 0.5-2.5%)")
print(f" H2 sections: {seo_d.get('h2_count', 0)}")
st = s["structure"]
print(f" Intro word count: {st.get('intro_word_count', 0)} (target: 30-200)")
print(f" Avg paragraph length: {st.get('avg_paragraph_word_count', 0)} words (target: ≤80)")
en = s["engagement"]
print(f" Questions: {en.get('question_count', 0)}")
print(f" Stats/numbers: {en.get('numbers_and_stats', 0)}")
print(f" Examples: {en.get('example_signals', 0)}")
print()
print(" ── Recommendations ────────────────────────")
if r["flesch_reading_ease"] < 55:
print(" ⚠ Readability is low — shorten sentences and use simpler words")
if not seo_d.get("keyword_in_title"):
print(" ⚠ Primary keyword missing from title — add it naturally")
if not seo_d.get("keyword_in_intro"):
print(" ⚠ Primary keyword missing from first 100 words")
if seo_d.get("h2_count", 0) < 3:
print(" ⚠ Add more H2 sections — aim for at least 4")
if st.get("avg_paragraph_word_count", 0) > 100:
print(" ⚠ Paragraphs too long for web — break them up")
if en.get("question_count", 0) == 0:
print(" ⚠ Add at least one question to engage readers")
if en.get("numbers_and_stats", 0) < 2:
print(" ⚠ Thin on data — add specific numbers or stats")
if total >= 70:
print(" ✅ Content is publish-ready (score ≥ 70)")
else:
print(f" ❌ Score below 70 — address recommendations before publishing")
print()
def main():
import argparse
parser = argparse.ArgumentParser(
description="Scores content 0-100 on readability, SEO, structure, and engagement."
)
parser.add_argument(
"file", nargs="?", default=None,
help="Path to a text/markdown file to analyze. If omitted, runs demo "
"with embedded sample content."
)
parser.add_argument(
"keyword", nargs="?", default="",
help="Target SEO keyword to check density and placement."
)
parser.add_argument(
"--json", action="store_true",
help="Also output results as JSON."
)
args = parser.parse_args()
title = ""
keyword = args.keyword
text = ""
if args.file is None:
# Demo mode — use embedded sample
print("[Demo mode — using embedded sample content]")
text = SAMPLE_CONTENT
title = SAMPLE_TITLE
keyword = SAMPLE_KEYWORD
else:
# Read from file
try:
with open(args.file, 'r', encoding='utf-8') as f:
text = f.read()
except FileNotFoundError:
print(f"Error: file not found: {args.file}", file=sys.stderr)
sys.exit(1)
# Extract title from first H1 or first line
for line in text.split('\n'):
line = line.strip()
if line.startswith('# '):
title = line[2:].strip()
break
elif line.startswith('Title:'):
title = line[6:].strip()
break
if not title and text:
title = text.split('\n')[0][:80]
result = score_content(text, title, keyword)
print_report(result, title, keyword)
# JSON output for programmatic use
if args.json:
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
FILE:scripts/seo_optimizer.py
#!/usr/bin/env python3
"""
SEO Content Optimizer - Analyzes and optimizes content for SEO
"""
import re
from typing import Dict, List, Set
import json
class SEOOptimizer:
def __init__(self):
# Common stop words to filter
self.stop_words = {
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
'of', 'with', 'by', 'from', 'as', 'is', 'was', 'are', 'were', 'be',
'been', 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will',
'would', 'could', 'should', 'may', 'might', 'must', 'can', 'shall'
}
# SEO best practices
self.best_practices = {
'title_length': (50, 60),
'meta_description_length': (150, 160),
'url_length': (50, 60),
'paragraph_length': (40, 150),
'heading_keyword_placement': True,
'keyword_density': (0.01, 0.03) # 1-3%
}
def analyze(self, content: str, target_keyword: str = None,
secondary_keywords: List[str] = None) -> Dict:
"""Analyze content for SEO optimization"""
analysis = {
'content_length': len(content.split()),
'keyword_analysis': {},
'structure_analysis': self._analyze_structure(content),
'readability': self._analyze_readability(content),
'meta_suggestions': {},
'optimization_score': 0,
'recommendations': []
}
# Keyword analysis
if target_keyword:
analysis['keyword_analysis'] = self._analyze_keywords(
content, target_keyword, secondary_keywords or []
)
# Generate meta suggestions
analysis['meta_suggestions'] = self._generate_meta_suggestions(
content, target_keyword
)
# Calculate optimization score
analysis['optimization_score'] = self._calculate_seo_score(analysis)
# Generate recommendations
analysis['recommendations'] = self._generate_recommendations(analysis)
return analysis
def _analyze_keywords(self, content: str, primary: str,
secondary: List[str]) -> Dict:
"""Analyze keyword usage and density"""
content_lower = content.lower()
word_count = len(content.split())
results = {
'primary_keyword': {
'keyword': primary,
'count': content_lower.count(primary.lower()),
'density': 0,
'in_title': False,
'in_headings': False,
'in_first_paragraph': False
},
'secondary_keywords': [],
'lsi_keywords': []
}
# Calculate primary keyword metrics
if word_count > 0:
results['primary_keyword']['density'] = (
results['primary_keyword']['count'] / word_count
)
# Check keyword placement
first_para = content.split('\n\n')[0] if '\n\n' in content else content[:200]
results['primary_keyword']['in_first_paragraph'] = (
primary.lower() in first_para.lower()
)
# Analyze secondary keywords
for keyword in secondary:
count = content_lower.count(keyword.lower())
results['secondary_keywords'].append({
'keyword': keyword,
'count': count,
'density': count / word_count if word_count > 0 else 0
})
# Extract potential LSI keywords
results['lsi_keywords'] = self._extract_lsi_keywords(content, primary)
return results
def _analyze_structure(self, content: str) -> Dict:
"""Analyze content structure for SEO"""
lines = content.split('\n')
structure = {
'headings': {'h1': 0, 'h2': 0, 'h3': 0, 'total': 0},
'paragraphs': 0,
'lists': 0,
'images': 0,
'links': {'internal': 0, 'external': 0},
'avg_paragraph_length': 0
}
paragraphs = []
current_para = []
for line in lines:
# Count headings
if line.startswith('# '):
structure['headings']['h1'] += 1
structure['headings']['total'] += 1
elif line.startswith('## '):
structure['headings']['h2'] += 1
structure['headings']['total'] += 1
elif line.startswith('### '):
structure['headings']['h3'] += 1
structure['headings']['total'] += 1
# Count lists
if line.strip().startswith(('- ', '* ', '1. ')):
structure['lists'] += 1
# Count links
internal_links = len(re.findall(r'\[.*?\]\(/.*?\)', line))
external_links = len(re.findall(r'\[.*?\]\(https?://.*?\)', line))
structure['links']['internal'] += internal_links
structure['links']['external'] += external_links
# Track paragraphs
if line.strip() and not line.startswith('#'):
current_para.append(line)
elif current_para:
paragraphs.append(' '.join(current_para))
current_para = []
if current_para:
paragraphs.append(' '.join(current_para))
structure['paragraphs'] = len(paragraphs)
if paragraphs:
avg_length = sum(len(p.split()) for p in paragraphs) / len(paragraphs)
structure['avg_paragraph_length'] = round(avg_length, 1)
return structure
def _analyze_readability(self, content: str) -> Dict:
"""Analyze content readability"""
sentences = re.split(r'[.!?]+', content)
words = content.split()
if not sentences or not words:
return {'score': 0, 'level': 'Unknown'}
avg_sentence_length = len(words) / len(sentences)
# Simple readability scoring
if avg_sentence_length < 15:
level = 'Easy'
score = 90
elif avg_sentence_length < 20:
level = 'Moderate'
score = 70
elif avg_sentence_length < 25:
level = 'Difficult'
score = 50
else:
level = 'Very Difficult'
score = 30
return {
'score': score,
'level': level,
'avg_sentence_length': round(avg_sentence_length, 1)
}
def _extract_lsi_keywords(self, content: str, primary_keyword: str) -> List[str]:
"""Extract potential LSI (semantically related) keywords"""
words = re.findall(r'\b[a-z]+\b', content.lower())
word_freq = {}
# Count word frequencies
for word in words:
if word not in self.stop_words and len(word) > 3:
word_freq[word] = word_freq.get(word, 0) + 1
# Sort by frequency and return top related terms
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
# Filter out the primary keyword and return top 10
lsi_keywords = []
for word, count in sorted_words:
if word != primary_keyword.lower() and count > 1:
lsi_keywords.append(word)
if len(lsi_keywords) >= 10:
break
return lsi_keywords
def _generate_meta_suggestions(self, content: str, keyword: str = None) -> Dict:
"""Generate SEO meta tag suggestions"""
# Extract first sentence for description base
sentences = re.split(r'[.!?]+', content)
first_sentence = sentences[0] if sentences else content[:160]
suggestions = {
'title': '',
'meta_description': '',
'url_slug': '',
'og_title': '',
'og_description': ''
}
if keyword:
# Title suggestion
suggestions['title'] = f"{keyword.title()} - Complete Guide"
if len(suggestions['title']) > 60:
suggestions['title'] = keyword.title()[:57] + "..."
# Meta description
desc_base = f"Learn everything about {keyword}. {first_sentence}"
if len(desc_base) > 160:
desc_base = desc_base[:157] + "..."
suggestions['meta_description'] = desc_base
# URL slug
suggestions['url_slug'] = re.sub(r'[^a-z0-9-]+', '-',
keyword.lower()).strip('-')
# Open Graph tags
suggestions['og_title'] = suggestions['title']
suggestions['og_description'] = suggestions['meta_description']
return suggestions
def _calculate_seo_score(self, analysis: Dict) -> int:
"""Calculate overall SEO optimization score"""
score = 0
max_score = 100
# Content length scoring (20 points)
if 300 <= analysis['content_length'] <= 2500:
score += 20
elif 200 <= analysis['content_length'] < 300:
score += 10
elif analysis['content_length'] > 2500:
score += 15
# Keyword optimization (30 points)
if analysis['keyword_analysis']:
kw_data = analysis['keyword_analysis']['primary_keyword']
# Density scoring
if 0.01 <= kw_data['density'] <= 0.03:
score += 15
elif 0.005 <= kw_data['density'] < 0.01:
score += 8
# Placement scoring
if kw_data['in_first_paragraph']:
score += 10
if kw_data.get('in_headings'):
score += 5
# Structure scoring (25 points)
struct = analysis['structure_analysis']
if struct['headings']['total'] > 0:
score += 10
if struct['paragraphs'] >= 3:
score += 10
if struct['links']['internal'] > 0 or struct['links']['external'] > 0:
score += 5
# Readability scoring (25 points)
readability_score = analysis['readability']['score']
score += int(readability_score * 0.25)
return min(score, max_score)
def _generate_recommendations(self, analysis: Dict) -> List[str]:
"""Generate SEO improvement recommendations"""
recommendations = []
# Content length recommendations
if analysis['content_length'] < 300:
recommendations.append(
f"Increase content length to at least 300 words (currently {analysis['content_length']})"
)
elif analysis['content_length'] > 3000:
recommendations.append(
"Consider breaking long content into multiple pages or adding a table of contents"
)
# Keyword recommendations
if analysis['keyword_analysis']:
kw_data = analysis['keyword_analysis']['primary_keyword']
if kw_data['density'] < 0.01:
recommendations.append(
f"Increase keyword density for '{kw_data['keyword']}' (currently {kw_data['density']:.2%})"
)
elif kw_data['density'] > 0.03:
recommendations.append(
f"Reduce keyword density to avoid over-optimization (currently {kw_data['density']:.2%})"
)
if not kw_data['in_first_paragraph']:
recommendations.append(
"Include primary keyword in the first paragraph"
)
# Structure recommendations
struct = analysis['structure_analysis']
if struct['headings']['total'] == 0:
recommendations.append("Add headings (H1, H2, H3) to improve content structure")
if struct['links']['internal'] == 0:
recommendations.append("Add internal links to related content")
if struct['avg_paragraph_length'] > 150:
recommendations.append("Break up long paragraphs for better readability")
# Readability recommendations
if analysis['readability']['avg_sentence_length'] > 20:
recommendations.append("Simplify sentences for better readability")
return recommendations
def optimize_content(content: str, keyword: str = None,
secondary_keywords: List[str] = None) -> str:
"""Main function to optimize content"""
optimizer = SEOOptimizer()
# Parse secondary keywords from comma-separated string if provided
if secondary_keywords and isinstance(secondary_keywords, str):
secondary_keywords = [kw.strip() for kw in secondary_keywords.split(',')]
results = optimizer.analyze(content, keyword, secondary_keywords)
# Format output
output = [
"=== SEO Content Analysis ===",
f"Overall SEO Score: {results['optimization_score']}/100",
f"Content Length: {results['content_length']} words",
f"",
"Content Structure:",
f" Headings: {results['structure_analysis']['headings']['total']}",
f" Paragraphs: {results['structure_analysis']['paragraphs']}",
f" Avg Paragraph Length: {results['structure_analysis']['avg_paragraph_length']} words",
f" Internal Links: {results['structure_analysis']['links']['internal']}",
f" External Links: {results['structure_analysis']['links']['external']}",
f"",
f"Readability: {results['readability']['level']} (Score: {results['readability']['score']})",
f""
]
if results['keyword_analysis']:
kw = results['keyword_analysis']['primary_keyword']
output.extend([
"Keyword Analysis:",
f" Primary Keyword: {kw['keyword']}",
f" Count: {kw['count']}",
f" Density: {kw['density']:.2%}",
f" In First Paragraph: {'Yes' if kw['in_first_paragraph'] else 'No'}",
f""
])
if results['keyword_analysis']['lsi_keywords']:
output.append(" Related Keywords Found:")
for lsi in results['keyword_analysis']['lsi_keywords'][:5]:
output.append(f" • {lsi}")
output.append("")
if results['meta_suggestions']:
output.extend([
"Meta Tag Suggestions:",
f" Title: {results['meta_suggestions']['title']}",
f" Description: {results['meta_suggestions']['meta_description']}",
f" URL Slug: {results['meta_suggestions']['url_slug']}",
f""
])
output.extend([
"Recommendations:",
])
for rec in results['recommendations']:
output.append(f" • {rec}")
return '\n'.join(output)
if __name__ == "__main__":
import sys
import argparse
parser = argparse.ArgumentParser(
description="SEO Content Optimizer - Analyzes and optimizes content for SEO"
)
parser.add_argument(
"file", nargs="?", default=None,
help="Text file to analyze"
)
parser.add_argument(
"--keyword", "-k", default=None,
help="Primary keyword to optimize for"
)
parser.add_argument(
"--secondary", "-s", default=None,
help="Comma-separated secondary keywords"
)
args = parser.parse_args()
if args.file:
with open(args.file, 'r') as f:
content = f.read()
print(optimize_content(content, args.keyword, args.secondary))
else:
print("Usage: python seo_optimizer.py <file> [--keyword primary] [--secondary kw1,kw2]")
FILE:templates/content-brief-template.md
# Content Brief Template
> Fill in every field before writing starts. Blank fields mean assumptions. Assumptions mean rewrites.
---
## Basic Info
| Field | Value |
|---|---|
| **Working Title** | |
| **Target Publish Date** | |
| **Author / Owner** | |
| **Content Type** | Blog post / Guide / Case study / Comparison / Listicle |
| **Target Length** | ~___ words |
| **Goal** | Awareness / Lead gen / SEO / Thought leadership / Product education |
---
## SEO Targeting
| Field | Value |
|---|---|
| **Primary Keyword** | |
| **Monthly Search Volume** | |
| **Keyword Difficulty** | |
| **Secondary Keywords** (2-4) | |
| **Search Intent** | Informational / Commercial / Navigational |
| **SERP Features to Target** | Featured snippet / FAQ / People Also Ask |
---
## Audience
**Who is reading this?**
(Job title, company stage, pain point they're searching from)
**What do they already know?**
(Level: beginner / intermediate / expert)
**What do they want to walk away with?**
(The specific outcome or answer)
**What's their biggest objection or doubt?**
(What might make them click away?)
---
## Angle & POV
**The core argument / unique angle:**
(One sentence — what's our take that's different from the competition?)
**Why should they trust us on this?**
(Our authority, experience, or data that backs the angle)
**What's the competition missing?**
(Specific gap in top-ranking content we're exploiting)
---
## Structure
**H1 (draft):**
**Intro approach:**
(Hook type: stat / story / counterintuitive claim / problem statement)
**H2 Outline:**
1.
2.
3.
4.
5.
(Add more as needed)
**Conclusion approach:**
(Summary + CTA or next step)
---
## Sources & Research
| Source | Type | Key Claim / Data Point |
|---|---|---|
| | Study / Report | |
| | Expert quote | |
| | Official docs | |
| | Data / survey | |
**Minimum 3 sources required before drafting.**
---
## Internal Linking
**Links FROM this piece (to existing content):**
- [Anchor text] → [URL / page title]
- [Anchor text] → [URL / page title]
**Links TO this piece (from existing content):**
- [Existing page] → link to this once published
---
## Competitive Pieces to Beat
| URL | Word Count | What They Do Well | What They Miss |
|---|---|---|---|
| | | | |
| | | | |
---
## Success Criteria
- [ ] Ranks on page 1 for primary keyword within 6 months
- [ ] Achieves target engagement (avg time on page > ___ min)
- [ ] Generates ___ leads / clicks to product within 30 days
- [ ] Other: ___
---
## Notes / Special Instructions
(Brand voice requirements, topics to avoid, tone calibration, product mentions)
Soạn tài liệu kinh doanh theo từng khu vực pháp lý: hợp đồng freelance, đề xuất dự án, SOW, NDA và MSA.
---
name: "contract-and-proposal-writer"
description: "Generate professional, jurisdiction-aware business documents: freelance contracts, project proposals, SOWs, NDAs, and MSAs. Structured Markdown output with docx conversion instructions. Covers US (Delaware), EU (GDPR), UK, and DACH (German law) jurisdictions. Not a substitute for legal counsel — use as strong starting points. Use when drafting a freelance contract, preparing a client proposal, writing an SOW for a new engagement, or producing an NDA before sharing sensitive material."
---
# Contract & Proposal Writer
**Tier:** POWERFUL
**Category:** Business Growth
**Domain:** Legal Documents, Business Development, Client Relations
---
## Overview
Generate professional, jurisdiction-aware business documents: freelance contracts, project proposals, SOWs, NDAs, and MSAs. Outputs structured Markdown with docx conversion instructions. Covers US (Delaware), EU (GDPR), UK, and DACH (German law) jurisdictions.
**Not a substitute for legal counsel.** Use these templates as strong starting points; review with an attorney for high-value or complex engagements.
---
## Core Capabilities
- Freelance development contracts (fixed-price & hourly)
- Project proposals with timeline/budget breakdown
- Statements of Work (SOW) with deliverables matrix
- NDAs (mutual & one-way)
- Master Service Agreements (MSA)
- Jurisdiction-specific clauses (US/EU/UK/DACH)
- GDPR Data Processing Addenda (EU/DACH)
---
## Key Clauses Reference
| Clause | Options |
|--------|---------|
| Payment terms | Net-30, milestone-based, monthly retainer |
| IP ownership | Work-for-hire (US), assignment (EU/UK), license-back |
| Liability cap | 1x contract value (standard), 3x (high-risk) |
| Termination | For cause (14-day cure), convenience (30/60/90-day notice) |
| Confidentiality | 2-5 year term, perpetual for trade secrets |
| Warranty | "As-is" disclaimer, limited 30/90-day fix warranty |
| Dispute resolution | Arbitration (AAA/ICC), courts (jurisdiction-specific) |
---
## When to Use
- Starting a new client engagement and need a contract fast
- Client asks for a proposal with pricing and timeline
- Partnership or vendor relationship requiring an MSA
- Protecting IP or confidential information with an NDA
- EU/DACH project requiring GDPR-compliant data clauses
---
## Workflow
### 1. Gather Requirements
Ask the user:
1. Document type? (contract / proposal / SOW / NDA / MSA)
2. Jurisdiction? (US-Delaware / EU / UK / DACH)
3. Engagement type? (fixed-price / hourly / retainer)
4. Parties? (names, roles, business addresses)
5. Scope summary? (1-3 sentences)
6. Total value or hourly rate?
7. Start date / end date or duration?
8. Special requirements? (IP assignment, white-label, subcontractors)
### 2. Select Template
| Type | Jurisdiction | Template |
|------|-------------|----------|
| Dev contract fixed | Any | Template A |
| Consulting retainer | Any | Template B |
| SaaS partnership | Any | Template C |
| NDA mutual | US/EU/UK/DACH | NDA-M |
| NDA one-way | US/EU/UK/DACH | NDA-OW |
| SOW | Any | SOW base |
### 3. Generate & Fill
Fill all [BRACKETED] placeholders. Flag missing data as "REQUIRED".
### 4. Convert to DOCX
```bash
# Install pandoc
brew install pandoc # macOS
apt install pandoc # Ubuntu
# Basic conversion
pandoc contract.md -o contract.docx \
--reference-doc=reference.docx \
-V geometry:margin=1in
# With numbered sections (legal style)
pandoc contract.md -o contract.docx \
--number-sections \
-V documentclass=article \
-V fontsize=11pt
# With custom company template
pandoc contract.md -o contract.docx \
--reference-doc=company-template.docx
```
---
## Jurisdiction Notes
### US (Delaware)
- Governing law: State of Delaware
- Work-for-hire doctrine applies (Copyright Act 101)
- Arbitration: AAA Commercial Rules
- Non-compete: enforceable with reasonable scope/time
### EU (GDPR)
- Must include Data Processing Addendum if handling personal data
- IP assignment requires separate written deed in some member states
- Arbitration: ICC or local chamber
### UK (post-Brexit)
- Governed by English law
- IP: Patents Act 1977 / CDPA 1988
- Arbitration: LCIA Rules
- Data: UK GDPR (post-Brexit equivalent)
### DACH (Germany / Austria / Switzerland)
- BGB (Buergerliches Gesetzbuch) governs contracts
- Written form requirement for certain clauses (para 126 BGB)
- IP: Author always retains moral rights; must explicitly transfer Nutzungsrechte
- Non-competes: max 2 years, compensation required (para 74 HGB)
- Jurisdiction: German courts (Landgericht) or DIS arbitration
- DSGVO (GDPR implementation) mandatory for personal data processing
- Kuendigungsfristen: statutory notice periods apply
---
## Template A: Web Dev Fixed-Price Contract
```markdown
# SOFTWARE DEVELOPMENT AGREEMENT
**Effective Date:** [DATE]
**Client:** [CLIENT LEGAL NAME], [ADDRESS] ("Client")
**Developer:** [YOUR LEGAL NAME / COMPANY], [ADDRESS] ("Developer")
---
## 1. SERVICES
Developer agrees to design, develop, and deliver:
**Project:** [PROJECT NAME]
**Description:** [1-3 sentence scope]
**Deliverables:**
- [Deliverable 1] due [DATE]
- [Deliverable 2] due [DATE]
- [Deliverable 3] due [DATE]
## 2. PAYMENT
**Total Fee:** [CURRENCY] [AMOUNT]
| Milestone | Amount | Due |
|-----------|--------|-----|
| Contract signing | 50% | Upon execution |
| Beta delivery | 25% | [DATE] |
| Final acceptance | 25% | Within 5 days of acceptance |
Late payments accrue interest at 1.5% per month.
Client has [10] business days to accept or reject deliverables in writing.
## 3. INTELLECTUAL PROPERTY
Upon receipt of full payment, Developer assigns all right, title, and interest in the
Work Product to Client as a work made for hire (US) / by assignment of future copyright (EU/UK).
Developer retains the right to display Work Product in portfolio unless Client
requests confidentiality in writing within [30] days of delivery.
Pre-existing IP (tools, libraries, frameworks) remains Developer's property.
Developer grants Client a perpetual, royalty-free license to use pre-existing IP
as embedded in the Work Product.
## 4. CONFIDENTIALITY
Each party keeps confidential all non-public information received from the other.
This obligation survives termination for [3] years.
## 5. WARRANTIES
Developer warrants Work Product will substantially conform to specifications for
[90] days post-delivery. Developer will fix material defects at no charge during
this period. EXCEPT AS STATED, WORK PRODUCT IS PROVIDED "AS IS."
## 6. LIABILITY
Developer's total liability shall not exceed total fees paid under this Agreement.
Neither party liable for indirect, incidental, or consequential damages.
## 7. TERMINATION
For Cause: Either party may terminate if the other materially breaches and fails
to cure within [14] days of written notice.
For Convenience: Client may terminate with [30] days written notice and pay for
all work completed plus [10%] of remaining contract value.
## 8. DISPUTE RESOLUTION
US: Binding arbitration under AAA Commercial Rules, [CITY], Delaware law.
EU/DACH: ICC / DIS arbitration, [CITY]. German / English law.
UK: LCIA Rules, London. English law.
## 9. GENERAL
- Entire Agreement: Supersedes all prior discussions.
- Amendments: Must be in writing, signed by both parties.
- Independent Contractor: Developer is not an employee of Client.
---
CLIENT: _________________________ Date: _________
[CLIENT NAME], [TITLE]
DEVELOPER: _________________________ Date: _________
[YOUR NAME], [TITLE]
```
---
## Template B: Monthly Consulting Retainer
```markdown
# CONSULTING RETAINER AGREEMENT
**Effective Date:** [DATE]
**Client:** [CLIENT LEGAL NAME] ("Client")
**Consultant:** [YOUR NAME / COMPANY] ("Consultant")
---
## 1. SERVICES
Consultant provides [DOMAIN, e.g., "CTO advisory and technical architecture"] services.
**Monthly Hours:** Up to [X] hours/month
**Rollover:** Unused hours [do / do not] roll over (max [X] hours banked)
**Overflow Rate:** [CURRENCY] [RATE]/hr for hours exceeding retainer
## 2. FEES
**Monthly Retainer:** [CURRENCY] [AMOUNT], due on the 1st of each month.
**Payment Method:** Bank transfer / Stripe / SEPA direct debit
**Late Payment:** 2% monthly interest after [10]-day grace period.
## 3. TERM AND TERMINATION
**Initial Term:** [3] months starting [DATE]
**Renewal:** Auto-renews monthly unless either party gives [30] days written notice.
**Immediate termination:** For material breach uncured after [7] days notice.
On termination, Consultant delivers all work in progress within [5] business days.
## 4. INTELLECTUAL PROPERTY
Work product created under this Agreement belongs to [Client / Consultant / jointly].
Advisory output (recommendations, analyses) are Client property upon full payment.
## 5. EXCLUSIVITY
[OPTION A - Non-exclusive:]
This Agreement is non-exclusive. Consultant may work with other clients.
[OPTION B - Partial exclusivity:]
Consultant will not work with direct competitors of Client during the term
and [90] days thereafter.
## 6. CONFIDENTIALITY AND DATA PROTECTION
EU/DACH: If Consultant processes personal data on behalf of Client, the parties
shall execute a Data Processing Agreement (DPA) per Art. 28 GDPR.
## 7. LIABILITY
Consultant's aggregate liability is capped at [3x] the fees paid in the [3] months
preceding the claim.
---
Signatures as above.
```
---
## Template C: SaaS Partnership Agreement
```markdown
# SAAS PARTNERSHIP AGREEMENT
**Effective Date:** [DATE]
**Provider:** [NAME], [ADDRESS]
**Partner:** [NAME], [ADDRESS]
---
## 1. PURPOSE
Provider grants Partner [reseller / referral / white-label / integration] rights to
Provider's [PRODUCT NAME] ("Software") subject to this Agreement.
## 2. PARTNERSHIP TYPE
[ ] Referral: Partner refers customers; earns [X%] of first-year ARR per referral.
[ ] Reseller: Partner resells licenses; earns [X%] discount off list price.
[ ] White-label: Partner rebrands Software; pays [AMOUNT]/month platform fee.
[ ] Integration: Partner integrates Software via API; terms in Exhibit A.
## 3. REVENUE SHARE
| Tier | Monthly ARR Referred | Commission |
|------|---------------------|------------|
| Bronze | < $10,000 | [X]% |
| Silver | $10,000-$50,000 | [X]% |
| Gold | > $50,000 | [X]% |
Payout: Net-30 after month close, minimum $[500] threshold.
## 4. INTELLECTUAL PROPERTY
Each party retains all IP in its own products. No implied licenses.
Partner may use Provider's marks per Provider's Brand Guidelines (Exhibit B).
## 5. DATA AND PRIVACY
Each party is an independent data controller for its own customers.
Joint processing requires a separate DPA (Exhibit C - EU/DACH projects).
## 6. TERM
Initial: [12] months. Renews annually unless [90]-day written notice given.
Termination for Cause: [30]-day cure period for material breach.
## 7. LIMITATION OF LIABILITY
Each party's liability capped at [1x] fees paid/received in prior [12] months.
Mutual indemnification for IP infringement claims from own products.
---
Signatures, exhibits, and governing law per applicable jurisdiction.
```
---
## GDPR Data Processing Addendum (EU/DACH Clause Block)
```markdown
## DATA PROCESSING ADDENDUM (Art. 28 GDPR)
Controller: [CLIENT NAME]
Processor: [CONTRACTOR NAME]
### Subject Matter
Processor processes personal data on behalf of Controller solely to perform services
under the main Agreement.
### Categories of Data Subjects
[e.g., end users, employees, customers]
### Categories of Personal Data
[e.g., names, email addresses, usage data]
### Processing Duration
For the term of the main Agreement; deletion within [30] days of termination.
### Processor Obligations
- Process data only on Controller's documented instructions
- Ensure persons authorized to process have committed to confidentiality
- Implement technical and organizational measures per Art. 32 GDPR
- Assist Controller with data subject rights requests
- Not engage sub-processors without prior written consent
- Delete or return all personal data upon termination
### Sub-processors (current as of Effective Date)
| Sub-processor | Location | Purpose |
|--------------|----------|---------|
| [AWS / GCP / Azure] | [Region] | Cloud hosting |
| [Other] | [Location] | [Purpose] |
### Cross-border Transfers
Data transfers outside EEA covered by: [ ] SCCs [ ] Adequacy Decision [ ] BCRs
```
---
## Common Pitfalls
1. **Missing IP assignment language** - "work for hire" alone is insufficient in EU; need explicit assignment of Nutzungsrechte in DACH
2. **Vague acceptance criteria** - Always define what "accepted" means (written sign-off, X days to reject)
3. **No change order process** - Scope creep kills fixed-price projects; add a clause for out-of-scope work
4. **Jurisdiction mismatch** - Choosing Delaware law for a German-only project creates enforcement problems
5. **Missing limitation of liability** - Without a cap, one bug could mean unlimited damages
6. **Oral amendments** - Contracts modified verbally are hard to enforce; always require written amendments
---
## Best Practices
- Use **milestone payments** over net-30 for projects >$10K - reduces cash flow risk
- For EU/DACH: always check if a DPA is needed (any personal data = yes)
- For DACH: include a **Schriftformklausel** (written form clause) explicitly
- Add a **force majeure** clause for anything over 3 months
- For retainers: define response time SLAs (e.g., 4h urgent / 24h normal)
- Keep templates in version control; track changes with `git diff`
- Review annually - laws change, especially GDPR enforcement interpretations
- For NDAs: always specify the return/destruction of confidential materials on termination
Lãnh đạo vận hành: thiết kế quy trình, thực thi OKR, nhịp vận hành và kịch bản mở rộng quy mô.
---
name: "coo-advisor"
description: "Operations leadership for scaling companies. Process design, OKR execution, operational cadence, and scaling playbooks. Use when designing operations, setting up OKRs, building processes, scaling teams, analyzing bottlenecks, planning operational cadence, or when user mentions COO, operations, process improvement, OKRs, scaling, operational efficiency, or execution."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: c-level
domain: coo-leadership
updated: 2026-03-05
python-tools: ops_efficiency_analyzer.py, okr_tracker.py
frameworks: scaling-playbook, ops-cadence, process-frameworks
---
# COO Advisor
Operational frameworks and tools for turning strategy into execution, scaling processes, and building the organizational engine.
## Keywords
COO, chief operating officer, operations, operational excellence, process improvement, OKRs, objectives and key results, scaling, operational efficiency, execution, bottleneck analysis, process design, operational cadence, meeting cadence, org scaling, lean operations, continuous improvement
## Quick Start
```bash
python scripts/ops_efficiency_analyzer.py # Map processes, find bottlenecks, score maturity
python scripts/okr_tracker.py # Cascade OKRs, track progress, flag at-risk items
```
## Core Responsibilities
### 1. Strategy Execution
The CEO sets direction. The COO makes it happen. Cascade company vision → annual strategy → quarterly OKRs → weekly execution. See `references/ops_cadence.md` for full OKR cascade framework.
### 2. Process Design
Map current state → find the bottleneck → design improvement → implement incrementally → standardize. See `references/process_frameworks.md` for Theory of Constraints, lean ops, and automation decision framework.
**Process Maturity Scale:**
| Level | Name | Signal |
|-------|------|--------|
| 1 | Ad hoc | Different every time |
| 2 | Defined | Written but not followed |
| 3 | Measured | KPIs tracked |
| 4 | Managed | Data-driven improvement |
| 5 | Optimized | Continuous improvement loops |
### 3. Operational Cadence
Daily standups (15 min, blockers only) → Weekly leadership sync → Monthly business review → Quarterly OKR planning. See `references/ops_cadence.md` for full templates.
### 4. Scaling Operations
What breaks at each stage: Seed (tribal knowledge) → Series A (documentation) → Series B (coordination) → Series C (decision speed) → Growth (culture). See `references/scaling_playbook.md` for detailed playbook per stage.
### 5. Cross-Functional Coordination
RACI for key decisions. Escalation framework: Team lead → Dept head → COO → CEO based on impact scope.
## Key Questions a COO Asks
- "What's the bottleneck? Not what's annoying — what limits throughput."
- "How many manual steps? Which break at 3x volume?"
- "Who's the single point of failure?"
- "Can every team articulate how their work connects to company goals?"
- "The same blocker appeared 3 weeks in a row. Why isn't it fixed?"
## Operational Metrics
| Category | Metric | Target |
|----------|--------|--------|
| Execution | OKR progress (% on track) | > 70% |
| Execution | Quarterly goals hit rate | > 80% |
| Speed | Decision cycle time | < 48 hours |
| Quality | Customer-facing incidents | < 2/month |
| Efficiency | Revenue per employee | Track trend |
| Efficiency | Burn multiple | < 2x |
| People | Regrettable attrition | < 10% |
## Red Flags
- OKRs consistently 1.0 (not ambitious) or < 0.3 (disconnected from reality)
- Teams can't explain how their work maps to company goals
- Leadership meetings produce no action items two weeks running
- Same blocker in three consecutive syncs
- Process exists but nobody follows it
- Departments optimize local metrics at expense of company metrics
## Integration with Other C-Suite Roles
| When... | COO works with... | To... |
|---------|-------------------|-------|
| Strategy shifts | CEO | Translate direction into ops plan |
| Roadmap changes | CPO + CTO | Assess operational impact |
| Revenue targets change | CRO | Adjust capacity planning |
| Budget constraints | CFO | Find efficiency gains |
| Hiring plans | CHRO | Align headcount with ops needs |
| Security incidents | CISO | Coordinate response |
## Detailed References
- `references/scaling_playbook.md` — what changes at each growth stage
- `references/ops_cadence.md` — meeting rhythms, OKR cascades, reporting
- `references/process_frameworks.md` — lean ops, TOC, automation decisions
## Proactive Triggers
Surface these without being asked when you detect them in company context:
- Same blocker appearing 3+ weeks → process is broken, not just slow
- OKR check-in overdue → prompt quarterly review
- Team growing past a scaling threshold (10→30, 30→80) → flag what will break
- Decision cycle time increasing → authority structure needs adjustment
- Meeting cadence not established → propose rhythm before chaos sets in
## Output Artifacts
| Request | You Produce |
|---------|-------------|
| "Set up OKRs" | Cascaded OKR framework (company → dept → team) |
| "We're scaling fast" | Scaling readiness report with what breaks next |
| "Our process is broken" | Process map with bottleneck identified + fix plan |
| "How efficient are we?" | Ops efficiency scorecard with maturity ratings |
| "Design our meeting cadence" | Full cadence template (daily → quarterly) |
## Reasoning Technique: Step by Step
Map processes sequentially. Identify each step, handoff, and decision point. Find the bottleneck using throughput analysis. Propose improvements one step at a time.
## Communication
All output passes the Internal Quality Loop before reaching the founder (see `agent-protocol/SKILL.md`).
- Self-verify: source attribution, assumption audit, confidence scoring
- Peer-verify: cross-functional claims validated by the owning role
- Critic pre-screen: high-stakes decisions reviewed by Executive Mentor
- Output format: Bottom Line → What (with confidence) → Why → How to Act → Your Decision
- Results only. Every finding tagged: 🟢 verified, 🟡 medium, 🔴 assumed.
## Context Integration
- **Always** read `company-context.md` before responding (if it exists)
- **During board meetings:** Use only your own analysis in Phase 2 (no cross-pollination)
- **Invocation:** You can request input from other roles: `[INVOKE:role|question]`
FILE:references/ops_cadence.md
# Operational Cadence: Meetings, Async, Decisions, and Reporting
> The rhythm of your company determines its output. Bad cadence = constant context-switching, decisions made without information, and a leadership team that's always reactive.
---
## Philosophy
**Meetings are a tax.** Every hour in a meeting is an hour not spent building, selling, or serving customers. A good cadence minimizes meeting time while ensuring the right people have the right information at the right time.
**Async is default, sync is exception.** Most information sharing and routine updates should happen in writing. Reserve synchronous time for things that genuinely require real-time discussion: decisions with significant disagreement, complex problem-solving, relationship-building.
**Cadence serves strategy.** The calendar reflects priorities. If you're doing monthly all-hands but weekly status updates, you've inverted the importance.
---
## Meeting Cadence Templates
### Daily Operations
#### Daily Standup (Engineering / Product Teams)
**Format:** Async-first (Slack/Loom); sync only if blocked
**Sync duration:** 15 minutes max
**Participants:** Team (5–10 people)
**Facilitator:** Team lead or rotating
```
ASYNC FORMAT (post in #standup channel):
Yesterday: [What I completed]
Today: [What I'm working on]
Blocked: [Anything blocking me — tag the person who can unblock]
```
**Rules:**
- No status reporting in sync standup if everyone can read the async update
- Standups are not problem-solving sessions — take issues offline
- Skip standup if the team has a full-team session that day
- Kill standup if the team consistently has nothing blocked; replace with async
#### Daily Leadership Check-in (COO)
**Format:** Async only — read, don't meet
**Time:** 8:00–8:30 AM
**COO morning read:**
1. Yesterday's key metrics dashboard (5 min)
2. Overnight Slack/email escalations (5 min)
3. Today's decisions needed list (5 min)
4. Any P0/P1 incidents (check status page + on-call logs)
---
### Weekly Cadence
#### Leadership Sync (Weekly)
**Duration:** 60–90 minutes
**Participants:** C-suite + VP level
**Owner:** COO (or CEO)
**Day/Time:** Monday or Tuesday, morning
```
AGENDA TEMPLATE:
00:00–10:00 Metrics pulse (pre-read required — no presenting charts)
- Revenue: ACV, pipeline, churn delta
- Product: shipped last week, blockers this week
- Engineering: incidents, velocity
- CS: escalations, NPS delta
- People: open reqs, attrition flag
10:00–45:00 Priority items (submitted in advance, max 3)
- Item 1: [Owner: Name] [Decision needed / FYI / Input needed]
- Item 2: [Owner: Name]
- Item 3: [Owner: Name]
45:00–60:00 Parking lot / open
- Anything not covered
- Next week flagging
```
**Pre-meeting requirements:**
- Metrics dashboard updated by EOD Friday
- Priority items submitted by Sunday 6 PM
- Anyone who hasn't read the pre-read gets no floor time
**Output:** Decision log updated with outcomes, action items assigned in tracking system
#### 1:1 (Manager ↔ Direct Report)
**Duration:** 30–45 minutes
**Frequency:** Weekly (skip-levels: bi-weekly)
**Owner:** Report (the direct report sets agenda)
```
1:1 STRUCTURE:
[5 min] What's on your mind / temperature check
[15 min] Their agenda — what they want to discuss
[10 min] Manager agenda — feedback, context, decisions
[5 min] Action items review from last week
```
**1:1 anti-patterns to eliminate:**
- Using 1:1 for status updates (that's what standups are for)
- Manager dominating the agenda
- Skipping because "things are fine"
- No written record of what was discussed
**Private 1:1 doc:** Every manager/report pair maintains a shared doc with running notes, action items, and career development thread.
#### Cross-Functional Weekly Sync
**Duration:** 45 minutes
**Participants:** 2–4 team leads with shared dependencies
**Examples:** Product + Engineering, Sales + CS, Marketing + Sales
```
AGENDA:
00–10 Shared metrics (things both teams care about)
10–30 Active collaboration items — what needs coordination this week
30–40 Blockers + dependencies (what do I need from your team?)
40–45 Upcoming: what's coming that the other team should know about
```
---
### Monthly Cadence
#### All-Hands / Town Hall
**Duration:** 60–90 minutes
**Participants:** Entire company
**Owner:** CEO + functional heads
**Format:** In-person preferred; video if distributed
```
ALL-HANDS AGENDA (60 min version):
00–05 Opening — CEO sets the tone
05–20 Business update
- Where we are vs. plan (actuals vs. budget)
- Key wins and learning moments from last month
- What we're focused on this month
20–40 Functional spotlights (2 functions, 10 min each)
- What we shipped / what we did
- What we learned
- What's next
40–55 Open Q&A (no screened questions — take everything)
55–60 Closing
ALL-HANDS PREP CHECKLIST:
□ CEO talking points reviewed 48h in advance
□ Metrics slides reviewed by Finance for accuracy
□ Q&A prep — leadership team briefs on likely questions
□ Recording setup confirmed
□ Async option for timezones (recording posted within 2h)
□ Action items from Q&A captured and published within 24h
```
#### Monthly Business Review (MBR)
**Duration:** 2 hours
**Participants:** Leadership team
**Owner:** COO
```
MBR AGENDA:
00–20 Financial review (Finance presents)
- Revenue vs. plan, by segment
- Burn rate, runway
- Headcount actual vs. plan
- Key cost drivers
20–60 Functional reviews (each VP, 8 min each)
Standard template per function:
- Metrics: [3 key metrics vs. prior month vs. plan]
- Wins: [top 2-3 wins]
- Gaps: [where we missed and why]
- Next 30 days: [top 3 priorities]
60–90 Strategic topics (pre-submitted)
- Items requiring cross-functional decision
- Risks or issues needing leadership visibility
90–110 Decisions and action items
- Document decisions made
- Assign owners and deadlines
110–120 Retrospective
- What's working in how we operate?
- What needs to change?
```
**MBR pre-read package** (published 48h before):
- Financial summary (1 page)
- Each function's 1-pager (see template below)
```
FUNCTIONAL 1-PAGER TEMPLATE:
Function: [Name] Month: [Month Year]
Owner: [VP Name]
TOP METRICS:
| Metric | Target | Actual | vs. LM | vs. Plan |
|--------|--------|--------|--------|----------|
| [M1] | | | | |
| [M2] | | | | |
| [M3] | | | | |
WINS (2-3 bullets):
•
•
GAPS (be honest — no spin):
•
•
DEPENDENCIES (what I need from other teams):
•
NEXT 30 DAYS (top 3 priorities):
1.
2.
3.
```
---
### Quarterly Cadence
#### Quarterly Business Review (QBR)
**Duration:** Half day (4 hours)
**Participants:** Leadership team + key functional leads
**Owner:** CEO + COO
```
QBR AGENDA (4 hours):
PART 1: Look back (90 min)
- CEO: Business context and narrative (15 min)
- Finance: Full quarter P&L review (20 min)
- Each function: 10-min review against OKRs
Format: Hit/Miss/Partial for each objective + root cause
PART 2: Look forward (90 min)
- Product/Engineering: What ships next quarter (20 min)
- Sales/Marketing: Pipeline and demand plan (20 min)
- People: Headcount plan and key hires (15 min)
- Finance: Budget and forecast (20 min)
- Cross-functional dependencies (15 min)
PART 3: Strategic discussion (60 min)
- 1–2 strategic topics requiring deep discussion
- Pre-submitted and pre-read
PART 4: OKR setting for next quarter (30 min)
- Draft OKRs reviewed and challenged
- Final OKRs locked or assigned for next week finalization
```
#### Quarterly Leadership Off-site
**Duration:** 1–2 days (Series B+)
**Participants:** C-suite + VPs
**Purpose:** Strategy alignment, relationship building, hard conversations
**Off-site agenda principles:**
- No laptops during sessions (phones away)
- At least 50% discussion, max 50% presentation
- Include one session on how the leadership team is functioning (not just what the business is doing)
- Output: 1-page summary of decisions and commitments shared with the company
---
### Annual Cadence
#### Annual Planning Cycle
**Timeline:** Start 8–10 weeks before fiscal year end
```
ANNUAL PLANNING TIMELINE:
Week -10: Company strategic priorities draft (CEO + COO)
Week -8: Revenue model + market analysis (Finance + Sales)
Week -7: Functional goal-setting begins
Week -6: Headcount planning by function
Week -5: Draft plans reviewed by COO
Week -4: Cross-functional dependency alignment
Week -3: Budget finalization
Week -2: Board review (if applicable)
Week -1: Final company OKRs published
Week 0: Year kick-off all-hands
```
#### Year Kick-off All-Hands
**Duration:** 2–4 hours
**Participants:** Entire company
**Purpose:** Align entire company on year strategy and goals
```
KICK-OFF AGENDA:
- Last year retrospective: What we accomplished, what we learned
- Market context: Why now, why us
- Year strategy: The 2-3 things that matter most
- OKRs: Company-level goals, each function's goals
- Culture: How we'll work together
- Q&A: Open and honest
```
---
## Async Communication Frameworks
### The Writing-First Culture
All communication defaults to written unless real-time is genuinely necessary. This is how you scale decision-making without scaling meetings.
**Written first means:**
- Decisions are documented before they're communicated
- Updates are published before questions are asked
- Problems are described before solutions are proposed
### Slack Channel Architecture
```
REQUIRED CHANNELS:
#announcements Read-only. Major company announcements only.
#general Company-wide conversation
#leadership-public Leadership decisions visible to all (transparency)
#incidents P0/P1 incidents only. Auto-resolved when incident is closed.
#metrics Automated metric updates. No discussion here.
#wins Customer wins, team wins. Culture channel.
FUNCTIONAL CHANNELS:
#engineering, #product, #sales, #marketing, #cs, #people, #finance
PROJECT CHANNELS:
#proj-[name] Temporary. Archive when project ships.
DECISION CHANNELS:
#decisions All cross-team decisions logged here with context
```
**Anti-patterns to eliminate:**
- DMs for work decisions (decisions belong in channels, visible to team)
- @channel abuse (train people — this means everyone stops what they're doing)
- Thread avoidance (all replies go in threads, period)
- Multiple channels for same function (merge aggressively)
### Async Decision Template
When a decision needs input but doesn't require a meeting:
```
DECISION REQUEST (post in #decisions):
**Context:** [1-3 sentences on why this decision is needed]
**Options considered:**
A) [Option A] — Pros: X. Cons: Y.
B) [Option B] — Pros: X. Cons: Y.
**Recommendation:** [Your recommendation and why]
**Input needed from:** @person1, @person2 (tag specific people)
**Decide by:** [Date/Time — give at least 24 hours]
**If no response:** [Default action if no input received]
```
### Loom / Video for Async Communication
Use async video for:
- Explaining complex technical architecture
- Walking through a design or document with context
- Giving feedback that needs tone/nuance
- Team updates that would otherwise be a meeting
**Loom best practices:**
- Keep under 5 minutes; break up anything longer
- Always include a summary comment with key points
- Ask viewers to leave timestamp comments for specific questions
---
## Decision-Making Frameworks
### RAPID
The most practical decision-making framework for startups scaling to enterprises.
| Role | Meaning | Responsibility |
|------|---------|---------------|
| **R** — Recommend | Proposes decision with analysis | Does the work, gathers input, makes recommendation |
| **A** — Agree | Must agree before decision is final | Has veto power; should be used sparingly |
| **P** — Perform | Executes the decision | Consulted during recommendation phase |
| **I** — Input | Consulted for perspective | Shares point of view; not binding |
| **D** — Decide | Makes the final call | One person only — groups don't decide |
**How to use RAPID:**
1. For every significant decision, explicitly assign R, A, P, I, D before work begins
2. The D role is always one person — never a committee
3. Agree (A) roles should be limited to 2–3 people maximum; more = paralysis
4. Post the RAPID in the decision doc so everyone knows the structure
**Example application:**
```
Decision: Migrate from PostgreSQL to distributed database
R: VP Engineering
A: CTO, COO (for cost implications)
P: Infrastructure team
I: Product leads, Finance
D: CTO
```
### RACI
Better for ongoing processes than one-time decisions. Use RACI for recurring operational responsibilities.
| Role | Meaning |
|------|---------|
| **R** — Responsible | Does the work |
| **A** — Accountable | Owns the outcome; one person only |
| **C** — Consulted | Input before decisions/actions |
| **I** — Informed | Told of decisions/actions after the fact |
**RACI matrix template:**
```
PROCESS: Customer Escalation Handling
Task | CS Lead | VP CS | Eng Lead | CEO
------------------------|---------|-------|----------|----
Receive escalation | R | I | I | -
Diagnose issue | R | C | C | -
Communicate to customer | R | A | - | I (major)
Resolve technical issue | C | - | R | -
Close escalation | R | A | I | -
Post-mortem (P0/P1) | C | A | R | I
```
**Common RACI mistakes:**
- Multiple A roles (breaks accountability)
- R and A always same person (defeats the purpose)
- Too many C roles (everyone's consulted, nothing moves)
- Not distinguishing C from I (different obligations)
### DRI (Directly Responsible Individual)
Apple's framework; used widely in fast-moving tech companies. Simpler than RAPID/RACI for internal use.
**The rule:** Every project, deliverable, and decision has exactly one DRI. The DRI is the person who gets credit when it succeeds and gets called on when it fails. No DRI = no accountability.
**DRI requirements:**
- Listed by name in every project brief
- Has authority to make decisions within scope
- Is responsible for communicating status
- Cannot blame lack of resources — their job is to escalate when blocked
**DRI vs. RACI:** Use DRI for project ownership and RACI for process ownership. They complement each other.
### Decision Log
Every significant decision gets logged. Significant = affects more than one team, costs more than $10K, or is difficult to reverse.
```
DECISION LOG FORMAT:
Date: [YYYY-MM-DD]
Decision: [One sentence summary]
Context: [Why was this decision needed? What was the situation?]
Options considered: [What alternatives were evaluated?]
Decision made: [What was decided?]
Rationale: [Why this option?]
Owner: [Who made the final call?]
Reversible: [Yes / No / Partially]
Review date: [When should this decision be revisited?]
Outcome: [Filled in later — what actually happened?]
```
---
## Reporting Templates
### Weekly CEO/COO Dashboard
```
COMPANY HEALTH — WEEK OF [DATE]
REVENUE
ARR: $[X]M (vs. plan: +/-X%, vs. LW: +/-X%)
New ARR this week: $[X]K
Churned ARR: $[X]K
Pipeline (90-day): $[X]M
PRODUCT
Shipped this week: [Brief list]
P0/P1 incidents: [Count] — [1-line summary if any]
Deploy frequency: [X per week]
CUSTOMER
Active customers: [X]
NPS (rolling 30d): [X]
Open escalations: [X] (P0: [X], P1: [X])
PEOPLE
Headcount: [X] (vs. plan: [X])
Open reqs: [X]
Attrition (30d): [X]
CASH
Cash on hand: $[X]M
Burn (last 30d): $[X]M
Runway: [X] months
🔴 ISSUES (needs leadership attention):
•
•
🟡 WATCH (monitor, no action yet):
•
🟢 WINS:
•
```
### Monthly Investor/Board Update
```
[COMPANY NAME] — MONTHLY UPDATE — [MONTH YEAR]
THE HEADLINE
[2-3 sentences: what was the defining story of this month?]
KEY METRICS
| Metric | [Month] | vs. Prior | vs. Plan |
|--------|---------|-----------|----------|
| ARR | | | |
| MRR Added | | | |
| Churn | | | |
| NRR | | | |
| Burn | | | |
| Runway | | | |
WINS
1. [Specific, concrete win with numbers]
2. [Second win]
3. [Third win]
CHALLENGES
1. [Honest description of challenge + what you're doing about it]
2. [Second challenge]
KEY DECISIONS MADE
• [Decision + brief rationale]
ASKS FROM INVESTORS
• [Specific ask with context — intros, advice, etc.]
NEXT MONTH PRIORITIES
1.
2.
3.
```
### Quarterly OKR Progress Report
```
Q[X] OKR PROGRESS — [COMPANY NAME]
SCORING GUIDE:
🟢 On track (>70% confidence of hitting target)
🟡 At risk (50-70% confidence)
🔴 Off track (<50% confidence)
COMPANY OBJECTIVES:
O1: [Objective title]
KR1.1: [Key Result] ............... [X]% 🟢
KR1.2: [Key Result] ............... [X]% 🟡
Objective confidence: 🟢 | Notes: [1 line]
O2: [Objective title]
KR2.1: [Key Result] ............... [X]% 🔴
KR2.2: [Key Result] ............... [X]% 🟢
Objective confidence: 🟡 | Notes: [1 line]
FUNCTIONAL OBJECTIVES:
[Same format per function]
OVERALL QUARTER HEALTH: 🟡
Summary: [2-3 sentences on overall trajectory]
TOP 3 ACTIONS TO GET BACK ON TRACK:
1. [Action + owner + deadline]
2.
3.
```
---
## Cadence Anti-Patterns to Eliminate
| Anti-Pattern | What It Looks Like | Fix |
|---|---|---|
| **Meeting creep** | Calendar blocks added over time, never removed | Quarterly calendar audit — delete all recurring meetings, re-add only what's essential |
| **Update theater** | Meetings where people read from slides | Require pre-reads; ban in-meeting presentations |
| **Decision avoidance** | Topics recur across multiple meetings | Assign a D (decider) before the meeting. If no D, don't hold the meeting. |
| **Sync for async** | Using meetings for information sharing | Move updates to Loom/Slack; protect sync time for discussion |
| **HIPPO problem** | Highest-paid person in room wins | Structure discussions so data is presented before opinions |
| **Retrospective theater** | Retros with no action items | Every retro must produce ≥1 committed change |
| **Silent agenda** | Agenda not shared until meeting starts | Agendas published 24h in advance, required reading |
---
*Cadence framework synthesized from Amazon's PR/FAQ culture, Google's OKR playbook, GitLab's remote work handbook, and operational patterns from 50+ Series A–C companies.*
FILE:references/process_frameworks.md
# Process Frameworks for Startup Operations
> Theory of Constraints, Lean, process mapping, automation, and change management — applied to real startup contexts, not factory floors.
---
## Part 1: Theory of Constraints (TOC) Applied to Startups
### What TOC Actually Says
Eliyahu Goldratt's core insight: **every system has exactly one constraint that limits throughput.** Improving anything other than the constraint is waste. The goal isn't to optimize every function — it's to identify the single bottleneck and exploit it until a new constraint emerges.
**The Five Focusing Steps:**
1. **Identify** the constraint — what limits the system's output?
2. **Exploit** it — get maximum output from the constraint without adding resources
3. **Subordinate** everything else — other activities serve the constraint's needs
4. **Elevate** it — add resources to increase constraint capacity
5. **Repeat** — when the constraint moves, find the new one
### Finding the Constraint in Your Startup
The constraint is almost never where people think it is. Sales thinks it's Marketing. Engineering thinks it's Product. Everyone thinks it's someone else.
**Method:** Map your value stream (see Part 3), measure throughput at each step, find the step with the lowest throughput or the highest queue in front of it.
**Common startup constraints by stage:**
| Stage | Most Common Constraint | Why |
|-------|----------------------|-----|
| Pre-PMF | Learning speed | Not enough customer feedback cycles |
| Series A | Sales capacity | Demand > sales team's ability to close |
| Series B | Engineering velocity | Product backlog growing faster than shipping rate |
| Series C | Onboarding throughput | New customer volume > CS team's onboarding capacity |
| Growth | Hiring throughput | Headcount plan > recruiting team's capacity |
### Applying TOC to Product Development
**The five visible constraints in product development:**
**1. Requirements clarity**
*Symptom:* Engineering asks for clarification mid-sprint. Tickets re-opened. Scope creep.
*Fix:* Never pull a story into sprint until acceptance criteria are written and reviewed. Product manager must be available same-day for clarification.
**2. Review and approval bottleneck**
*Symptom:* PRs sit unreviewed for >24 hours. Deploys waiting for sign-off.
*Fix:* Code review SLA: 2-hour response for small PRs (<100 lines), 4-hour for medium. Design reviews: 24-hour turnaround. Anyone waiting >SLA can escalate to manager.
**3. QA throughput**
*Symptom:* "Done" pile grows faster than QA can test. Release day crunch.
*Fix:* QA is pulled into sprint planning and sprint review. Testing starts as features finish, not all at end. Automated test coverage as a sprint exit criterion.
**4. Deployment pipeline speed**
*Symptom:* Deploy takes 45+ minutes. Engineers wait. Hotfix urgency causes dangerous shortcuts.
*Fix:* Measure deploy time weekly. Set target (10 min for most apps). Build optimization into engineering roadmap as a real ticket.
**5. Feedback loop latency**
*Symptom:* You ship features and don't know if they worked for weeks.
*Fix:* Every shipped feature has instrumented metrics reviewed within 5 business days. If no metrics exist, feature doesn't ship.
### Applying TOC to Sales
**The sales pipeline as a system of constraints:**
```
Lead generation → Qualification → Demo → Proposal → Negotiation → Close
[X] → [X] → [X] → [X] → [X] → [X]
Measure: conversion rate and time-in-stage at each step.
The constraint is the step with the LOWEST conversion rate × volume.
```
**Example diagnosis:**
- Lead → Qualified: 40% conversion, 2 days
- Qualified → Demo: 80% conversion, 5 days ← High conversion but slow (queue)
- Demo → Proposal: 60% conversion, 3 days
- Proposal → Close: 30% conversion, 14 days ← **Constraint** (lowest conversion)
*Diagnosis:* Proposals are being sent to wrong buyers or proposals aren't compelling. Fix: proposal template audit, champion coaching, economic buyer access earlier in process.
---
## Part 2: Lean Operations for Tech Companies
### The Lean Toolkit (What's Actually Useful)
Lean Manufacturing was designed for car factories. Most of the original toolkit doesn't apply to software. Here's what does:
**Value Stream Mapping** — Map the full flow of work from customer request to delivery. Label value-add time vs. wait time. Most processes are 90% wait time and 10% actual work.
**5S** — Sort, Set in order, Shine, Standardize, Sustain. Applied to digital work:
- *Sort:* Delete unused tools, channels, documents
- *Set in order:* Organize information architecture so things are findable
- *Shine:* Regular cleanup sprints (documentation, tech debt, tool hygiene)
- *Standardize:* Templates, conventions, naming standards
- *Sustain:* Assign owners; entropy is the default state
**Pull vs. Push** — Don't push work onto people's plates. Pull = people take work when they have capacity. Push = work is assigned to people regardless of capacity. Most companies push; lean companies pull.
**Kaizen** — Continuous small improvements. Build this into your operating rhythm:
- Weekly: each team identifies one small improvement to their process
- Monthly: review and close out improvement items
- Quarterly: broader process retrospective
**Waste Categories (TIMWOODS) — Applied to Operations:**
| Waste Type | Factory Example | Startup Example |
|-----------|----------------|-----------------|
| **T**ransportation | Moving parts | Handing off work between tools with no integration |
| **I**nventory | Parts stockpile | Unreviewed PRs, unworked backlog items, unread reports |
| **M**otion | Worker movement | Context switching between apps / communication channels |
| **W**aiting | Machine idle | Waiting for approvals, waiting for data, waiting for decisions |
| **O**verproduction | Making more than needed | Features built that weren't validated |
| **O**verprocessing | Extra steps | 6-step approval for $200 purchase |
| **D**efects | Rework | Bug fixes, incorrect specs, miscommunicated requirements |
| **S**kills | Underutilized talent | Senior engineers doing manual QA |
**Exercise:** For your most important process, walk through each waste category and estimate hours/week wasted. This exercise typically reveals 20–40% improvement opportunities in the first pass.
### Cycle Time and Lead Time
**Lead time:** Time from when a request enters the system to when it exits (customer perspective).
**Cycle time:** Time a unit of work is actively being worked on (team perspective).
```
Lead Time = Cycle Time + Wait Time
```
Most teams only measure cycle time. Customers only experience lead time. The gap between the two is pure waste.
**Measuring in your context:**
- Engineering: Lead time = ticket created → in production. Cycle time = in progress → PR merged.
- Sales: Lead time = lead created → closed won. Cycle time = demo completed → proposal sent.
- CS: Lead time = ticket opened → customer confirms resolved. Cycle time = ticket in-progress → resolution sent.
**Improvement pattern:**
1. Measure lead time (not just cycle time)
2. Find the steps where tickets sit waiting
3. Remove the wait (automation, reduced approval layers, clearer handoff criteria)
### WIP Limits
Work-In-Progress limits prevent the multi-tasking trap. When people work on 5 things simultaneously, each thing takes 5x longer and quality drops.
**Recommended WIP limits:**
- Individual IC: 2–3 active items at once
- Team sprint: WIP = number of engineers × 1.5
- Leadership team: No more than 3 company-level priorities per quarter
**Implementation:** In Jira/Linear, add a WIP column. Set a hard limit. When the column is full, no new work starts until something ships.
---
## Part 3: Process Mapping Techniques
### When to Map a Process
Map a process when:
- It's done by more than 2 people
- It fails regularly (errors, rework, complaints)
- It needs to scale (you're about to add people or volume)
- You're automating it (you must understand the manual process first)
- You're onboarding someone new to it
Don't map processes that are genuinely ad-hoc, one-person, or will change significantly in the next 90 days.
### The Three Levels of Process Maps
**Level 1: Swim Lane Map (for cross-functional processes)**
Best for: Customer onboarding, sales-to-CS handoff, escalation handling, hiring
```
Example: Sales to CS Handoff
| Sales AE | Sales Ops | CS Manager | CS Rep |
--------|---------------|---------------|---------------|---------------|
Step 1 | Close deal | | | |
Step 2 | Fill handoff | | | |
| doc | | | |
Step 3 | | Route to CS | | |
Step 4 | | | Review & | |
| | | assign | |
Step 5 | | | | Send welcome |
Step 6 | | | | Schedule kick-|
| | | | off |
```
**Level 2: Flowchart (for decision-heavy processes)**
Best for: Escalation routing, incident response, approval workflows
Use standard symbols:
- Rectangle = action/task
- Diamond = decision (yes/no branch)
- Oval = start/end
- Parallelogram = input/output
**Level 3: Work Instructions (for execution-level processes)**
Best for: Checklists, SOPs, how-to guides
Format:
```
Process: [Name]
Owner: [Role]
Last reviewed: [Date]
Trigger: [What starts this process]
Step 1: [Action] — [Who does it] — [Tool used] — [Expected output]
Step 2: ...
Exceptions:
- If [condition], then [alternative action]
Done when: [Definition of done]
```
### Process Audit Technique
Run this quarterly on your most critical processes:
**1. Walk the process** — Literally follow a unit of work from start to finish. Ask the people doing it, not the people managing it.
**2. Measure three numbers:**
- How long does it actually take? (lead time)
- How often does it go wrong? (error/rework rate)
- What's the cost of a failure? (downstream impact)
**3. Score it:**
```
PROCESS HEALTH SCORE:
Lead time vs. target: [+2 on target / 0 delayed / -2 significantly delayed]
Error rate: [+2 <5% / 0 5-15% / -2 >15%]
Documented: [+1 yes / -1 no]
Owner named: [+1 yes / -1 no]
Last reviewed (< 6 months): [+1 yes / -1 no]
Max: 7. Score <3 = needs immediate attention.
```
---
## Part 4: Automation Decision Framework
### The "Should I Automate This?" Test
Not everything should be automated. Bad automation of a broken process = faster broken process.
**The five-question filter:**
1. **Is the process stable?** If it changes monthly, automate later. Automating unstable processes locks in the wrong behavior.
2. **How often does it happen?** Weekly or more frequent = good candidate. Monthly or less = probably not worth it.
3. **What's the error rate without automation?** If the manual process is accurate 95%+ of the time, automation ROI is lower.
4. **What's the cost of failure?** Customer-facing, compliance, or financial processes deserve higher automation priority than internal reporting.
5. **Is the process well-documented?** If you can't describe it in a flowchart, you can't automate it. Document first.
### Automation ROI Calculation
```
Annual hours saved = (minutes per occurrence / 60) × occurrences per year
Annual labor cost saved = hours saved × fully-loaded cost per hour
Net annual value = labor cost saved + error reduction value + speed improvement value
Build/buy cost = development time + maintenance overhead
Payback period = build/buy cost ÷ net annual value
Rule of thumb: automate if payback period < 12 months
```
**Example:**
- Process: Weekly sales report compilation
- Time: 3 hours/week manually
- Fully-loaded cost: $75/hour
- Annual manual cost: 3 × 52 × $75 = $11,700
- Automation cost: 40 hours to build = $3,000
- Payback: 3,000 ÷ 11,700 = 3 months → **Automate**
### Automation Tiers
**Tier 1: No-code automation** (0–8 hours to implement)
- Tools: Zapier, Make (Integromat), n8n, HubSpot workflows
- Use for: Notification triggers, data syncs between tools, simple conditional routing
- Example: New customer in CRM → create CS ticket → send welcome Slack message
**Tier 2: Low-code automation** (8–40 hours to implement)
- Tools: Retool, internal scripts, Google Apps Script, Airtable Automations
- Use for: Internal dashboards, data transformation, approval workflows
- Example: Weekly metrics compilation from Salesforce + Mixpanel + HubSpot into Notion dashboard
**Tier 3: Engineered automation** (40+ hours to implement)
- Built by engineering team as product/infrastructure work
- Use for: Customer-facing workflows, compliance-critical processes, high-volume operations
- Example: Automated customer health score calculation → CS alert → playbook trigger
### Automation Prioritization Matrix
```
HIGH FREQUENCY
|
Tier 1 now | Tier 2-3 now
(quick win) | (high-value)
|
LOW VALUE ________________|________________ HIGH VALUE
|
Don't bother | Plan for later
| (when it's bigger)
|
LOW FREQUENCY
```
Place each manual process in the quadrant. Execute top-right first, Tier 1 items second.
### Automation Governance
As automation grows, it needs governance:
**Automation registry:** Maintain a list of all automations with:
- Name and description
- Owner (person responsible if it breaks)
- Tools used
- Trigger and action
- Last tested date
- Business impact if down
**Review cadence:** Quarterly review of automation registry. Kill automations nobody uses.
**Failure alerting:** Every production automation must have failure notifications sent to a named owner. Silent failures are worse than no automation.
---
## Part 5: Change Management for Process Rollouts
### Why Process Changes Fail
Most process changes fail not because the process is wrong, but because of how it's rolled out. Common failure modes:
- **Top-down dictate:** Process designed by leadership, announced to team, implemented poorly because people weren't involved and don't understand why.
- **No training:** "Here's the new process" with no demonstration or practice.
- **No feedback loop:** Process is rolled out and never adjusted based on what the team discovers.
- **No accountability:** Process is optional in practice because there are no consequences for ignoring it.
- **Old behavior still possible:** You introduce a new tool but don't turn off the old way.
### The Change Management Framework (ADKAR)
ADKAR (Awareness, Desire, Knowledge, Ability, Reinforcement) is the most practical model for operational change.
**A — Awareness:** Does everyone understand WHY the change is needed?
- Don't just announce the new process — explain what was broken about the old one
- Share the data: "Our current onboarding takes 45 days, customers who onboard faster have 2x better retention. The new process targets 21 days."
**D — Desire:** Do people want to change?
- Resistance is information. Listen to it.
- Involve front-line workers in process design. People support what they help build.
- Address WIIFM (What's In It For Me) for each affected group
**K — Knowledge:** Do people know HOW to do the new process?
- Write it down (work instructions format above)
- Run live demos and practice sessions
- Create a "first time" checklist
**A — Ability:** Can people actually do the new process?
- Identify where people get stuck (first 2 weeks of rollout)
- Have a designated expert for questions
- Remove friction: if the new process requires 3 clicks where the old required 1, people will revert
**R — Reinforcement:** Does the change stick?
- Measure adoption (are people actually using the new process?)
- Celebrate early adopters
- Address non-adoption promptly — call it out without shame
### Change Rollout Checklist
```
PRE-LAUNCH:
□ Process designed and documented
□ Stakeholders identified (people affected by change)
□ Champions identified (people who will help adoption)
□ Training materials created
□ Success metrics defined (how will you know it worked?)
□ Rollback plan documented (what if it breaks something?)
□ Launch timeline set and communicated
LAUNCH WEEK:
□ Announcement sent with WHY, WHAT, and WHEN
□ Training sessions held (at least 2 options for different schedules)
□ Feedback channel opened (Slack thread, form, or dedicated meeting)
□ Champions briefed to support peers
2-WEEK CHECK:
□ Adoption rate measured
□ Friction points documented
□ Quick fixes implemented
□ Feedback reviewed and responded to
30-DAY REVIEW:
□ Success metrics reviewed vs. baseline
□ Process adjustments made based on learnings
□ Champions recognized
□ Process documentation updated with lessons learned
90-DAY CLOSE:
□ Full adoption confirmed or non-adoption addressed
□ Process owners confirmed
□ Handoff to BAU (business as usual) operations
```
### Managing Resistance
**Types of resistance and responses:**
| Resistance Type | What It Sounds Like | Right Response |
|----------------|---------------------|----------------|
| Legitimate concern | "This process won't work because X happens" | Acknowledge, investigate, fix or explain |
| Anxiety | "I don't know how to do this" | Training, support, reassurance |
| Loss of control | "This takes away my judgment" | Involve them in design; give them ownership of part of it |
| Passive non-compliance | Silent ignoring of the new process | Direct conversation; make it visible and required |
| Organizational inertia | "We've always done it this way" | Show the cost of the status quo in concrete terms |
**The three levers of adoption:**
1. **Make the new way easier than the old way** (remove the old path if possible)
2. **Make non-adoption visible** (dashboards showing who's using the process)
3. **Connect process to meaningful outcomes** (show how it affects things people care about)
### Process Documentation Standards
Every process should have exactly one owner responsible for keeping it current.
**Minimum documentation for any process:**
- **Process name** and one-sentence purpose
- **Owner:** Named individual, not a team
- **Trigger:** What starts this process
- **Steps:** Written at the level that a new employee could execute
- **Exceptions:** Common edge cases and how to handle them
- **Done definition:** How you know the process is complete
- **Review date:** Set a future date when this gets reviewed
**Documentation debt kills scale.** The most valuable time to document is right after you've run the process for the third time — you've found the edge cases, you know the real steps, and the process is still fresh.
---
## Framework Selection Guide
| Situation | Framework |
|-----------|-----------|
| We're slow and can't figure out why | Theory of Constraints — find the bottleneck |
| We have lots of waste and overhead | Lean — waste audit (TIMWOODS) |
| Process is inconsistent across team | Process mapping — Level 1 swim lane |
| Deciding what to automate | Automation decision framework + ROI calc |
| New process keeps getting ignored | ADKAR change management |
| Unclear who's responsible | RACI or DRI framework |
| Too many decisions escalating to leadership | RAPID decision rights |
---
*Frameworks synthesized from: Eliyahu Goldratt's The Goal and Critical Chain; Womack and Jones' Lean Thinking; Prosci ADKAR model; Scaled Agile Framework (SAFe) process guidance; operational playbooks from Stripe, Airbnb, and Shopify operations teams.*
FILE:references/scaling_playbook.md
# Scaling Playbook: What Breaks at Each Growth Stage
> Compiled from patterns across 100+ high-growth companies. Not theory — this is what actually breaks and what to do about it.
---
## How to Use This Playbook
Each stage section covers:
1. **What breaks** — the specific failure modes that kill companies at this stage
2. **Hiring** — who to bring in and when
3. **Process** — what to formalize vs. keep loose
4. **Tools** — infrastructure that unlocks the next stage
5. **Communication** — how information flow changes
6. **Culture** — what to protect and what to let go
**Benchmarks are medians** — your mileage varies by sector, geography, and business model.
---
## Stage 0: Pre-Seed / Seed ($0–$2M ARR, 1–15 people)
### Key Benchmarks
| Metric | Benchmark |
|--------|-----------|
| Revenue per employee | $0–$100K (still finding PMF) |
| Manager:IC ratio | N/A (no managers) |
| Burn multiple | 2–5x (acceptable) |
| Runway | 12–18 months minimum |
| Time-to-hire | 2–4 weeks |
### What Breaks
**Premature process.** The #1 mistake at seed stage is adding process before you have a repeatable model. Sprint ceremonies, OKR frameworks, and performance reviews are all theater when you haven't found PMF. Every hour spent in process is an hour not spent learning.
**Wrong first hires.** Hiring "senior" people who've only worked in structured environments. You need people who can operate in chaos, not people who expect process to already exist.
**Founder communication bottleneck.** Founders try to be in every decision. Fine at 5 people, fatal at 12. No written decisions means knowledge lives in founders' heads — unscalable.
**Technical debt accepted as strategy.** "We'll fix it later" said about core data models, auth systems, or billing. Later comes at Series A and it costs 3x more to fix.
### Hiring
- **Don't hire for scale you don't have.** Hire for the next 12 months.
- **First 10 hires set culture permanently.** Get them wrong and you'll spend years correcting.
- **Hire athletes, not specialists.** Generalists who can do multiple jobs outperform specialists at this stage.
- **Avoid VP titles early.** Inflated titles block future hires and create expectations you can't meet.
- **Founder-referral bias is real.** Your network is homogeneous. Force diversity early.
**Who to hire first (in rough order):**
1. Engineers who can ship product (2–3 generalists)
2. First sales/GTM if B2B (founder-led sales first, then one closer)
3. Designer/product (often a hybrid)
4. Customer success (often a founder at first)
### Process
**Formalize nothing before PMF.** Literally. Run on Slack, shared docs, and founder judgment.
**After PMF signals appear, formalize only:**
- How you handle customer escalations
- How you deploy code (even basic CI/CD)
- How you onboard new hires (a 1-page checklist is enough)
**Decision rule:** If a founder has to answer the same question three times, write it down. Once.
### Tools
| Function | Seed-Stage Tool |
|----------|----------------|
| Communication | Slack + Google Workspace |
| Project tracking | Linear or Notion (pick one, stay consistent) |
| CRM | HubSpot free or Notion |
| Engineering | GitHub + basic CI (GitHub Actions) |
| Finance | Brex/Mercury + QuickBooks |
| HR | Rippling or Gusto (basic) |
| Analytics | Mixpanel or PostHog (free tier) |
**Rule:** One tool per function. No tool sprawl. Every extra tool is a coordination tax.
### Communication
- **Weekly all-hands** (30 min max). What shipped, what's stuck, what's next.
- **No status meetings.** Anyone can see status in Linear/Notion.
- **Founder write-ups.** Every major decision gets a 1-paragraph Slack post explaining *why*.
- **Group chat discipline.** One channel per project/customer. Inbox zero mentality.
### Culture
**What to build deliberately:**
- High ownership: everyone acts like they own the company, because they do
- Direct feedback: brutal honesty delivered with care
- Bias to ship: done > perfect
- Customer obsession: founders talk to customers weekly
**What to watch for:**
- "Hero culture" where one person saves everything — unsustainable
- Over-indexing on culture fit (code for homogeneity)
- Avoidance of conflict — mistaking silence for agreement
---
## Stage 1: Series A ($2–$10M ARR, 15–50 people)
### Key Benchmarks
| Metric | Benchmark |
|--------|-----------|
| Revenue per employee | $100–$200K |
| Manager:IC ratio | 1:6–1:8 |
| Burn multiple | 1.5–2.5x |
| Sales efficiency (CAC payback) | <18 months |
| Churn (B2B SaaS) | <10% net annual |
| Engineering velocity | Feature shipped every 1–2 weeks |
| Time-to-hire | 4–6 weeks |
| Offer acceptance rate | >80% |
### What Breaks
**Founder-as-manager bottleneck.** At 20+ people, founders can't manage everyone. The first layer of management needs to appear — and it's usually picked wrong (best IC ≠ best manager).
**Tribal knowledge explosion.** "Ask Sarah" stops working when Sarah has 15 things open. Documentation becomes critical — not for bureaucracy, but because institutional knowledge is now a flight risk.
**Sales process fragmentation.** Without a defined sales process, every rep closes differently. You can't train, debug, or scale what you can't see.
**Scope creep in product.** With Series A money comes investor pressure to expand scope. Teams try to build three things at once and ship nothing well.
**Compensation chaos.** Early employees got equity-heavy deals. New hires get market cash. Someone compares, someone gets upset. No comp philosophy = constant re-negotiation.
**Recruiting becomes a job in itself.** Founders can't hire 30 people themselves. First dedicated recruiter needed by 25 people.
### Hiring
**Who to hire at Series A:**
- **Head of Engineering** (if founder is CTO): needs to be an operator, not just an architect
- **First Sales Manager** (when you have 3+ reps): don't promote the best seller
- **HR/People Ops** (generalist, by 30 people): comp, compliance, recruiting coordination
- **Finance** (fractional CFO or strong controller): Series A board needs real numbers
- **Customer Success Lead**: retention is everything at this stage
**Hiring mistakes to avoid:**
- Hiring "big company" execs who need large teams and established process
- Assuming your Series A lead can recruit (they can intro, not close)
- Taking too long — top candidates have 2–3 offers. Move in <2 weeks from first call to offer.
**Leveling:** Build a simple career ladder *before* the compensation complaints start. 3–4 levels per function is enough.
### Process
**What to formalize at Series A:**
1. **Sprint planning** (2-week sprints, public roadmap)
2. **Sales process** (defined stages with entry/exit criteria)
3. **Onboarding** (30/60/90 day plan for each function)
4. **1:1 cadence** (weekly for direct reports, bi-weekly for skip-levels)
5. **Incident response** (P0/P1/P2 definition, on-call rotation)
6. **Quarterly planning** (OKRs or goals framework — keep it lightweight)
**What to keep loose:**
- Internal project process (let teams self-organize)
- Meeting formats (let teams evolve their own rituals)
- Tool selection within approved stack
**Documentation standard:** Write decisions down in a shared wiki. "Decision log" with date, decision, context, owner, and outcome. Takes 5 minutes, saves hours.
### Tools
| Function | Series A Tool |
|----------|--------------|
| Project/Product | Linear + Notion |
| CRM | HubSpot or Salesforce (Starter) |
| Engineering | GitHub + CI/CD pipeline + Sentry |
| HR/People | Rippling or Lattice (performance) |
| Finance | NetSuite or QBO + Brex |
| Analytics | Mixpanel/Amplitude + Looker (or Metabase) |
| Customer Success | Intercom + HubSpot or Zendesk |
| Docs | Notion or Confluence |
### Communication
**Introduce structured communication layers:**
1. **Company all-hands** (monthly, 60 min): CEO share, metrics review, team spotlights, Q&A
2. **Leadership sync** (weekly, 60 min): cross-functional issues, blockers, priorities
3. **Team standups** (async or 15 min daily): what's in progress, what's blocked
4. **1:1s** (weekly): direct report health, career, performance
5. **Written updates** (weekly to investors + board): CEO memo format
**Information hierarchy:** Everyone in the company should know: (1) company goals this quarter, (2) their team's goals, (3) what they personally own. If they don't, your communication structure is broken.
### Culture
**Deliberate culture work starts here.** You're too big for culture to be accidental.
- **Write down values.** Real values with examples of what they look like in action. Not "integrity" — "we tell investors bad news before we tell them good news."
- **Performance management.** First PIPs (Performance Improvement Plans) happen at this stage. Handle them well — the team is watching.
- **Equity culture.** Make sure people understand what their equity is worth in different outcomes. Lack of transparency breeds resentment.
- **First layoff plan.** Even if you never use it, know the criteria. Reactive layoffs destroy trust; plan-based ones (even painful) preserve it.
---
## Stage 2: Series B ($10–$30M ARR, 50–150 people)
### Key Benchmarks
| Metric | Benchmark |
|--------|-----------|
| Revenue per employee | $150–$300K |
| Manager:IC ratio | 1:5–1:7 |
| Burn multiple | 1.0–1.5x |
| CAC payback | <12 months |
| NRR (net revenue retention) | >110% |
| Engineering: Product ratio | ~3:1 |
| Sales: CS ratio | ~3:1 |
| Time-to-hire (senior) | 6–10 weeks |
| Annual attrition | <15% voluntary |
### What Breaks
**Middle management void.** You now have managers managing managers. The "player-coach" model breaks — people can't be ICs and managers simultaneously at this scale. Force the choice.
**Planning misalignment.** Sales promises what product hasn't built. Product builds what customers didn't ask for. Engineering ships what QA didn't test. Fixing this requires cross-functional planning ceremonies.
**Data fragmentation.** Five different versions of "how are we doing." Sales sees Salesforce. Product sees Amplitude. Finance sees spreadsheets. Nobody agrees. You need a single source of truth.
**Process debt.** The Series A processes are starting to creak. Onboarding that worked for 5 hires/quarter doesn't work for 20. Customer escalation paths built for 50 customers fail at 500.
**Cultural fragmentation.** Engineering culture ≠ Sales culture ≠ Support culture. Sub-cultures form. The shared identity you had at 30 people requires active work to maintain at 100.
**The "brilliant jerk" problem.** High performers with bad behavior were tolerated early. Now they're managers with bad behavior, and it's systemic. Act decisively or lose your best people.
### Hiring
**Who to hire at Series B:**
- **COO or VP Operations**: founder is overwhelmed, someone needs to run the machine
- **VP Sales**: first Sales Manager won't scale to 20-rep org
- **VP Marketing**: demand gen and brand need dedicated ownership
- **Dedicated Recruiting**: 2–3 recruiters minimum; you're hiring 30–50 people/year
- **Data/Analytics**: dedicated analyst or data engineer to consolidate reporting
- **Legal counsel**: fractional or in-house; contracts and compliance are getting complex
**The "big company exec" trap.** Series B is when companies hire their first VP from FAANG or a large SaaS company. 60% of these fail within 18 months. They're used to: large teams, established brand, existing process, political navigation. They struggle with: scrappy execution, no support staff, ambiguous direction. Vet explicitly for startup experience.
**Span of control.** At this stage, hold managers to 5–8 direct reports. More than 8 = no time for actual management. Less than 3 = management overhead isn't justified.
### Process
**What to formalize at Series B:**
1. **Quarterly Business Reviews (QBRs)** — every function presents metrics, wins, gaps
2. **Annual planning** — budget, headcount plan, strategic priorities
3. **Cross-functional roadmap alignment** — product/sales/marketing in sync quarterly
4. **Promotion criteria** — written, public, applied consistently
5. **Interview scorecards** — structured interviews with defined rubrics
6. **Change management** — how major process changes get communicated and adopted
7. **Vendor management** — evaluation criteria, approval process, contract management
**SOPs for critical processes:**
- Customer onboarding (if >50 customers)
- Sales handoff from SDR to AE to CS
- Engineering release process
- Incident response playbook
- Contractor/vendor procurement
### Tools
| Function | Series B Tool |
|----------|--------------|
| Project/Product | Jira or Linear (with roadmapping) |
| CRM | Salesforce (full) |
| ERP/Finance | NetSuite |
| HR | Workday or BambooHR + Lattice |
| Analytics | Looker or Tableau + data warehouse |
| Customer Success | Gainsight or ChurnZero |
| Engineering | GitHub Enterprise + full CI/CD + observability |
| Security | 1Password Teams + SSO (Okta) + endpoint management |
### Communication
**At 50+ people, informal communication breaks down.** Information no longer flows naturally — it has to be architected.
**Communication stack:**
- **Monthly all-hands** (90 min): metrics deep-dive, strategy update, team Q&A
- **Weekly leadership team** (90 min): cross-functional priorities, decisions, escalations
- **Bi-weekly skip-levels** (30 min): every manager holds these with their manager's reports
- **Quarterly town halls** (2 hrs): broader context, financial update, roadmap preview
- **Written company update** (bi-weekly): CEO to all-hands via Slack/email
**The information gradient problem.** People at the top know too much. People at the bottom know too little. Fix this with a deliberate "broadcast" culture — any decision affecting more than 5 people gets written up and shared.
### Culture
**Retention becomes an existential issue.** At Series B, you have 50–150 people who've been with you through something hard. They're valuable. And they have options.
- **Career ladders** are non-negotiable by this stage. People leave when they can't see a future.
- **Manager quality** determines retention. Invest in manager training. Run manager effectiveness surveys.
- **Compensation benchmarking** quarterly. If you're more than 10% below market, you're losing people silently.
- **Culture carriers.** Identify the 10–15 people who embody your culture and make them formally responsible for transmitting it. Give them a platform.
---
## Stage 3: Series C ($30–$75M ARR, 150–500 people)
### Key Benchmarks
| Metric | Benchmark |
|--------|-----------|
| Revenue per employee | $200–$400K |
| Manager:IC ratio | 1:5–1:6 |
| Burn multiple | 0.75–1.25x |
| NRR | >115% |
| CAC payback | <9 months |
| Sales cycle (Enterprise) | 60–120 days |
| Engineering team % | 30–40% of headcount |
| Annual attrition target | <12% voluntary |
| Time-to-hire (senior) | 8–12 weeks |
### What Breaks
**Strategy execution gap.** Leadership agrees on strategy. Middle management interprets it differently. ICs execute on their interpretation. By the time work ships, it barely resembles the original strategy. Fix: strategy must cascade in writing with explicit outcomes.
**Process bureaucracy.** The processes you built at Series B start generating bureaucracy. Approval chains lengthen. Simple decisions require three meetings. The antidote is explicit process owners empowered to eliminate friction.
**Org design complexity.** Do you have functional teams (all engineers in one org) or product teams (engineers embedded in product squads)? The answer affects everything: career paths, knowledge sharing, delivery speed. Most companies get this wrong twice before getting it right.
**Geographic complexity.** First international office or remote-heavy team introduces timezone, communication, and culture challenges that don't exist when everyone is in one room.
**Leadership team dysfunction.** Seven VPs who were all individual contributors two years ago are now running $10M+ organizations. Some have grown into it. Some haven't. This is the stage where hard leadership team changes happen.
### Hiring
**Series C hiring is about depth, not breadth.** You have functional coverage — now hire people who go deep within functions.
- **Functional leaders' deputies**: VP Engineering needs a Director of Platform Engineering, Director of Product Engineering, etc.
- **Internal promotions**: 40–60% of leadership roles should be filled internally by now. If you're hiring externally for everything, you've failed at development.
- **Specialists**: Security, data science, UX research, RevOps — functions that were "shared" become dedicated.
- **General Counsel**: Legal volume justifies full-time counsel.
**Headcount planning discipline.** Every hire should have a business case. "The team is busy" is not a business case. "This role will unlock $X in revenue or save Y hours/week" is a business case.
### Process
**Process consolidation.** Audit every process. Kill anything that doesn't have a clear owner and clear outcome. The average Series C company has 40% more process than it needs.
**Key processes to have locked at Series C:**
1. **Annual planning cycle** (strategy → goals → headcount → budget)
2. **Quarterly operating review** (progress against plan, forecast, adjustments)
3. **Product development lifecycle** (discovery → design → build → launch → measure)
4. **Revenue operations** (forecasting, pipeline management, territory planning)
5. **People operations** (performance cycles, promotion cadence, compensation philosophy)
6. **Risk management** (operational, security, compliance, legal)
**Delegation architecture.** At 200+ people, the COO cannot know about every decision. Build explicit decision rights: what decisions require CEO/COO approval vs. VP vs. Director vs. IC.
### Tools
**Consolidate the tech stack.** By Series C, you have tool sprawl. The average 200-person company has 100+ SaaS tools. 40% are redundant. Consolidation saves $200–500K/year and reduces security surface.
**Must-have by Series C:**
- Enterprise SSO (Okta/Google Workspace with MFA everywhere)
- Data warehouse (Snowflake/BigQuery) + BI layer
- HRIS with performance management (Workday, Rippling, BambooHR)
- Revenue intelligence (Gong, Chorus)
- Security tooling (endpoint, SIEM basics, SOC 2 compliance)
### Communication
**Internal comms becomes a function.** You cannot rely on ad-hoc Slack and email at 200+ people. Someone needs to own internal communications.
- **Monthly CEO update** (written, 500 words max): company performance, strategic context, what's next
- **Quarterly all-hands** (2 hrs): comprehensive business review, open Q&A
- **Leadership alignment sessions** (quarterly): leadership team off-site to calibrate on strategy
- **Manager cascade** (after every major announcement): managers brief their teams with tailored context
### Culture
**Culture is now a function, not an instinct.** By Series C, your original culture-carriers are managers or have left. New people joining have never seen how you worked when you were small.
- **Culture explicitly documented** — not a values poster, a behavioral handbook
- **Onboarding redesigned** for culture transmission at scale
- **Manager enablement** — managers are your primary culture delivery mechanism; invest heavily
- **Listening infrastructure** — eNPS quarterly, exit interviews, skip-level feedback — all analyzed systematically
---
## Stage 4: Growth Stage ($75M+ ARR, 500+ people)
### Key Benchmarks
| Metric | Benchmark |
|--------|-----------|
| Revenue per employee | $300–$600K |
| Manager:IC ratio | 1:4–1:6 |
| Burn multiple (path to profitability) | <0.5x |
| NRR | >120% |
| S&M as % of revenue | 25–35% |
| R&D as % of revenue | 15–25% |
| G&A as % of revenue | 8–12% |
| Rule of 40 | >40 (growth rate + profit margin) |
| Annual attrition target | <10% voluntary |
### What Breaks
**Execution at scale.** The larger you are, the harder it is to move fast. The average decision at a 500-person company takes 3x longer than at a 50-person company. This is not inevitable — but fixing it requires explicit investment.
**Internal politics.** Org boundaries create fiefdoms. VPs protect headcount. Teams optimize for their metrics at the expense of company metrics. This is the #1 culture problem at scale.
**Innovation starvation.** The core business is optimized, but new bets are starved of resources. The people working on new initiatives are constrained by processes designed for a mature product. Structural solution required: separate P&L, separate team, different metrics.
**Middle management bloat.** Growth-stage companies often have too many managers and not enough ICs. A manager managing one other manager managing three ICs is a 3-level chain where 2 people add no value. Flatten aggressively.
### Hiring
**You're now competing for talent with FAANG.** Your advantage is mission, equity, and the ability to have impact. Candidates who want to join a Fortune 500 will not join you. Stop trying to attract them.
- **Leadership pipeline**: promote from within at 50%+ for senior roles
- **Talent density over headcount**: 30 strong engineers > 50 average engineers
- **Diverse hiring**: by this stage, lack of diversity is a business problem, not just an ethical one
### Operational Priorities at Scale
1. **Operational efficiency over growth**: headcount growth should lag revenue growth
2. **Process ownership**: every major process has a named owner accountable for outcomes
3. **Quarterly operating model**: budget vs. actual, full P&L transparency to VP level
4. **Automation**: manual operational processes that cost >40 hrs/week should be automated
---
## Cross-Stage Principles
### The Three Things That Kill Companies at Every Stage
1. **Running out of cash before finding the next unlock** — runway management is sacred
2. **Hiring the wrong person for a critical role** — one bad VP can set you back 18 months
3. **Moving too slowly** — market timing matters; perfect is the enemy of shipped
### The Org Design Progression
```
Seed: Flat | Everyone reports to founder | No structure
Series A: Functional pods | First-line managers | Light structure
Series B: Functional departments | VPs emerge | Defined structure
Series C: Business units or product squads | Directors + VPs | Full structure
Growth: Divisional or matrix | EVPs/SVPs | Corporate structure
```
### Revenue per Employee by Function (B2B SaaS benchmarks)
| Function | Series A | Series B | Series C | Growth |
|----------|----------|----------|----------|--------|
| Engineering | $400K | $500K | $600K | $700K |
| Sales | $250K | $350K | $450K | $500K |
| Customer Success | $300K | $400K | $500K | $600K |
| Marketing | $500K | $700K | $900K | $1M+ |
| G&A | $600K | $800K | $1M | $1.2M |
*Revenue per employee = ARR / headcount in function*
### The Management Span Rule
- **Individual contributors being managed**: 1 manager per 6–8 ICs
- **Managers being managed**: 1 director per 4–6 managers
- **Directors being managed**: 1 VP per 3–5 directors
- **VPs being managed**: 1 C-level per 5–8 VPs
Violation of this creates either manager burnout (too wide) or management theater (too narrow).
---
## Red Flags by Stage
| Stage | Red Flag | Likely Cause |
|-------|----------|-------------|
| Seed | Missed 3+ product deadlines | Wrong team or unclear prioritization |
| Series A | Churn >20% | PMF not actually found, or CS underfunded |
| Series B | >6-month sales cycle on SMB | Pricing/packaging problem |
| Series C | NRR <100% | Product-market fit eroding or CS broken |
| Growth | Rule of 40 <20 | Efficiency problem; hiring ahead of revenue |
---
*Sources: Sequoia, a16z operating frameworks; First Round Capital COO benchmarks; SaaStr metrics databases; OpenView SaaS benchmarks; Bain operational maturity models.*
FILE:scripts/okr_tracker.py
#!/usr/bin/env python3
"""
okr_tracker.py — OKR Cascade and Alignment Tracker
Tracks OKR progress from company → department → team level.
Calculates scores, flags at-risk key results, and generates alignment reports.
Scoring: Google's 0.0–1.0 scale (target: 0.6–0.7; hitting 1.0 means goal was too easy)
Usage:
python okr_tracker.py # Runs with sample data
python okr_tracker.py --input okrs.json # Custom OKR data
python okr_tracker.py --input okrs.json --output report.txt
python okr_tracker.py --format json # Machine-readable output
"""
import json
import sys
import argparse
from datetime import datetime, date
from typing import Any
# ---------------------------------------------------------------------------
# Scoring Engine
# ---------------------------------------------------------------------------
# OKR health thresholds (Google-style 0.0–1.0 scale)
SCORE_THRESHOLDS = {
"on_track": 0.70, # Above this: healthy
"at_risk": 0.40, # Between at_risk and on_track: needs attention
# Below at_risk: off track
}
STATUS_LABELS = {
"on_track": "🟢 On Track",
"at_risk": "🟡 At Risk",
"off_track": "🔴 Off Track",
"complete": "✅ Complete",
"not_started": "⬜ Not Started",
}
RISK_LABELS = {
"critical": "🔴 Critical",
"high": "🟠 High",
"medium": "🟡 Medium",
"low": "🟢 Low",
}
def calculate_kr_score(kr: dict) -> float:
"""
Calculate a Key Result's progress score (0.0–1.0).
Supports multiple KR types:
- numeric: current_value / target_value
- percentage: current_pct / target_pct
- milestone: milestone_score (0.0–1.0 provided directly)
- boolean: done (1.0) / not done (0.0)
"""
kr_type = kr.get("type", "numeric")
if kr_type == "boolean":
return 1.0 if kr.get("done", False) else 0.0
elif kr_type == "milestone":
# Milestone KRs have explicit score (0.0–1.0) or count of milestones hit
milestones_total = kr.get("milestones_total", 1)
milestones_hit = kr.get("milestones_hit", 0)
explicit_score = kr.get("score")
if explicit_score is not None:
return max(0.0, min(1.0, float(explicit_score)))
return milestones_hit / milestones_total if milestones_total > 0 else 0.0
elif kr_type == "percentage":
target = kr.get("target_pct", 100)
current = kr.get("current_pct", 0)
baseline = kr.get("baseline_pct", 0)
if target == baseline:
return 0.0
score = (current - baseline) / (target - baseline)
return max(0.0, min(1.0, score))
else: # numeric (default)
target = kr.get("target_value", 0)
current = kr.get("current_value", 0)
baseline = kr.get("baseline_value", 0)
if target == baseline:
return 0.0
# Handle "lower is better" metrics (e.g., churn, response time)
if kr.get("lower_is_better", False):
if current <= target:
return 1.0
improvement = baseline - current
needed = baseline - target
score = improvement / needed if needed != 0 else 0.0
else:
score = (current - baseline) / (target - baseline)
return max(0.0, min(1.0, score))
def get_kr_status(score: float, quarter_progress: float, kr: dict) -> str:
"""
Determine KR status based on score, time elapsed in quarter, and trend.
A KR is at-risk if its score is significantly behind the time elapsed.
E.g., if we're 70% through the quarter but KR is at 30%, it's at risk.
"""
if kr.get("done", False):
return "complete"
# Not started
if score == 0.0 and quarter_progress < 0.1:
return "not_started"
# Check against absolute thresholds
if score >= SCORE_THRESHOLDS["on_track"]:
return "on_track"
# Adjust for time: if we're early in quarter, lower scores are acceptable
adjusted_threshold = SCORE_THRESHOLDS["at_risk"] * (quarter_progress or 0.5)
if score >= max(adjusted_threshold, SCORE_THRESHOLDS["at_risk"]):
return "at_risk"
return "off_track"
def calculate_objective_score(objective: dict, quarter_progress: float) -> dict:
"""
Score an objective based on its key results.
Returns scored objective with KR scores and status.
"""
key_results = objective.get("key_results", [])
if not key_results:
return {**objective, "score": 0.0, "status": "not_started", "key_results_scored": []}
scored_krs = []
for kr in key_results:
score = calculate_kr_score(kr)
status = get_kr_status(score, quarter_progress, kr)
# Calculate time-adjusted gap
expected_score = quarter_progress * 0.85 # Expect 85% of time-proportional progress
gap = expected_score - score
risk_level = _assess_kr_risk(score, status, gap, quarter_progress, kr)
scored_krs.append({
**kr,
"score": round(score, 3),
"score_pct": f"{score * 100:.0f}%",
"status": status,
"status_label": STATUS_LABELS.get(status, status),
"expected_score": round(expected_score, 3),
"gap_vs_expected": round(gap, 3),
"risk_level": risk_level,
"risk_label": RISK_LABELS.get(risk_level, risk_level),
})
# Objective score = weighted average of KR scores
# Weight is explicit in KR data or defaults to equal weight
total_weight = sum(kr.get("weight", 1.0) for kr in key_results)
weighted_score = sum(
kr_scored["score"] * kr.get("weight", 1.0)
for kr_scored, kr in zip(scored_krs, key_results)
)
obj_score = weighted_score / total_weight if total_weight > 0 else 0.0
# Objective status = worst KR status (a chain is only as strong as weakest link)
status_priority = {"off_track": 0, "at_risk": 1, "not_started": 2, "on_track": 3, "complete": 4}
obj_status = min(scored_krs, key=lambda x: status_priority.get(x["status"], 2))["status"]
return {
**objective,
"score": round(obj_score, 3),
"score_pct": f"{obj_score * 100:.0f}%",
"status": obj_status,
"status_label": STATUS_LABELS.get(obj_status, obj_status),
"key_results_scored": scored_krs,
}
def _assess_kr_risk(
score: float,
status: str,
gap: float,
quarter_progress: float,
kr: dict,
) -> str:
"""Assess risk level for a key result."""
if status == "complete" or status == "on_track":
return "low"
weeks_remaining = kr.get("weeks_remaining", max(1, int((1 - quarter_progress) * 13)))
# Critical: off track with <4 weeks left
if status == "off_track" and weeks_remaining <= 4:
return "critical"
# High: significantly behind with limited time
if gap > 0.3 and weeks_remaining <= 6:
return "high"
# High: off track regardless of time
if status == "off_track":
return "high"
# Medium: at risk
if status == "at_risk":
return "medium"
return "low"
# ---------------------------------------------------------------------------
# OKR Cascade and Alignment Analysis
# ---------------------------------------------------------------------------
def build_okr_tree(data: dict, quarter_progress: float) -> dict:
"""
Build scored OKR tree: company → departments → teams.
Returns full hierarchy with scores at every level.
"""
company = data.get("company_okrs", {})
departments = data.get("department_okrs", [])
teams = data.get("team_okrs", [])
# Score company-level OKRs
company_scored = {
"name": company.get("name", "Company"),
"quarter": company.get("quarter", ""),
"objectives": [
calculate_objective_score(obj, quarter_progress)
for obj in company.get("objectives", [])
],
}
# Score department-level OKRs
depts_scored = []
for dept in departments:
dept_objectives = [
calculate_objective_score(obj, quarter_progress)
for obj in dept.get("objectives", [])
]
dept_score = (
sum(o["score"] for o in dept_objectives) / len(dept_objectives)
if dept_objectives else 0.0
)
depts_scored.append({
**dept,
"objectives": dept_objectives,
"overall_score": round(dept_score, 3),
"overall_score_pct": f"{dept_score * 100:.0f}%",
})
# Score team-level OKRs
teams_scored = []
for team in teams:
team_objectives = [
calculate_objective_score(obj, quarter_progress)
for obj in team.get("objectives", [])
]
team_score = (
sum(o["score"] for o in team_objectives) / len(team_objectives)
if team_objectives else 0.0
)
teams_scored.append({
**team,
"objectives": team_objectives,
"overall_score": round(team_score, 3),
"overall_score_pct": f"{team_score * 100:.0f}%",
})
return {
"company": company_scored,
"departments": depts_scored,
"teams": teams_scored,
}
def analyze_alignment(okr_tree: dict) -> dict:
"""
Analyze how team and department OKRs align to company OKRs.
Flags: orphaned OKRs (no company parent), missing coverage (company OKR with no team support).
"""
company_objective_ids = {
obj.get("id") for obj in okr_tree["company"].get("objectives", [])
if obj.get("id")
}
# Collect all alignment references from dept and team OKRs
alignment_map: dict[str, list[str]] = {oid: [] for oid in company_objective_ids}
orphaned = []
all_supporting = []
def check_objectives(objectives: list, owner_name: str, level: str):
for obj in objectives:
supports = obj.get("supports_company_objective_ids", [])
if not supports:
# Check if it's supposed to support something
if obj.get("supports_company_objective_id"):
supports = [obj["supports_company_objective_id"]]
if not supports:
orphaned.append({
"level": level,
"owner": owner_name,
"objective": obj.get("title", obj.get("name", "Unknown")),
"issue": "No link to company objective — may be misaligned or low priority",
})
else:
for cid in supports:
if cid in alignment_map:
alignment_map[cid].append(f"{level}:{owner_name}")
all_supporting.append(cid)
else:
orphaned.append({
"level": level,
"owner": owner_name,
"objective": obj.get("title", obj.get("name", "Unknown")),
"issue": f"References company objective '{cid}' which doesn't exist",
})
for dept in okr_tree["departments"]:
check_objectives(dept["objectives"], dept.get("name", "Unknown Dept"), "Department")
for team in okr_tree["teams"]:
check_objectives(team["objectives"], team.get("name", "Unknown Team"), "Team")
# Find company objectives with no support from below
unsupported = []
for obj in okr_tree["company"].get("objectives", []):
obj_id = obj.get("id")
if obj_id and obj_id not in all_supporting:
unsupported.append({
"objective_id": obj_id,
"objective": obj.get("title", obj.get("name", "Unknown")),
"issue": "No department or team OKR explicitly supports this company objective",
})
coverage_score = (
len(set(all_supporting)) / len(company_objective_ids) * 100
if company_objective_ids else 100
)
return {
"alignment_map": alignment_map,
"orphaned_okrs": orphaned,
"unsupported_company_objectives": unsupported,
"coverage_score_pct": round(coverage_score, 1),
}
def collect_at_risk_krs(okr_tree: dict) -> list[dict]:
"""Collect all at-risk and off-track key results across the full OKR tree."""
at_risk = []
def scan_objectives(objectives: list, owner: str, level: str):
for obj in objectives:
for kr in obj.get("key_results_scored", []):
if kr["status"] in ("at_risk", "off_track"):
at_risk.append({
"level": level,
"owner": owner,
"objective": obj.get("title", obj.get("name", "Unknown")),
"key_result": kr.get("title", kr.get("name", "Unknown")),
"score": kr["score"],
"score_pct": kr["score_pct"],
"status": kr["status"],
"status_label": kr["status_label"],
"risk_level": kr["risk_level"],
"risk_label": kr["risk_label"],
"gap_vs_expected": kr["gap_vs_expected"],
"notes": kr.get("notes", ""),
})
scan_objectives(
okr_tree["company"].get("objectives", []),
okr_tree["company"].get("name", "Company"),
"Company",
)
for dept in okr_tree["departments"]:
scan_objectives(dept["objectives"], dept.get("name", ""), "Department")
for team in okr_tree["teams"]:
scan_objectives(team["objectives"], team.get("name", ""), "Team")
# Sort: off_track before at_risk, then by gap
status_order = {"off_track": 0, "at_risk": 1}
at_risk.sort(key=lambda x: (status_order.get(x["status"], 2), -x.get("gap_vs_expected", 0)))
return at_risk
# ---------------------------------------------------------------------------
# Report Formatter
# ---------------------------------------------------------------------------
def _score_bar(score: float, width: int = 20) -> str:
"""Render a text progress bar for a 0.0–1.0 score."""
filled = round(score * width)
bar = "█" * filled + "░" * (width - filled)
return f"[{bar}] {score * 100:.0f}%"
def format_report(
okr_tree: dict,
alignment: dict,
at_risk_krs: list[dict],
quarter_progress: float,
quarter_label: str,
) -> str:
"""Format full OKR tracking report as plain text."""
lines = []
now = datetime.now().strftime("%Y-%m-%d %H:%M")
company_name = okr_tree["company"].get("name", "Company")
lines.append("=" * 70)
lines.append(f"OKR TRACKING REPORT — {company_name}")
lines.append(f"Quarter: {quarter_label} | Quarter progress: {quarter_progress * 100:.0f}%")
lines.append(f"Generated: {now}")
lines.append("=" * 70)
# --- Executive Summary ---
lines.append("\n📊 EXECUTIVE SUMMARY")
lines.append("-" * 40)
company_objectives = okr_tree["company"].get("objectives", [])
if company_objectives:
company_avg = sum(o["score"] for o in company_objectives) / len(company_objectives)
on_track = sum(1 for o in company_objectives if o["status"] == "on_track")
at_risk = sum(1 for o in company_objectives if o["status"] == "at_risk")
off_track = sum(1 for o in company_objectives if o["status"] == "off_track")
lines.append(f"Company OKR Score: {_score_bar(company_avg)}")
lines.append(f"Objectives: {len(company_objectives)} total — "
f"🟢 {on_track} on track, 🟡 {at_risk} at risk, 🔴 {off_track} off track")
lines.append(f"At-risk KRs (all): {len(at_risk_krs)}")
lines.append(f"Alignment coverage: {alignment['coverage_score_pct']}% of company objectives have team support")
# Overall health assessment
if company_avg >= 0.7:
health = "🟢 HEALTHY — On track for a strong quarter"
elif company_avg >= 0.5:
health = "🟡 CAUTION — Some objectives need attention"
elif company_avg >= 0.3:
health = "🔴 AT RISK — Multiple objectives behind; intervention needed"
else:
health = "🚨 CRITICAL — Quarter in serious jeopardy; executive review required"
lines.append(f"\nOverall Health: {health}")
# --- Company OKRs ---
lines.append("\n\n🏢 COMPANY OKRs")
lines.append("-" * 40)
for obj in company_objectives:
lines.append(f"\n Objective: {obj.get('title', obj.get('name', 'Unknown'))}")
lines.append(f" Owner: {obj.get('owner', 'Unassigned')} | Score: {_score_bar(obj['score'], 15)} {obj['status_label']}")
for kr in obj.get("key_results_scored", []):
risk_marker = f" {kr['risk_label']}" if kr["risk_level"] in ("critical", "high") else ""
lines.append(f"\n KR: {kr.get('title', kr.get('name', 'Unknown'))}")
lines.append(f" Score: {_score_bar(kr['score'], 12)} {kr['status_label']}{risk_marker}")
# Show actual progress
if kr.get("type") == "numeric":
current = kr.get("current_value", "?")
target = kr.get("target_value", "?")
baseline = kr.get("baseline_value", 0)
unit = kr.get("unit", "")
lines.append(f" Progress: {current}{unit} / {target}{unit} (baseline: {baseline}{unit})")
elif kr.get("type") == "percentage":
lines.append(f" Progress: {kr.get('current_pct', '?')}% / {kr.get('target_pct', '?')}%")
elif kr.get("type") == "milestone":
hit = kr.get("milestones_hit", "?")
total = kr.get("milestones_total", "?")
lines.append(f" Milestones: {hit} / {total}")
if kr.get("notes"):
lines.append(f" Note: {kr['notes']}")
# --- Department OKRs ---
lines.append("\n\n🏬 DEPARTMENT OKRs")
lines.append("-" * 40)
for dept in okr_tree["departments"]:
lines.append(f"\n 📁 {dept.get('name', 'Unknown')} | Score: {_score_bar(dept['overall_score'], 15)}")
for obj in dept.get("objectives", []):
lines.append(f"\n Objective: {obj.get('title', obj.get('name', 'Unknown'))}")
lines.append(f" Owner: {obj.get('owner', 'Unassigned')} | {obj['status_label']}")
supports = obj.get("supports_company_objective_ids", [])
if supports:
lines.append(f" Supports: Company Objective(s) {', '.join(supports)}")
for kr in obj.get("key_results_scored", []):
risk_marker = f" {kr['risk_label']}" if kr["risk_level"] in ("critical", "high") else ""
lines.append(f"\n KR: {kr.get('title', kr.get('name', 'Unknown'))}")
lines.append(f" {_score_bar(kr['score'], 10)} {kr['status_label']}{risk_marker}")
# --- Team OKRs ---
if okr_tree["teams"]:
lines.append("\n\n👥 TEAM OKRs")
lines.append("-" * 40)
for team in okr_tree["teams"]:
lines.append(f"\n 📋 {team.get('name', 'Unknown')} | Score: {_score_bar(team['overall_score'], 15)}")
for obj in team.get("objectives", []):
lines.append(f"\n Objective: {obj.get('title', obj.get('name', 'Unknown'))}")
supports = obj.get("supports_company_objective_ids", [])
if supports:
lines.append(f" Supports: {', '.join(supports)}")
for kr in obj.get("key_results_scored", []):
risk_marker = f" {kr['risk_label']}" if kr["risk_level"] in ("critical", "high") else ""
lines.append(
f" • {kr.get('title', kr.get('name', 'Unknown'))}: "
f"{kr['score_pct']} {kr['status_label']}{risk_marker}"
)
# --- At-Risk KRs ---
lines.append("\n\n⚠️ AT-RISK KEY RESULTS (Action Required)")
lines.append("-" * 40)
if not at_risk_krs:
lines.append("✅ No key results currently at risk or off track.")
else:
critical = [kr for kr in at_risk_krs if kr["risk_level"] == "critical"]
high = [kr for kr in at_risk_krs if kr["risk_level"] == "high"]
medium = [kr for kr in at_risk_krs if kr["risk_level"] == "medium"]
for group_label, group in [("🔴 CRITICAL", critical), ("🟠 HIGH", high), ("🟡 MEDIUM", medium)]:
if not group:
continue
lines.append(f"\n{group_label} ({len(group)} items):")
for kr in group:
lines.append(f"\n [{kr['level']}] {kr['owner']}")
lines.append(f" Obj: {kr['objective']}")
lines.append(f" KR: {kr['key_result']}")
lines.append(f" Score: {kr['score_pct']} {kr['status_label']} (gap vs expected: {kr['gap_vs_expected'] * 100:.0f}pp)")
if kr["notes"]:
lines.append(f" Note: {kr['notes']}")
# --- Alignment Report ---
lines.append("\n\n🔗 ALIGNMENT REPORT")
lines.append("-" * 40)
lines.append(f"Alignment coverage: {alignment['coverage_score_pct']}% of company objectives have explicit support\n")
# Show alignment map
lines.append("Company Objective Coverage:")
for obj in company_objectives:
obj_id = obj.get("id", "")
supporters = alignment["alignment_map"].get(obj_id, [])
obj_name = obj.get("title", obj.get("name", obj_id))
count = len(supporters)
marker = "✅" if count > 0 else "⚠️ "
lines.append(f" {marker} [{obj_id}] {obj_name}")
if supporters:
for s in supporters:
lines.append(f" ↑ {s}")
else:
lines.append(f" ↑ (no department or team OKR supports this)")
if alignment["unsupported_company_objectives"]:
lines.append(f"\n⚠️ Unsupported Company Objectives ({len(alignment['unsupported_company_objectives'])}):")
for u in alignment["unsupported_company_objectives"]:
lines.append(f" • [{u['objective_id']}] {u['objective']}")
lines.append(f" → {u['issue']}")
if alignment["orphaned_okrs"]:
lines.append(f"\n⚠️ Orphaned OKRs (not linked to company objectives):")
for o in alignment["orphaned_okrs"]:
lines.append(f" • [{o['level']}] {o['owner']}: {o['objective']}")
lines.append(f" → {o['issue']}")
# --- Recommendations ---
lines.append("\n\n📋 RECOMMENDED ACTIONS")
lines.append("-" * 40)
recs = _generate_recommendations(okr_tree, at_risk_krs, alignment, quarter_progress)
for i, rec in enumerate(recs, 1):
lines.append(f"\n{i}. {rec['title']}")
lines.append(f" {rec['detail']}")
lines.append(f" Owner: {rec['owner']} | When: {rec['when']}")
lines.append("\n" + "=" * 70)
lines.append("END OF REPORT")
lines.append("=" * 70)
return "\n".join(lines)
def _generate_recommendations(
okr_tree: dict,
at_risk_krs: list[dict],
alignment: dict,
quarter_progress: float,
) -> list[dict]:
"""Generate actionable recommendations based on OKR analysis."""
recs = []
# Critical KRs
critical = [kr for kr in at_risk_krs if kr["risk_level"] == "critical"]
if critical:
recs.append({
"title": f"Emergency review: {len(critical)} critical key result(s) need immediate intervention",
"detail": f"Critical KRs: {', '.join(kr['key_result'] for kr in critical[:3])}. "
f"With limited time remaining, these need escalation today.",
"owner": "COO + KR owners",
"when": "This week",
})
# Off-track objectives
off_track_objs = [
o for o in okr_tree["company"].get("objectives", [])
if o["status"] == "off_track"
]
if off_track_objs:
recs.append({
"title": f"Scope reset for {len(off_track_objs)} off-track company objective(s)",
"detail": "When a company objective is off track by mid-quarter, "
"the options are: (1) resource surge, (2) scope reduction, or (3) accept the miss. "
"Choose explicitly — don't let it drift.",
"owner": "CEO + COO",
"when": "Within 1 week",
})
# Alignment gaps
if alignment["coverage_score_pct"] < 80:
recs.append({
"title": "OKR alignment gap — not all company objectives have team support",
"detail": f"Only {alignment['coverage_score_pct']}% of company objectives have explicit team/dept OKRs supporting them. "
"Either add supporting OKRs or acknowledge these objectives are founder-owned.",
"owner": "COO + VPs",
"when": "Next OKR planning cycle",
})
if alignment["orphaned_okrs"]:
recs.append({
"title": f"{len(alignment['orphaned_okrs'])} orphaned OKR(s) with no company objective linkage",
"detail": "Team OKRs that don't connect to company objectives waste capacity. "
"Either link them explicitly or discontinue them.",
"owner": "Team leads + COO",
"when": "OKR review session",
})
# Late quarter: force ranking
if quarter_progress >= 0.67:
at_risk_count = sum(
1 for o in okr_tree["company"].get("objectives", [])
if o["status"] in ("at_risk", "off_track")
)
if at_risk_count > 0:
recs.append({
"title": f"Late quarter: force-rank which at-risk OKRs to save vs. accept as miss",
"detail": f"{at_risk_count} objectives at risk with <{int((1 - quarter_progress) * 13)} weeks left. "
"You cannot save everything. Pick the 1–2 most important and resource them fully. "
"Explicitly accept the others as misses and learn from them.",
"owner": "CEO + COO",
"when": "Immediately",
})
# Measurement gaps
unscored_krs = []
for obj in okr_tree["company"].get("objectives", []):
for kr in obj.get("key_results_scored", []):
if kr["score"] == 0.0 and kr["status"] == "not_started" and quarter_progress > 0.25:
unscored_krs.append(kr.get("title", kr.get("name", "Unknown")))
if unscored_krs:
recs.append({
"title": f"{len(unscored_krs)} key result(s) show no progress past Q1",
"detail": "KRs with zero progress after 25% of quarter has elapsed are either not started, "
"unmeasured, or forgotten. Require owners to update scores this week.",
"owner": "KR owners",
"when": "This week — before next leadership sync",
})
return recs
def format_json_output(okr_tree: dict, alignment: dict, at_risk_krs: list[dict]) -> str:
"""Format analysis as machine-readable JSON."""
return json.dumps(
{
"generated_at": datetime.now().isoformat(),
"company_score": (
sum(o["score"] for o in okr_tree["company"].get("objectives", []))
/ max(1, len(okr_tree["company"].get("objectives", [])))
),
"at_risk_count": len(at_risk_krs),
"alignment_coverage_pct": alignment["coverage_score_pct"],
"objectives": okr_tree["company"].get("objectives", []),
"departments": okr_tree["departments"],
"teams": okr_tree["teams"],
"at_risk_key_results": at_risk_krs,
"alignment": alignment,
},
indent=2,
)
# ---------------------------------------------------------------------------
# Main Entrypoint
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(
description="OKR Cascade and Alignment Tracker — COO Advisor Tool",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("--input", "-i", help="Path to JSON OKR data file", default=None)
parser.add_argument("--output", "-o", help="Path to write report (default: stdout)", default=None)
parser.add_argument(
"--format", "-f",
choices=["text", "json"],
default="text",
help="Output format: text (default) or json",
)
parser.add_argument(
"--quarter-progress",
type=float,
default=None,
help="Override quarter progress (0.0–1.0). Default: auto-calculated from quarter dates.",
)
args = parser.parse_args()
if args.input:
try:
with open(args.input, "r") as f:
data = json.load(f)
except FileNotFoundError:
print(f"Error: Input file not found: {args.input}", file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON: {e}", file=sys.stderr)
sys.exit(1)
else:
print("No input file specified — running with sample data.\n")
data = SAMPLE_DATA
# Determine quarter progress
if args.quarter_progress is not None:
quarter_progress = args.quarter_progress
else:
quarter_progress = _calculate_quarter_progress(data)
quarter_label = data.get("company_okrs", {}).get("quarter", "Unknown Quarter")
# Run analysis
okr_tree = build_okr_tree(data, quarter_progress)
alignment = analyze_alignment(okr_tree)
at_risk_krs = collect_at_risk_krs(okr_tree)
# Format output
if args.format == "json":
output = format_json_output(okr_tree, alignment, at_risk_krs)
else:
output = format_report(okr_tree, alignment, at_risk_krs, quarter_progress, quarter_label)
if args.output:
with open(args.output, "w") as f:
f.write(output)
print(f"Report written to: {args.output}")
else:
print(output)
def _calculate_quarter_progress(data: dict) -> float:
"""Auto-calculate quarter progress from start/end dates in data, or default to 0.5."""
q = data.get("company_okrs", {})
start_str = q.get("quarter_start")
end_str = q.get("quarter_end")
if not start_str or not end_str:
return 0.5 # Default to mid-quarter if not specified
try:
start = date.fromisoformat(start_str)
end = date.fromisoformat(end_str)
today = date.today()
total_days = (end - start).days
elapsed_days = (today - start).days
progress = elapsed_days / total_days if total_days > 0 else 0.5
return max(0.0, min(1.0, progress))
except (ValueError, TypeError):
return 0.5
# ---------------------------------------------------------------------------
# Sample Data
# ---------------------------------------------------------------------------
SAMPLE_DATA = {
"company_okrs": {
"name": "AcmeSaaS",
"quarter": "Q1 2025",
"quarter_start": "2025-01-01",
"quarter_end": "2025-03-31",
"objectives": [
{
"id": "CO1",
"title": "Achieve breakout revenue growth",
"owner": "CEO",
"key_results": [
{
"id": "CO1-KR1",
"title": "Reach $5M net new ARR",
"type": "numeric",
"baseline_value": 0,
"current_value": 2800000,
"target_value": 5000000,
"unit": "",
"notes": "Strong January, February softer; pipeline looks better for March",
},
{
"id": "CO1-KR2",
"title": "Achieve 115% NRR",
"type": "percentage",
"baseline_pct": 108,
"current_pct": 110,
"target_pct": 115,
"notes": "Expansion motion improved; churn still elevated in SMB segment",
},
{
"id": "CO1-KR3",
"title": "Close 3 enterprise deals (>$150K ACV)",
"type": "numeric",
"baseline_value": 0,
"current_value": 1,
"target_value": 3,
"unit": " deals",
"notes": "1 closed, 2 in late-stage negotiation",
},
],
},
{
"id": "CO2",
"title": "Build a world-class product that customers love",
"owner": "CPO",
"key_results": [
{
"id": "CO2-KR1",
"title": "Increase feature adoption rate to 65% (% of customers using 3+ core features)",
"type": "percentage",
"baseline_pct": 48,
"current_pct": 52,
"target_pct": 65,
"notes": "Onboarding improvements shipped; adoption curve is moving",
},
{
"id": "CO2-KR2",
"title": "Ship the integration platform (milestone)",
"type": "milestone",
"milestones_total": 4,
"milestones_hit": 1,
"milestones": [
"API design complete",
"Internal alpha",
"Beta with 5 customers",
"GA launch",
],
"notes": "API design shipped. Internal alpha delayed 2 weeks.",
},
{
"id": "CO2-KR3",
"title": "NPS score reaches 45",
"type": "numeric",
"baseline_value": 32,
"current_value": 38,
"target_value": 45,
"unit": "",
},
],
},
{
"id": "CO3",
"title": "Build an operationally excellent company",
"owner": "COO",
"key_results": [
{
"id": "CO3-KR1",
"title": "Reduce burn multiple from 1.8x to 1.3x",
"type": "numeric",
"baseline_value": 1.8,
"current_value": 1.65,
"target_value": 1.3,
"lower_is_better": True,
"unit": "x",
},
{
"id": "CO3-KR2",
"title": "Achieve <30-day customer onboarding (avg)",
"type": "numeric",
"baseline_value": 47,
"current_value": 38,
"target_value": 30,
"lower_is_better": True,
"unit": " days",
"notes": "Good progress; blocked by technical setup step (avg 12 days)",
},
{
"id": "CO3-KR3",
"title": "Voluntary attrition <10%",
"type": "numeric",
"baseline_value": 15,
"current_value": 12,
"target_value": 10,
"lower_is_better": True,
"unit": "%",
"notes": "2 unexpected departures in January; retention initiatives launched",
},
],
},
],
},
"department_okrs": [
{
"name": "Sales",
"owner": "VP Sales",
"objectives": [
{
"title": "Drive net new ARR to hit company growth target",
"owner": "VP Sales",
"supports_company_objective_ids": ["CO1"],
"key_results": [
{
"title": "Close $4M in new business ARR",
"type": "numeric",
"baseline_value": 0,
"current_value": 2200000,
"target_value": 4000000,
"unit": "",
},
{
"title": "Maintain pipeline coverage ratio ≥3x",
"type": "numeric",
"baseline_value": 2.5,
"current_value": 3.1,
"target_value": 3.0,
"unit": "x",
},
{
"title": "Reduce average sales cycle to 42 days",
"type": "numeric",
"baseline_value": 58,
"current_value": 50,
"target_value": 42,
"lower_is_better": True,
"unit": " days",
},
],
}
],
},
{
"name": "Engineering",
"owner": "VP Engineering",
"objectives": [
{
"title": "Deliver the integration platform on schedule",
"owner": "VP Engineering",
"supports_company_objective_ids": ["CO2"],
"key_results": [
{
"title": "Integration platform beta live with 5 customers",
"type": "milestone",
"milestones_total": 3,
"milestones_hit": 1,
"notes": "Alpha delayed — dependency on API gateway refactor",
},
{
"title": "Deploy frequency ≥10/week",
"type": "numeric",
"baseline_value": 6,
"current_value": 9,
"target_value": 10,
"unit": "/week",
},
{
"title": "P0/P1 incidents <2 per month",
"type": "numeric",
"baseline_value": 5,
"current_value": 2.5,
"target_value": 2,
"lower_is_better": True,
"unit": "/month",
},
],
}
],
},
{
"name": "Customer Success",
"owner": "VP CS",
"objectives": [
{
"title": "Drive retention and expansion to fuel NRR growth",
"owner": "VP CS",
"supports_company_objective_ids": ["CO1", "CO2"],
"key_results": [
{
"title": "Gross retention ≥92%",
"type": "percentage",
"baseline_pct": 88,
"current_pct": 89,
"target_pct": 92,
"notes": "3 at-risk accounts in red status",
},
{
"title": "Average onboarding time ≤30 days",
"type": "numeric",
"baseline_value": 47,
"current_value": 38,
"target_value": 30,
"lower_is_better": True,
"unit": " days",
},
{
"title": "Expansion ARR from existing customers: $800K",
"type": "numeric",
"baseline_value": 0,
"current_value": 580000,
"target_value": 800000,
"unit": "",
},
],
}
],
},
],
"team_okrs": [
{
"name": "Platform Engineering",
"department": "Engineering",
"objectives": [
{
"title": "Build the integration API infrastructure",
"supports_company_objective_ids": ["CO2"],
"key_results": [
{
"title": "API gateway v2 deployed to production",
"type": "boolean",
"done": False,
"notes": "Targeting end of week 8",
},
{
"title": "Webhook system handles 10K events/sec",
"type": "boolean",
"done": False,
},
{
"title": "P99 API latency <200ms",
"type": "numeric",
"baseline_value": 380,
"current_value": 290,
"target_value": 200,
"lower_is_better": True,
"unit": "ms",
},
],
}
],
},
{
"name": "Enterprise Sales Team",
"department": "Sales",
"objectives": [
{
"title": "Land 3 enterprise accounts",
"supports_company_objective_ids": ["CO1"],
"key_results": [
{
"title": "3 enterprise deals closed",
"type": "numeric",
"baseline_value": 0,
"current_value": 1,
"target_value": 3,
"unit": " deals",
},
{
"title": "5 enterprise POCs initiated",
"type": "numeric",
"baseline_value": 0,
"current_value": 4,
"target_value": 5,
"unit": " POCs",
},
],
}
],
},
],
}
if __name__ == "__main__":
main()
FILE:scripts/ops_efficiency_analyzer.py
#!/usr/bin/env python3
"""
ops_efficiency_analyzer.py — Operational Efficiency Analyzer
Analyzes startup operational efficiency using Theory of Constraints,
process maturity scoring, and bottleneck identification.
Usage:
python ops_efficiency_analyzer.py # Runs with sample data
python ops_efficiency_analyzer.py --input data.json # Custom data
python ops_efficiency_analyzer.py --input data.json --output report.txt
Input format: See SAMPLE_DATA at bottom of file.
"""
import json
import sys
import argparse
import math
from datetime import datetime
from typing import Any, Optional
# ---------------------------------------------------------------------------
# Data Models (plain dicts with type aliases for clarity)
# ---------------------------------------------------------------------------
ProcessData = dict[str, Any]
TeamData = dict[str, Any]
MetricsData = dict[str, Any]
# ---------------------------------------------------------------------------
# Process Maturity Scoring
# ---------------------------------------------------------------------------
MATURITY_LEVELS = {
1: "Ad Hoc",
2: "Defined",
3: "Managed",
4: "Optimized",
5: "Innovating",
}
MATURITY_DESCRIPTIONS = {
1: "No documented process. Outcomes depend on individual heroics.",
2: "Process exists and is documented. Inconsistently followed.",
3: "Process is followed consistently. Metrics are tracked.",
4: "Process is optimized based on metrics. Proactively improved.",
5: "Process enables competitive advantage. Continuously innovating.",
}
MATURITY_CRITERIA = {
"documentation": {
"weight": 0.20,
"levels": {
0: "No documentation",
1: "Informal notes or tribal knowledge",
2: "Process documented but not maintained",
3: "Documented, current, accessible",
4: "Documented with examples, edge cases, and owner",
5: "Living doc with version history and improvement log",
},
},
"ownership": {
"weight": 0.15,
"levels": {
0: "No owner",
1: "Unclear ownership, multiple people responsible",
2: "Named team responsible",
3: "Named individual DRI",
4: "DRI with metrics accountability",
5: "DRI with improvement mandate and resources",
},
},
"metrics": {
"weight": 0.20,
"levels": {
0: "No metrics",
1: "Anecdotal measurement",
2: "Some metrics tracked, not regularly reviewed",
3: "Key metrics tracked and reviewed monthly",
4: "Metrics drive decisions, targets set",
5: "Predictive metrics, benchmarked externally",
},
},
"automation": {
"weight": 0.20,
"levels": {
0: "100% manual",
1: "Mostly manual, some tools used",
2: "Key steps automated, significant manual work remains",
3: "Majority automated, manual exception handling",
4: "Mostly automated with exception playbooks",
5: "Fully automated with human oversight only",
},
},
"consistency": {
"weight": 0.15,
"levels": {
0: "Never consistent",
1: "Consistent <50% of time",
2: "Consistent 50-75% of time",
3: "Consistent 75-90% of time",
4: "Consistent >90% of time",
5: "Six Sigma level (>99.7%)",
},
},
"feedback_loop": {
"weight": 0.10,
"levels": {
0: "No feedback loop",
1: "Ad hoc complaints surface issues",
2: "Periodic review when problems arise",
3: "Regular review cadence",
4: "Structured improvement cycles",
5: "Real-time feedback with automated triggers",
},
},
}
def score_process_maturity(process: ProcessData) -> dict[str, Any]:
"""
Score a single process on 1-5 maturity scale.
Returns scored process with dimension breakdown and recommendations.
"""
maturity_inputs = process.get("maturity", {})
total_score = 0.0
dimension_scores = {}
recommendations = []
for dimension, config in MATURITY_CRITERIA.items():
raw_score = maturity_inputs.get(dimension, 0)
# Normalize raw score (0-5) to weight
normalized = (raw_score / 5.0) * config["weight"] * 5
total_score += normalized
dimension_scores[dimension] = raw_score
# Generate recommendation if below threshold
if raw_score < 3:
severity = "🔴 Critical" if raw_score < 2 else "🟡 Needs work"
recommendations.append({
"dimension": dimension,
"current_score": raw_score,
"target_score": 3,
"severity": severity,
"action": _get_improvement_action(dimension, raw_score),
})
# Clamp to 1-5 range (scores can't be below 1 for a running process)
maturity_score = max(1.0, min(5.0, total_score))
maturity_level = round(maturity_score)
return {
"name": process["name"],
"maturity_score": round(maturity_score, 2),
"maturity_level": maturity_level,
"maturity_label": MATURITY_LEVELS[maturity_level],
"dimension_scores": dimension_scores,
"recommendations": recommendations,
"process_data": process,
}
def _get_improvement_action(dimension: str, current_score: int) -> str:
"""Return a concrete improvement action for a given dimension and score."""
actions = {
"documentation": {
0: "Write a basic SOP this week: trigger, steps, owner, done-definition",
1: "Convert tribal knowledge into a written process doc with clear steps",
2: "Assign a process owner to maintain and update documentation quarterly",
},
"ownership": {
0: "Assign a DRI (Directly Responsible Individual) today",
1: "Clarify ownership: assign one named person, remove ambiguity",
2: "Give the named owner accountability for process metrics",
},
"metrics": {
0: "Define 1-2 metrics that measure if this process is working",
1: "Set up automated metric collection and add to monthly review",
2: "Set targets for each metric and review monthly",
},
"automation": {
0: "Identify the highest-volume manual step; automate it first",
1: "Run automation ROI calc — if payback <12 months, build it",
2: "Automate exception routing and error notifications",
},
"consistency": {
0: "Root-cause why the process fails; fix the #1 failure mode",
1: "Create a checklist for the process; require sign-off",
2: "Add process adherence check to team's weekly review",
},
"feedback_loop": {
0: "Add this process to monthly operational review agenda",
1: "Create a feedback channel (Slack thread, form) for process issues",
2: "Set a quarterly review date for this process",
},
}
return actions.get(dimension, {}).get(current_score, "Improve this dimension")
# ---------------------------------------------------------------------------
# Bottleneck Analysis (Theory of Constraints)
# ---------------------------------------------------------------------------
def analyze_bottlenecks(processes: list[ProcessData]) -> dict[str, Any]:
"""
Identify bottlenecks using throughput analysis.
Bottleneck = step with lowest throughput (or highest queue buildup).
"""
bottlenecks = []
throughput_chain = []
for process in processes:
steps = process.get("steps", [])
if not steps:
continue
step_analysis = []
min_throughput = float("inf")
bottleneck_step = None
for step in steps:
throughput = step.get("throughput_per_day", 0)
queue_depth = step.get("current_queue", 0)
avg_wait_hours = step.get("avg_wait_hours", 0)
# Utilization estimate
capacity = step.get("capacity_per_day", throughput * 1.2)
utilization = (throughput / capacity * 100) if capacity > 0 else 100
step_info = {
"name": step["name"],
"throughput_per_day": throughput,
"queue_depth": queue_depth,
"avg_wait_hours": avg_wait_hours,
"utilization_pct": round(utilization, 1),
"is_bottleneck": False,
}
step_analysis.append(step_info)
if throughput < min_throughput:
min_throughput = throughput
bottleneck_step = step_info
if bottleneck_step:
bottleneck_step["is_bottleneck"] = True
# Calculate flow efficiency
total_lead_time = sum(
s.get("avg_wait_hours", 0) + s.get("avg_process_hours", 1)
for s in steps
)
total_process_time = sum(s.get("avg_process_hours", 1) for s in steps)
flow_efficiency = (
(total_process_time / total_lead_time * 100)
if total_lead_time > 0
else 0
)
bottlenecks.append({
"process": process["name"],
"bottleneck_step": bottleneck_step["name"],
"bottleneck_throughput": min_throughput,
"bottleneck_queue": bottleneck_step["queue_depth"],
"flow_efficiency_pct": round(flow_efficiency, 1),
"steps": step_analysis,
"toc_recommendation": _generate_toc_recommendation(
bottleneck_step, process
),
})
throughput_chain.append({
"process": process["name"],
"steps": step_analysis,
})
# Rank bottlenecks by severity (queue depth × utilization)
for b in bottlenecks:
b["severity_score"] = b["bottleneck_queue"] * (b["bottleneck_throughput"] or 1)
bottlenecks.sort(key=lambda x: x["severity_score"], reverse=True)
return {
"bottlenecks": bottlenecks,
"throughput_chain": throughput_chain,
}
def _generate_toc_recommendation(bottleneck_step: dict, process: ProcessData) -> str:
"""Generate a Theory of Constraints recommendation for a bottleneck."""
util = bottleneck_step["utilization_pct"]
queue = bottleneck_step["queue_depth"]
step_name = bottleneck_step["name"]
if util >= 90:
return (
f"ELEVATE: '{step_name}' is at {util}% utilization — at capacity. "
f"Add resources (people, automation, or parallel processing) immediately. "
f"Queue of {queue} units will grow until capacity is increased."
)
elif util >= 70:
return (
f"EXPLOIT: '{step_name}' has capacity headroom but is the constraint. "
f"Eliminate non-value-add work in this step. Protect it from interruptions. "
f"Ensure upstream steps feed it steadily, not in batches."
)
else:
return (
f"INVESTIGATE: '{step_name}' shows low throughput ({bottleneck_step['throughput_per_day']}/day) "
f"despite available capacity. Root cause may be upstream blocking, "
f"unclear handoffs, or quality issues requiring rework."
)
# ---------------------------------------------------------------------------
# Team Structure Analysis
# ---------------------------------------------------------------------------
def analyze_team_structure(team: TeamData) -> dict[str, Any]:
"""
Analyze team structure for span of control, layer count, and hiring gaps.
"""
issues = []
recommendations = []
warnings = []
total_headcount = team.get("total_headcount", 0)
departments = team.get("departments", [])
# Span of control analysis
span_issues = []
for dept in departments:
for manager in dept.get("managers", []):
direct_reports = manager.get("direct_reports", 0)
manages_managers = manager.get("manages_managers", False)
optimal_min = 3 if manages_managers else 5
optimal_max = 5 if manages_managers else 8
if direct_reports < optimal_min:
span_issues.append({
"manager": manager["name"],
"dept": dept["name"],
"reports": direct_reports,
"issue": "Under-span",
"recommendation": f"Merge team or promote ICs — {direct_reports} reports is management overhead",
})
elif direct_reports > optimal_max:
span_issues.append({
"manager": manager["name"],
"dept": dept["name"],
"reports": direct_reports,
"issue": "Over-span",
"recommendation": f"Split team — {direct_reports} reports means minimal 1:1 time and poor feedback loops",
})
# Management layers analysis
max_layers = team.get("management_layers", 0)
expected_layers = _expected_layers(total_headcount)
if max_layers > expected_layers + 1:
issues.append({
"type": "Over-layered",
"detail": f"{max_layers} management layers for {total_headcount} people. "
f"Expected: {expected_layers}. Excess layers slow decisions.",
"recommendation": "Flatten: remove middle management layers that don't add decision value",
})
# Revenue per employee by department
annual_revenue = team.get("annual_revenue_usd", 0)
dept_analysis = []
for dept in departments:
headcount = dept.get("headcount", 0)
if headcount > 0 and annual_revenue > 0:
rev_per_employee = annual_revenue / headcount
benchmark = _dept_revenue_benchmark(dept["name"], team.get("stage", "series_a"))
efficiency_pct = (rev_per_employee / benchmark * 100) if benchmark > 0 else None
dept_analysis.append({
"department": dept["name"],
"headcount": headcount,
"revenue_per_employee": round(rev_per_employee),
"benchmark": benchmark,
"efficiency_vs_benchmark_pct": round(efficiency_pct, 1) if efficiency_pct else "N/A",
"status": _efficiency_status(efficiency_pct),
})
# Open req health
open_reqs = team.get("open_requisitions", 0)
req_to_headcount_ratio = (open_reqs / total_headcount * 100) if total_headcount > 0 else 0
if req_to_headcount_ratio > 20:
warnings.append(
f"High open req ratio: {open_reqs} open reqs against {total_headcount} headcount "
f"({req_to_headcount_ratio:.0f}%). This level of hiring while operating is operationally disruptive."
)
return {
"total_headcount": total_headcount,
"management_layers": max_layers,
"expected_layers": expected_layers,
"span_of_control_issues": span_issues,
"structural_issues": issues,
"department_efficiency": dept_analysis,
"open_req_health": {
"open_reqs": open_reqs,
"ratio_pct": round(req_to_headcount_ratio, 1),
"warnings": warnings,
},
}
def _expected_layers(headcount: int) -> int:
if headcount <= 15:
return 1
elif headcount <= 50:
return 2
elif headcount <= 150:
return 3
elif headcount <= 500:
return 4
else:
return 5
def _dept_revenue_benchmark(dept_name: str, stage: str) -> int:
"""Revenue per employee benchmark by department and stage (USD)."""
benchmarks = {
"series_a": {
"engineering": 400000,
"sales": 250000,
"customer_success": 300000,
"marketing": 500000,
"operations": 400000,
"product": 400000,
"default": 200000,
},
"series_b": {
"engineering": 500000,
"sales": 350000,
"customer_success": 400000,
"marketing": 700000,
"operations": 500000,
"product": 500000,
"default": 300000,
},
"series_c": {
"engineering": 600000,
"sales": 450000,
"customer_success": 500000,
"marketing": 900000,
"operations": 600000,
"product": 600000,
"default": 400000,
},
}
stage_data = benchmarks.get(stage, benchmarks["series_a"])
dept_key = dept_name.lower().replace(" ", "_").replace("-", "_")
return stage_data.get(dept_key, stage_data["default"])
def _efficiency_status(efficiency_pct: Optional[float]) -> str:
if efficiency_pct is None:
return "N/A"
if efficiency_pct >= 90:
return "🟢 On benchmark"
elif efficiency_pct >= 70:
return "🟡 Below benchmark"
else:
return "🔴 Significantly below"
# ---------------------------------------------------------------------------
# Improvement Plan Generator
# ---------------------------------------------------------------------------
def generate_improvement_plan(
process_scores: list[dict],
bottleneck_analysis: dict,
team_analysis: dict,
metrics: MetricsData,
) -> list[dict]:
"""
Generate a prioritized improvement plan combining all analysis outputs.
Priority = Impact × Urgency / Effort
"""
items = []
# Priority 1: Process bottlenecks (Theory of Constraints — fix the constraint first)
for b in bottleneck_analysis.get("bottlenecks", [])[:3]:
items.append({
"priority": 1,
"category": "Bottleneck",
"item": f"Resolve bottleneck in '{b['process']}' at step '{b['bottleneck_step']}'",
"detail": b["toc_recommendation"],
"impact": "HIGH — constraint limits entire system throughput",
"effort": "MEDIUM",
"owner_suggestion": "COO + process owner",
"timebox": "2-4 weeks",
"success_metric": f"Throughput at {b['bottleneck_step']} increases by 25%+",
})
# Priority 2: Critical process maturity gaps
critical_processes = [
p for p in process_scores if p["maturity_score"] < 2.0
]
for proc in sorted(critical_processes, key=lambda x: x["maturity_score"]):
for rec in proc["recommendations"][:2]: # Top 2 recs per critical process
items.append({
"priority": 2,
"category": "Process Maturity",
"item": f"Fix {rec['dimension']} in '{proc['name']}' (score: {rec['current_score']}/5)",
"detail": rec["action"],
"impact": "HIGH — ad-hoc processes create inconsistency and risk",
"effort": "LOW-MEDIUM",
"owner_suggestion": "Process owner",
"timebox": "1-2 weeks",
"success_metric": f"Dimension score improves to 3/5",
})
# Priority 3: Team structural issues
for issue in team_analysis.get("structural_issues", []):
items.append({
"priority": 3,
"category": "Org Structure",
"item": issue["type"],
"detail": issue["detail"],
"impact": "MEDIUM — structural issues compound over time",
"effort": "HIGH",
"owner_suggestion": "COO + People",
"timebox": "1-2 quarters",
"success_metric": "Management layer count normalized",
})
for span_issue in team_analysis.get("span_of_control_issues", []):
severity = "HIGH" if span_issue["issue"] == "Over-span" else "MEDIUM"
items.append({
"priority": 3,
"category": "Span of Control",
"item": f"{span_issue['issue']}: {span_issue['manager']} ({span_issue['dept']})",
"detail": span_issue["recommendation"],
"impact": severity,
"effort": "MEDIUM",
"owner_suggestion": f"VP {span_issue['dept']}",
"timebox": "1 quarter",
"success_metric": "Span within 5-8 for ICs, 3-5 for managers",
})
# Priority 4: Maturity improvements for non-critical processes
medium_processes = [
p for p in process_scores if 2.0 <= p["maturity_score"] < 3.5
]
for proc in sorted(medium_processes, key=lambda x: x["maturity_score"])[:3]:
if proc["recommendations"]:
top_rec = proc["recommendations"][0]
items.append({
"priority": 4,
"category": "Process Improvement",
"item": f"Improve {top_rec['dimension']} in '{proc['name']}'",
"detail": top_rec["action"],
"impact": "MEDIUM",
"effort": "LOW",
"owner_suggestion": "Process owner",
"timebox": "2-4 weeks",
"success_metric": f"Dimension score reaches 3/5",
})
# Priority 5: Metrics-driven flags
burn_multiple = metrics.get("burn_multiple")
if burn_multiple and burn_multiple > 2.0:
items.append({
"priority": 2,
"category": "Financial Efficiency",
"item": f"Burn multiple of {burn_multiple:.1f}x is above healthy range",
"detail": "Burn multiple >1.5x indicates spending exceeds efficient growth. Review headcount-to-revenue ratio by department.",
"impact": "HIGH",
"effort": "MEDIUM",
"owner_suggestion": "COO + CFO",
"timebox": "30 days to diagnose, 60-90 days to act",
"success_metric": "Burn multiple <1.5x within 2 quarters",
})
nrr = metrics.get("net_revenue_retention_pct")
if nrr and nrr < 100:
items.append({
"priority": 1,
"category": "Revenue Health",
"item": f"NRR of {nrr}% — losing more from churn/contraction than gaining from expansion",
"detail": "NRR <100% means the customer base shrinks without new sales. Investigate churn root causes immediately.",
"impact": "CRITICAL",
"effort": "HIGH",
"owner_suggestion": "COO + VP CS",
"timebox": "Immediate — 30 days to root cause, 90 days to fix",
"success_metric": "NRR >100% within 2 quarters",
})
# Sort by priority then impact
priority_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
items.sort(key=lambda x: (x["priority"], priority_order.get(x["impact"].split(" — ")[0], 9)))
return items
# ---------------------------------------------------------------------------
# Report Formatter
# ---------------------------------------------------------------------------
def format_report(
process_scores: list[dict],
bottleneck_analysis: dict,
team_analysis: dict,
improvement_plan: list[dict],
metrics: MetricsData,
) -> str:
"""Format the full analysis report as plain text."""
lines = []
now = datetime.now().strftime("%Y-%m-%d %H:%M")
lines.append("=" * 70)
lines.append("OPERATIONAL EFFICIENCY ANALYSIS REPORT")
lines.append(f"Generated: {now}")
lines.append("=" * 70)
# --- Executive Summary ---
lines.append("\n📊 EXECUTIVE SUMMARY")
lines.append("-" * 40)
avg_maturity = (
sum(p["maturity_score"] for p in process_scores) / len(process_scores)
if process_scores else 0
)
critical_count = sum(1 for p in process_scores if p["maturity_score"] < 2.0)
bottleneck_count = len(bottleneck_analysis.get("bottlenecks", []))
plan_items = len(improvement_plan)
lines.append(f"Average Process Maturity: {avg_maturity:.1f}/5.0 ({MATURITY_LEVELS.get(round(avg_maturity), 'Unknown')})")
lines.append(f"Critical Process Gaps: {critical_count}")
lines.append(f"Active Bottlenecks: {bottleneck_count}")
lines.append(f"Improvement Plan Items: {plan_items}")
if metrics:
lines.append("\nKey Business Metrics:")
if metrics.get("burn_multiple"):
flag = " ⚠️" if metrics["burn_multiple"] > 2.0 else ""
lines.append(f" Burn Multiple: {metrics['burn_multiple']:.1f}x{flag}")
if metrics.get("net_revenue_retention_pct"):
flag = " ⚠️" if metrics["net_revenue_retention_pct"] < 100 else ""
lines.append(f" NRR: {metrics['net_revenue_retention_pct']}%{flag}")
if metrics.get("cac_payback_months"):
flag = " ⚠️" if metrics["cac_payback_months"] > 18 else ""
lines.append(f" CAC Payback: {metrics['cac_payback_months']} months{flag}")
# --- Process Maturity Scores ---
lines.append("\n\n📋 PROCESS MATURITY SCORES")
lines.append("-" * 40)
lines.append(f"{'Process':<35} {'Score':>6} {'Level':<12} {'Status'}")
lines.append(f"{'─'*35} {'─'*6} {'─'*12} {'─'*20}")
for p in sorted(process_scores, key=lambda x: x["maturity_score"]):
score = p["maturity_score"]
label = p["maturity_label"]
status = "🔴 Critical" if score < 2 else ("🟡 Needs work" if score < 3.5 else "🟢 Healthy")
lines.append(f"{p['name']:<35} {score:>6.1f} {label:<12} {status}")
# Dimension heatmap
lines.append("\n\nDimension Breakdown (scores 0-5):")
lines.append(f"{'Process':<30} {'Doc':>4} {'Own':>4} {'Met':>4} {'Aut':>4} {'Con':>4} {'Fbk':>4}")
lines.append(f"{'─'*30} {'─'*4} {'─'*4} {'─'*4} {'─'*4} {'─'*4} {'─'*4}")
for p in sorted(process_scores, key=lambda x: x["maturity_score"]):
d = p["dimension_scores"]
lines.append(
f"{p['name']:<30} {d.get('documentation',0):>4} {d.get('ownership',0):>4} "
f"{d.get('metrics',0):>4} {d.get('automation',0):>4} "
f"{d.get('consistency',0):>4} {d.get('feedback_loop',0):>4}"
)
# --- Bottleneck Analysis ---
lines.append("\n\n🔍 BOTTLENECK ANALYSIS (Theory of Constraints)")
lines.append("-" * 40)
bottlenecks = bottleneck_analysis.get("bottlenecks", [])
if not bottlenecks:
lines.append("No process steps defined for bottleneck analysis.")
else:
for i, b in enumerate(bottlenecks, 1):
lines.append(f"\n{i}. {b['process']}")
lines.append(f" Bottleneck step: {b['bottleneck_step']}")
lines.append(f" Throughput: {b['bottleneck_throughput']}/day")
lines.append(f" Queue depth: {b['bottleneck_queue']} units")
lines.append(f" Flow efficiency: {b['flow_efficiency_pct']}%")
lines.append(f" Recommendation: {b['toc_recommendation']}")
lines.append(f"\n Step-by-step throughput:")
for step in b["steps"]:
marker = " ← BOTTLENECK" if step["is_bottleneck"] else ""
lines.append(
f" {step['name']:<30} {step['throughput_per_day']:>4}/day "
f"Queue: {step['queue_depth']:>4} Util: {step['utilization_pct']:>5.1f}%{marker}"
)
# --- Team Structure ---
lines.append("\n\n👥 TEAM STRUCTURE ANALYSIS")
lines.append("-" * 40)
lines.append(f"Total headcount: {team_analysis['total_headcount']}")
lines.append(f"Management layers: {team_analysis['management_layers']} (expected: {team_analysis['expected_layers']})")
span_issues = team_analysis.get("span_of_control_issues", [])
if span_issues:
lines.append(f"\n⚠️ Span of Control Issues ({len(span_issues)}):")
for issue in span_issues:
lines.append(f" {issue['issue']}: {issue['manager']} ({issue['dept']}) — {issue['reports']} reports")
lines.append(f" → {issue['recommendation']}")
dept_eff = team_analysis.get("department_efficiency", [])
if dept_eff:
lines.append(f"\nDepartment Revenue Efficiency:")
lines.append(f"{'Department':<20} {'HC':>4} {'Rev/Head':>10} {'Benchmark':>10} {'vs Bench':>9} {'Status'}")
lines.append(f"{'─'*20} {'─'*4} {'─'*10} {'─'*10} {'─'*9} {'─'*20}")
for d in dept_eff:
rev = f"," if d['revenue_per_employee'] else "N/A"
bench = f"," if d['benchmark'] else "N/A"
vs_bench = f"{d['efficiency_vs_benchmark_pct']}%" if d['efficiency_vs_benchmark_pct'] != "N/A" else "N/A"
lines.append(
f"{d['department']:<20} {d['headcount']:>4} {rev:>10} {bench:>10} {vs_bench:>9} {d['status']}"
)
# --- Improvement Plan ---
lines.append("\n\n🎯 PRIORITIZED IMPROVEMENT PLAN")
lines.append("-" * 40)
lines.append("Items ranked by priority (1=highest). Fix Priority 1 before starting Priority 2.\n")
current_priority = None
for i, item in enumerate(improvement_plan, 1):
if item["priority"] != current_priority:
current_priority = item["priority"]
lines.append(f"\nPRIORITY {current_priority}")
lines.append("─" * 30)
lines.append(f"\n{i}. [{item['category']}] {item['item']}")
lines.append(f" Detail: {item['detail']}")
lines.append(f" Impact: {item['impact']}")
lines.append(f" Effort: {item['effort']}")
lines.append(f" Owner: {item['owner_suggestion']}")
lines.append(f" Timebox: {item['timebox']}")
lines.append(f" Success: {item['success_metric']}")
lines.append("\n" + "=" * 70)
lines.append("END OF REPORT")
lines.append("=" * 70)
return "\n".join(lines)
# ---------------------------------------------------------------------------
# Main Entrypoint
# ---------------------------------------------------------------------------
def run_analysis(data: dict) -> str:
"""Run the full analysis pipeline on input data."""
processes = data.get("processes", [])
team = data.get("team", {})
metrics = data.get("metrics", {})
# 1. Score process maturity
process_scores = [score_process_maturity(p) for p in processes]
# 2. Analyze bottlenecks
bottleneck_analysis = analyze_bottlenecks(processes)
# 3. Analyze team structure
team_analysis = analyze_team_structure(team)
# 4. Generate improvement plan
improvement_plan = generate_improvement_plan(
process_scores, bottleneck_analysis, team_analysis, metrics
)
# 5. Format and return report
return format_report(
process_scores, bottleneck_analysis, team_analysis, improvement_plan, metrics
)
def main():
parser = argparse.ArgumentParser(
description="Operational Efficiency Analyzer — COO Advisor Tool",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument(
"--input", "-i",
help="Path to JSON input file (default: use built-in sample data)",
default=None,
)
parser.add_argument(
"--output", "-o",
help="Path to write report (default: stdout)",
default=None,
)
args = parser.parse_args()
if args.input:
try:
with open(args.input, "r") as f:
data = json.load(f)
except FileNotFoundError:
print(f"Error: Input file not found: {args.input}", file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON in input file: {e}", file=sys.stderr)
sys.exit(1)
else:
print("No input file specified — running with sample data.\n")
data = SAMPLE_DATA
report = run_analysis(data)
if args.output:
with open(args.output, "w") as f:
f.write(report)
print(f"Report written to: {args.output}")
else:
print(report)
# ---------------------------------------------------------------------------
# Sample Data
# ---------------------------------------------------------------------------
SAMPLE_DATA = {
"company": "AcmeSaaS",
"stage": "series_b",
"metrics": {
"annual_revenue_usd": 18000000,
"burn_multiple": 1.8,
"net_revenue_retention_pct": 108,
"cac_payback_months": 14,
"headcount": 85,
"monthly_churn_pct": 1.2,
},
"processes": [
{
"name": "Customer Onboarding",
"category": "Customer Success",
"maturity": {
"documentation": 3,
"ownership": 4,
"metrics": 3,
"automation": 2,
"consistency": 3,
"feedback_loop": 2,
},
"steps": [
{
"name": "Contract signed → kickoff scheduled",
"throughput_per_day": 4,
"capacity_per_day": 6,
"current_queue": 3,
"avg_wait_hours": 4,
"avg_process_hours": 1,
},
{
"name": "Technical setup & integration",
"throughput_per_day": 2,
"capacity_per_day": 3,
"current_queue": 8,
"avg_wait_hours": 24,
"avg_process_hours": 8,
},
{
"name": "Training & enablement",
"throughput_per_day": 3,
"capacity_per_day": 4,
"current_queue": 2,
"avg_wait_hours": 8,
"avg_process_hours": 4,
},
{
"name": "Go-live confirmation",
"throughput_per_day": 4,
"capacity_per_day": 6,
"current_queue": 1,
"avg_wait_hours": 2,
"avg_process_hours": 1,
},
],
},
{
"name": "Sales Deal Qualification",
"category": "Sales",
"maturity": {
"documentation": 2,
"ownership": 3,
"metrics": 4,
"automation": 2,
"consistency": 2,
"feedback_loop": 3,
},
"steps": [
{
"name": "Inbound lead review",
"throughput_per_day": 15,
"capacity_per_day": 20,
"current_queue": 5,
"avg_wait_hours": 2,
"avg_process_hours": 0.5,
},
{
"name": "BANT qualification call",
"throughput_per_day": 8,
"capacity_per_day": 10,
"current_queue": 12,
"avg_wait_hours": 24,
"avg_process_hours": 1,
},
{
"name": "Demo scheduling & prep",
"throughput_per_day": 6,
"capacity_per_day": 8,
"current_queue": 4,
"avg_wait_hours": 8,
"avg_process_hours": 0.5,
},
],
},
{
"name": "Engineering Deployment",
"category": "Engineering",
"maturity": {
"documentation": 4,
"ownership": 5,
"metrics": 4,
"automation": 4,
"consistency": 5,
"feedback_loop": 4,
},
"steps": [
{
"name": "PR submitted",
"throughput_per_day": 20,
"capacity_per_day": 25,
"current_queue": 8,
"avg_wait_hours": 3,
"avg_process_hours": 2,
},
{
"name": "Code review",
"throughput_per_day": 18,
"capacity_per_day": 22,
"current_queue": 10,
"avg_wait_hours": 4,
"avg_process_hours": 1,
},
{
"name": "CI pipeline",
"throughput_per_day": 18,
"capacity_per_day": 30,
"current_queue": 2,
"avg_wait_hours": 0.5,
"avg_process_hours": 0.5,
},
{
"name": "Deploy to production",
"throughput_per_day": 16,
"capacity_per_day": 20,
"current_queue": 1,
"avg_wait_hours": 0.5,
"avg_process_hours": 0.25,
},
],
},
{
"name": "Incident Response",
"category": "Engineering / Operations",
"maturity": {
"documentation": 2,
"ownership": 2,
"metrics": 1,
"automation": 1,
"consistency": 2,
"feedback_loop": 1,
},
"steps": [],
},
{
"name": "Employee Onboarding",
"category": "People",
"maturity": {
"documentation": 2,
"ownership": 2,
"metrics": 1,
"automation": 1,
"consistency": 2,
"feedback_loop": 2,
},
"steps": [],
},
{
"name": "Vendor Procurement",
"category": "Operations",
"maturity": {
"documentation": 1,
"ownership": 1,
"metrics": 0,
"automation": 0,
"consistency": 1,
"feedback_loop": 0,
},
"steps": [],
},
],
"team": {
"total_headcount": 85,
"annual_revenue_usd": 18000000,
"stage": "series_b",
"management_layers": 3,
"open_requisitions": 18,
"departments": [
{
"name": "Engineering",
"headcount": 32,
"managers": [
{"name": "VP Engineering", "direct_reports": 4, "manages_managers": True},
{"name": "Engineering Manager (Platform)", "direct_reports": 7, "manages_managers": False},
{"name": "Engineering Manager (Product)", "direct_reports": 8, "manages_managers": False},
{"name": "Engineering Manager (Infra)", "direct_reports": 9, "manages_managers": False},
],
},
{
"name": "Sales",
"headcount": 18,
"managers": [
{"name": "VP Sales", "direct_reports": 3, "manages_managers": True},
{"name": "Sales Manager (SMB)", "direct_reports": 6, "manages_managers": False},
{"name": "Sales Manager (Enterprise)", "direct_reports": 4, "manages_managers": False},
],
},
{
"name": "Customer Success",
"headcount": 12,
"managers": [
{"name": "VP CS", "direct_reports": 2, "manages_managers": False},
],
},
{
"name": "Marketing",
"headcount": 8,
"managers": [
{"name": "VP Marketing", "direct_reports": 7, "manages_managers": False},
],
},
{
"name": "Operations",
"headcount": 6,
"managers": [
{"name": "COO", "direct_reports": 5, "manages_managers": True},
],
},
{
"name": "Product",
"headcount": 9,
"managers": [
{"name": "VP Product", "direct_reports": 8, "manages_managers": False},
],
},
],
},
}
if __name__ == "__main__":
main()
Hỗ trợ tạo khách hàng tiềm năng, tối ưu chuyển đổi và triển khai chiến dịch thu hút khách hàng đa kênh.
---
name: cs-demand-gen-specialist
description: Demand generation and customer acquisition specialist for lead generation, conversion optimization, and multi-channel acquisition campaigns
skills: marketing-skill/marketing-demand-acquisition
domain: marketing
model: sonnet
tools: [Read, Write, Bash, Grep, Glob]
---
# Demand Generation Specialist Agent
## Purpose
The cs-demand-gen-specialist agent is a specialized marketing agent focused on demand generation, lead acquisition, and conversion optimization. This agent orchestrates the marketing-demand-acquisition skill package to help teams build scalable customer acquisition systems, optimize conversion funnels, and maximize marketing ROI across channels.
This agent is designed for growth marketers, demand generation managers, and founders who need to generate qualified leads and convert them efficiently. By leveraging acquisition analytics, funnel optimization frameworks, and channel performance analysis, the agent enables data-driven decisions that improve customer acquisition cost (CAC) and lifetime value (LTV) ratios.
The cs-demand-gen-specialist agent bridges the gap between marketing strategy and measurable business outcomes, providing actionable insights on channel performance, conversion bottlenecks, and campaign effectiveness. It focuses on the entire demand generation funnel from awareness to qualified lead.
## Skill Integration
**Skill Location:** `../../marketing-skill/marketing-demand-acquisition/`
### Python Tools
1. **CAC Calculator**
- **Purpose:** Calculates Customer Acquisition Cost (CAC) across channels and campaigns
- **Path:** `../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py`
- **Usage:** `python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py campaign-spend.csv customer-data.csv`
- **Features:** CAC calculation by channel, LTV:CAC ratio, payback period analysis, ROI metrics
- **Use Cases:** Budget allocation, channel performance evaluation, campaign ROI analysis
**Note:** Additional tools (demand_gen_analyzer.py, funnel_optimizer.py) planned for future releases per marketing roadmap.
### Knowledge Bases
1. **Attribution Guide**
- **Location:** `../../marketing-skill/marketing-demand-acquisition/references/attribution-guide.md`
- **Content:** Marketing attribution models, channel attribution, ROI measurement frameworks
- **Use Case:** Campaign attribution, channel performance analysis, budget justification
2. **Campaign Templates**
- **Location:** `../../marketing-skill/marketing-demand-acquisition/references/campaign-templates.md`
- **Content:** Reusable campaign structures, launch checklists, multi-channel campaign blueprints
- **Use Case:** Campaign planning, rapid campaign setup, standardized launch processes
3. **HubSpot Workflows**
- **Location:** `../../marketing-skill/marketing-demand-acquisition/references/hubspot-workflows.md`
- **Content:** HubSpot automation workflows, lead nurturing sequences, CRM integration patterns
- **Use Case:** Marketing automation, lead scoring, nurture campaign setup
4. **International Playbooks**
- **Location:** `../../marketing-skill/marketing-demand-acquisition/references/international-playbooks.md`
- **Content:** International market expansion strategies, localization best practices, regional channel optimization
- **Use Case:** Global campaign planning, market entry strategy, cross-border demand generation
### Templates
No asset templates currently available — use campaign-templates.md reference for campaign structure guidance.
## Workflows
### Workflow 1: Multi-Channel Acquisition Campaign Launch
**Goal:** Plan and launch demand generation campaign across multiple acquisition channels
**Steps:**
1. **Define Campaign Goals** - Set targets for leads, MQLs, SQLs, conversion rates
2. **Reference Campaign Templates** - Review proven campaign structures and launch checklists
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/campaign-templates.md
```
3. **Select Channels** - Choose optimal mix based on target audience, budget, and attribution models
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/attribution-guide.md
```
4. **Set Up Automation** - Configure HubSpot workflows for lead nurturing
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/hubspot-workflows.md
```
5. **Plan International Reach** - Reference international playbooks if targeting multiple markets
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/international-playbooks.md
```
6. **Launch and Monitor** - Deploy campaigns, track metrics, collect data
**Expected Output:** Structured campaign plan with channel strategy, budget allocation, success metrics
**Time Estimate:** 4-6 hours for campaign planning and setup
### Workflow 2: Conversion Funnel Analysis & Optimization
**Goal:** Identify and fix conversion bottlenecks in acquisition funnel
**Steps:**
1. **Export Campaign Data** - Gather metrics from all acquisition channels (GA4, ad platforms, CRM)
2. **Calculate Channel CAC** - Run CAC calculator to analyze cost efficiency
```bash
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py campaign-spend.csv conversions.csv
```
3. **Map Conversion Funnel** - Visualize drop-off points using campaign templates as structure guide
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/campaign-templates.md
```
4. **Identify Bottlenecks** - Analyze conversion rates at each funnel stage:
- Awareness → Interest (CTR)
- Interest → Consideration (landing page conversion)
- Consideration → Intent (form completion)
- Intent → Purchase/MQL (qualification rate)
5. **Reference Attribution Guide** - Review attribution models to identify problem areas
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/attribution-guide.md
```
6. **Implement A/B Tests** - Test hypotheses for improvement
7. **Re-calculate CAC Post-Optimization** - Measure cost efficiency improvements
```bash
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py post-optimization-spend.csv post-optimization-conversions.csv
```
**Expected Output:** 15-30% reduction in CAC and improved LTV:CAC ratio
**Time Estimate:** 6-8 hours for analysis and optimization planning
**Example:**
```bash
# Complete CAC analysis workflow
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py q3-spend.csv q3-conversions.csv > cac-report.txt
cat cac-report.txt
# Review metrics and optimize high-CAC channels
```
### Workflow 3: Channel Performance Benchmarking
**Goal:** Evaluate and compare performance across acquisition channels to optimize budget allocation
**Steps:**
1. **Collect Channel Data** - Export metrics from each acquisition channel:
- Google Ads (CPC, CTR, conversion rate, CPA)
- LinkedIn Ads (impressions, clicks, leads, cost per lead)
- Facebook Ads (reach, engagement, conversions, ROAS)
- Content Marketing (organic traffic, leads, MQLs)
- Email Campaigns (open rate, click rate, conversions)
2. **Run CAC Comparison** - Calculate and compare CAC across all channels
```bash
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py channel-spend.csv channel-conversions.csv
```
3. **Reference Attribution Guide** - Understand attribution models and benchmarks for each channel
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/attribution-guide.md
```
4. **Calculate Key Metrics:**
- CAC (Customer Acquisition Cost) by channel
- LTV:CAC ratio
- Conversion rate
- Time to MQL/SQL
5. **Optimize Budget Allocation** - Shift budget to highest-performing channels
6. **Document Learnings** - Create playbook for future campaigns
**Expected Output:** Data-driven budget reallocation plan with projected ROI improvement
**Time Estimate:** 3-4 hours for comprehensive channel analysis
### Workflow 4: Lead Magnet Campaign Development
**Goal:** Create and launch lead magnet campaign to capture high-quality leads
**Steps:**
1. **Define Lead Magnet** - Choose format: ebook, webinar, template, assessment, free trial
2. **Reference Campaign Templates** - Review lead capture and campaign structure best practices
```bash
cat ../../marketing-skill/marketing-demand-acquisition/references/campaign-templates.md
```
3. **Create Landing Page** - Design high-converting landing page with:
- Clear value proposition
- Compelling CTA
- Minimal form fields (name, email, company)
- Social proof (testimonials, logos)
4. **Set Up Campaign Tracking** - Configure analytics and attribution
5. **Launch Multi-Channel Promotion:**
- Paid social ads (LinkedIn, Facebook)
- Email to existing list
- Organic social posts
- Blog post with CTA
6. **Monitor and Optimize** - Track CAC and conversion metrics
```bash
# Weekly CAC analysis
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py lead-magnet-spend.csv lead-magnet-conversions.csv
```
**Expected Output:** Lead magnet campaign generating 100-500 leads with 25-40% conversion rate
**Time Estimate:** 8-12 hours for development and launch
## Integration Examples
### Example 1: Automated Campaign Performance Dashboard
```bash
#!/bin/bash
# campaign-dashboard.sh - Daily campaign performance summary
DATE=$(date +%Y-%m-%d)
echo "📊 Demand Gen Dashboard - $DATE"
echo "========================================"
# Calculate yesterday's CAC by channel
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py \
daily-spend.csv daily-conversions.csv
echo ""
echo "💰 Budget Status:"
cat budget-tracking.txt
echo ""
echo "🎯 Today's Priorities:"
cat optimization-priorities.txt
```
### Example 2: Weekly Channel Performance Report
```bash
# Generate weekly CAC report for stakeholders
python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py \
weekly-spend.csv weekly-conversions.csv > weekly-cac-report.txt
# Email to stakeholders
echo "Weekly CAC analysis report attached." | \
mail -s "Weekly CAC Report" -a weekly-cac-report.txt stakeholders@company.com
```
### Example 3: Real-Time Funnel Monitoring
```bash
# Monitor CAC in real-time (run daily via cron)
CAC_RESULT=$(python ../../marketing-skill/marketing-demand-acquisition/scripts/calculate_cac.py \
daily-spend.csv daily-conversions.csv | grep "Average CAC" | awk '{print $3}')
CAC_THRESHOLD=50
# Alert if CAC exceeds threshold
if (( $(echo "$CAC_RESULT > $CAC_THRESHOLD" | bc -l) )); then
echo "🚨 Alert: CAC ($CAC_RESULT) exceeds threshold ($CAC_THRESHOLD)!" | \
mail -s "CAC Alert" demand-gen-team@company.com
fi
```
## Success Metrics
**Acquisition Metrics:**
- **Lead Volume:** 20-30% month-over-month growth
- **MQL Conversion Rate:** 15-25% of total leads qualify as MQLs
- **CAC (Customer Acquisition Cost):** Decrease by 15-20% with optimization
- **LTV:CAC Ratio:** Maintain 3:1 or higher ratio
**Channel Performance:**
- **Paid Search:** CTR 3-5%, conversion rate 5-10%
- **Paid Social:** CTR 1-2%, CPL (cost per lead) benchmarked by industry
- **Content Marketing:** 30-40% of organic traffic converts to leads
- **Email Campaigns:** Open rate 20-30%, click rate 3-5%, conversion rate 2-5%
**Funnel Optimization:**
- **Landing Page Conversion:** 25-40% conversion rate on optimized pages
- **Form Completion:** 60-80% of visitors who start form complete it
- **Lead Quality:** 40-50% of MQLs convert to SQLs
**Business Impact:**
- **Pipeline Contribution:** Demand gen accounts for 50-70% of sales pipeline
- **Revenue Attribution:** Track $X in closed-won revenue to demand gen campaigns
- **Payback Period:** CAC recovered within 6-12 months
## Related Agents
- [cs-content-creator](cs-content-creator.md) - Content creation for demand gen campaigns
- cs-product-marketing - Product positioning and messaging (planned)
- cs-growth-marketer - Growth hacking and viral acquisition (planned)
## References
- **Skill Documentation:** [../../marketing-skill/marketing-demand-acquisition/SKILL.md](../../marketing-skill/marketing-demand-acquisition/SKILL.md)
- **Marketing Domain Guide:** [../../marketing-skill/CLAUDE.md](../../marketing-skill/CLAUDE.md)
- **Agent Development Guide:** [../CLAUDE.md](../CLAUDE.md)
- **Marketing Roadmap:** [../../marketing-skill/marketing_skills_roadmap.md](../../marketing-skill/marketing_skills_roadmap.md)
---
**Last Updated:** November 5, 2025
**Sprint:** sprint-11-05-2025 (Day 2)
**Status:** Production Ready
**Version:** 1.0