---
name: post-mortem
description: >
  Generate dual post-mortem reports (internal + external) from a production incident description.
  Produces two Notion-ready markdown files following Pysae's post-mortem template.
  Use when the user says /post-mortem, 'post mortem', 'post-mortem', 'rapport d'incident',
  'incident report', 'analyse d'incident', 'RCA', 'root cause analysis', 'on a eu un incident',
  'on a eu un souci en prod', 'incident de prod', or describes a production incident that needs
  formal documentation. Also trigger when the user mentions writing up an outage, downtime event,
  or service disruption for stakeholders.
argument-hint: "[--internal] [description of the incident, or nothing to start interactive mode]"
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
  - Write
  - Agent
  - AskUserQuestion
---

Generate post-mortem reports from a production incident, ready to paste into Notion.

**Par défaut** : génère uniquement la version **externe** (client-facing, transparente mais mesurée).
**Avec `--internal`** : génère les deux versions (externe + interne avec le détail technique complet).

L'utilisateur peut aussi demander les deux en cours de route ("génère aussi la version interne", "fais les deux versions").

## Required tools

- `glab`
- `atlas`

Run `pysae-ai-tools tools require <tools>` before starting; if it exits non-zero, abort and report the install command from stderr to the user.

## Workflow

### 0. Load project references

Load the project reference to understand the infrastructure, services, and deployment architecture:

!`cat $(find pysae_ai_tools/claude_plugin/skills/references -name "pysae-projects.md" 2>/dev/null || echo "references/pysae-projects.md")`

Use this reference throughout the report to:
- Correctly name services, deployments, and infrastructure components
- Understand the relationship between repositories, K8s deployments, and Datadog services
- Frame technical details accurately in the internal version

### 1. Collect incident information

If the user provides a description, extract what you can. Then ask for anything missing from this list:

- **Date and time** of the incident (start → end)
- **Services impacted** (which APIs, apps, or components)
- **Root cause** (what triggered the incident)
- **Timeline** (key timestamps: detection, first fix, full resolution, return to normal)
- **Impact** (who was affected, how many users/devices, what was degraded)
- **Actions taken** during the incident
- **Who was involved** (responsible person for chronology)

Don't ask everything at once — extract from context first, then ask only what's missing.

### 2. Explore the codebase (optional)

If the incident involves specific components (a service, an autoscaler config, a client app), ask the user:

> "L'incident mentionne [composant]. Tu veux que j'explore le code pour enrichir l'analyse technique ?"

If yes, use Agent subagents to explore the relevant code in parallel (architecture, config, protections in place, monitoring setup). This enriches the internal version only — the external version never contains technical internals.

### 2b. Pull Atlas-side timeline data (when the incident touches MongoDB)

If the incident description mentions slow queries, replication lag, a failover, an Atlas maintenance window, or any DB-side symptom, pull the cluster's recorded events to anchor the timeline:

```bash
# Cluster events around the incident window (failovers, maintenance, alerts)
atlas -P pysae-prod events list --since <START-1h> --until <END+1h> --output json

# Open and recently-resolved alerts that overlap the incident
atlas -P pysae-prod alerts list --output json
```

Cite the matching events with their Atlas-side timestamps in the **internal** timeline. Never expose Atlas event types verbatim in the external version — translate to neutral language (see "External version — how to frame things" below).

### 3. Generate documents

Write files in the current working directory:

- **Default** : `post-mortem-YYYY-MM-DD-external.md` only → follow [references/template-external.md](references/template-external.md)
- **With `--internal`** : also generate `post-mortem-YYYY-MM-DD-internal.md` → follow [references/template-internal.md](references/template-internal.md)

### 4. Present and iterate

After generating, tell the user both files are ready and ask if they want to adjust anything. Common adjustments include:
- Reframing the interruption window (e.g., separating total outage from degradation)
- Softening or removing details from the external version
- Adding/removing actions from the plan
- Changing column structure in tables

## Critical rules

### Tone and content
- **Langue française** : respecter les [règles de rédaction en français](../references/french-writing-rules.md) pour tout texte généré
- **Blameless**: analyze the system that allowed the error, never blame a person. Use "erreur de manipulation" rather than "fat finger" in external docs.
- **Factual**: no excessive apologies, no corporate fluff. State what happened, what was done, what will change.
- **Data loss**: never affirm "aucune perte de données" — use "nos vérifications n'ont pas mis en évidence de perte de données significative" unless you have proof of zero loss.

### External version — what to NEVER include
- Internal technical terms: MongoDB, Atlas, pods, replicas, NDP, KEDA, HPA, nginx, WebSocket, Redis, EKS, Kubernetes
- Details about environment isolation (dev/prod separation, "se tromper de ligne")
- Specific scaling numbers (800 replicas, 300 maxReplicas)
- Internal monitoring gaps or tooling weaknesses
- Names of team members
- Anything that would make a client question infrastructure maturity

### External version — how to frame things
- Root cause: "erreur de configuration lors d'une opération d'administration sur notre infrastructure de base de données" (honest without exposing internals)
- Multiple config errors: "l'erreur comportait deux volets, dont le second n'a été identifié qu'après correction du premier"
- Thundering herd: "la reconnexion simultanée de l'ensemble des [nom produit client] a provoqué un pic de charge"
- Scaling: "renforcement de notre infrastructure" / "montée en capacité"
- Guard-fous: "les garde-fous en place étaient insuffisants pour prévenir ce type d'erreur"

### Markdown / Notion compatibility
- `# H1` = page title only (one per document)
- `## H2` = section headings (Contexte, Chronologie, Causes racines, etc.)
- `### H3` = sub-sections within Causes racines
- Metadata lines (Sévérité, Durée, etc.) separated by blank lines so Notion renders them as separate blocks
- Tables use standard markdown pipe syntax
- No HTML tags

## Gotchas

- **Chronologie cohérente entre versions** : si la version interne dit "correction complète à 18h20", la version externe ne peut pas dire "corrigé à 16h00". Les horaires doivent être cohérents même si le niveau de détail diffère. Reformuler en "dégradation partielle" plutôt que mentir sur l'heure de correction.
- **Ne jamais affirmer "aucune perte de données"** : si l'outage a duré plus de 10 minutes, des events côté client ont pu expirer (TTL côté buffer). Toujours utiliser la formulation prudente ("nos vérifications n'ont pas mis en évidence...").
- **Attention aux formulations qui exposent l'isolation des environnements** : "opération de maintenance sur un environnement de développement qui a impacté la production" → le client conclut immédiatement que dev et prod ne sont pas séparés. Préférer : "erreur de configuration lors d'une opération d'administration sur notre infrastructure".
- **Le plan d'actions externe est un sous-ensemble filtré de l'interne** : ne pas inventer d'actions dans la version externe qui n'existent pas en interne, et retirer les colonnes Owner/Statut.
- **Metadata Notion** : chaque ligne de metadata (Sévérité, Durée, Rédacteur, Date) doit être séparée par une ligne vide, sinon Notion les fusionne en un seul paragraphe.
- **Le "renforcement des garde-fous" ne doit pas sous-entendre "cloisonnement des environnements"** : les clients interprètent "cloisonnement renforcé" comme "c'était pas cloisonné avant". Rester sur "garde-fous sur les opérations sensibles".

## Exemple

Voici comment une même information est traitée dans les deux versions :

**Input utilisateur** :
> "On a eu un incident hier, un dev a changé le mdp MongoDB prod par erreur en pensant modifier le dev. Les 1500 devices ont bufferisé 10 min d'events et tout dépilé d'un coup à la reprise."

**Version INTERNE — Contexte** :
```
Le 20 mars 2026 à 15h10, une modification accidentelle du mot de passe
et du rôle du compte de service MongoDB de production a provoqué une
indisponibilité totale de toutes les APIs dépendantes de MongoDB.
```

**Version EXTERNE — Contexte** :
```
Le 20 mars 2026 à 15h10, une erreur de configuration lors d'une opération
d'administration sur notre infrastructure de base de données a provoqué
une indisponibilité du suivi temps réel des véhicules.
```

**Version INTERNE — Cause racine** :
```
### 1. Erreur humaine — fat finger sur Atlas (cause déclenchante)

Deux modifications ont été appliquées involontairement au compte de
service prod :
- Changement du mot de passe
- Changement du rôle → read-only

**Facteurs contributifs :**
- L'interface Atlas ne distingue pas visuellement les environnements
- Les comptes sont gérés manuellement via l'UI, sans filet IaC
```

**Version EXTERNE — Cause racine** :
```
### Erreur de configuration (cause déclenchante)

Une opération d'administration sur notre infrastructure de base de données
a entraîné une modification accidentelle de la configuration de production.
L'erreur comportait deux volets, dont le second n'a été identifié qu'après
correction du premier, prolongeant la durée de l'interruption.

**Facteurs contributifs :**
- L'opération a été réalisée manuellement, sans passer par un processus
  de validation automatisé (Infrastructure as Code)
- Les garde-fous en place étaient insuffisants pour prévenir ce type d'erreur
```
