project-memory
Substrat de mémoire structurée par mission, à 3 couches (Cold / Warm / Hot). Colonne vertébrale d'une mission de conseil : garantit que les décisions humaines (golden data) ne sont jamais écrasées par une régénération IA, mutualise la mémoire entre tous les agents/skills d'une mission, et rend la pensée auditable.
Ce skill est LLM-driven : tu exécutes chaque opération toi-même via Read / Write / Edit sur des fichiers .md. Il n'y a pas de moteur Python. La fiabilité du substrat dépend entièrement de ta discipline à suivre les gestes ci-dessous dans l'ordre.
Ce skill est le moteur ; il est en général invoqué par project-init (à l'init) ou par un agent métier (en cours de mission). Le point d'entrée du cycle de vie d'un projet est project-init, pas ce skill.
Règles dures (jamais d'exception)
- Immuabilité Cold. Ne jamais éditer le corps d'une décision au statut
Active. Le seul Edit in-place autorisé sur un fichier Décisions/ est le flip de statut dans le frontmatter (Active -> Révisée ou Abrogée, avec mise à jour de Révisé par), exécuté exclusivement par revise_decision ou abrogate_decision. Tout autre Edit d'une décision Active est une corruption du substrat.
- Index après chaque écriture. Après TOUTE écriture dans
Décisions/, Synthèses/ ou Logs/, régénérer immédiatement l'_Index.md du dossier touché, puis le _memory/_Index.md racine. C'est une étape à part entière, jamais omise.
- Frontmatter conforme avant Write. Vérifier le frontmatter contre
references/frontmatter-standards.md avant chaque Write. Champ obligatoire manquant ou valeur énumérée invalide : corriger d'abord, ne pas persister un fichier non conforme.
- Append-only Hot. Un log = un nouveau fichier. Jamais d'Edit d'un log existant.
Référentiels (lire au besoin, progressive disclosure)
references/memory-structure.md : doctrine des 3 couches, règle de routage, structure de dossier.
references/frontmatter-standards.md : les 4 frontmatters + règle de validation avant écriture.
references/templates/ : canevas de contenu (decision, synthesis, log, index).
references/claude-md-per-scope.md : template du CLAUDE.md déposé dans chaque _memory/.
references/config.example.md : domaines de décision, jalons, schéma context.md, politique de purge, locale. À lire pour toute opération qui touche un Domaine ou un Jalon.
references/operator-cadences.md : détail des routines lint_memory / operator_run et du modèle à 3 cadences. À lire avant d'exécuter ou de programmer une routine.
Le SKILL.md reste générique : les valeurs métier (domaines, jalons) vivent dans config.example.md.
Opérations
Chaque opération est une séquence de gestes ordonnés. Exécuter dans l'ordre, sans sauter d'étape.
init_memory(id, locale, context_meta)
Crée la structure complète. Idempotent : si _memory/ existe déjà, ne rien casser (compléter ce qui manque seulement).
- Déterminer la racine : la racine du dossier projet courant (
<racine projet>/_memory/).
- Créer
_memory/ et les 3 sous-dossiers Décisions/, Synthèses/, Logs/.
- Lire
references/config.example.md pour le schéma context.md, les domaines et jalons.
- Écrire
context.md (frontmatter du schéma de config.example.md + corps : description courte). Substituer les context_meta fournis. Valider le frontmatter contre le schéma config (tous les champs présents, dates au format YYYY-MM-DD) avant Write.
- Écrire
_memory/CLAUDE.md depuis references/claude-md-per-scope.md, en substituant id / locale et en copiant les listes de domaines et jalons depuis config.example.md (le CLAUDE.md doit être autoportant).
- Écrire un
_Index.md vide (mais frontmatté) dans chacun des 3 sous-dossiers, puis le _memory/_Index.md racine (Scope: top).
- Proposer la programmation des routines de maintenance : si le contexte est Cowork, poser l'
AskUserQuestion de programmation (cf. references/operator-cadences.md, section Scheduling). Si Claude Code local : ne pas proposer de scheduling (les routines restent on-demand). Défaut si pas de réponse : maintenance manuelle, aucune routine programmée.
read_context(id)
- Read
context.md. Retourner les métadonnées (frontmatter + corps) à l'agent appelant.
read_active_decisions(id, domain=None)
Appel obligatoire pour tout agent avant modification d'un livrable. Chemin de sécurité : ne pas dépendre de l'_Index.md (qui peut être désynchronisé), scanner les fichiers directement.
- Lister tous les fichiers
.md de Décisions/ (hors _Index.md). Read le frontmatter de chacun.
- Filtrer ceux au statut
Active (et par domain si fourni). Read le corps complet de chaque décision Active.
- Retourner la liste structurée : slug, domaine, décision retenue, conséquences. C'est le contexte anti-écrasement.
create_decision(id, slug, domain, content, options=None, consequences=None)
- Lire
config.example.md : vérifier que domain est une valeur autorisée.
- Read
Décisions/_Index.md : si une décision Active existe déjà sur le même slug, REFUSER et rediriger vers revise_decision.
- Construire le fichier
YYYY-MM-DD-<slug>.md depuis templates/decision-template.md : frontmatter Statut: Active, Révise: "", Révisé par: "" ; corps Contexte / Options / Décision retenue / Conséquences (Décision et Conséquences obligatoires).
- Valider le frontmatter (règle dure 3). Write le fichier.
- Régénérer
Décisions/_Index.md puis _memory/_Index.md (règle dure 2).
- Logguer l'opération (
log_action).
revise_decision(id, old_decision_path, new_slug, new_content, ...)
Ne jamais éditer le corps de l'ancienne décision (règle dure 1).
- Read l'ancienne décision (
old_decision_path). Si son statut n'est pas Active : REFUSER l'opération et expliquer l'état actuel. Ne pas réviser une décision déjà Révisée ou Abrogée.
- Créer la nouvelle décision (
YYYY-MM-DD-<new_slug>.md, Statut: Active, Révise: <old_decision_path>). Write.
- Edit du frontmatter de l'ancienne uniquement :
Statut: Active -> Révisée, Révisé par: <chemin de la nouvelle>. Ne pas toucher au corps de l'ancienne.
- Valider les deux frontmatters. Régénérer
Décisions/_Index.md puis _memory/_Index.md.
- Logguer l'opération (
log_action).
abrogate_decision(id, old_decision_path, reason)
- Read l'ancienne décision. Si son statut n'est pas
Active : REFUSER et expliquer l'état actuel.
- Edit du frontmatter uniquement :
Statut -> Abrogée. Pas de Révisé par (pas de remplacement). Ne pas toucher au corps.
- Régénérer
Décisions/_Index.md puis _memory/_Index.md.
- Logguer l'opération avec
reason (log_action).
log_action(id, agent, skill, action_meta)
- Construire
YYYY-MM-DD-<slug-action>.md depuis templates/log-template.md (frontmatter Log + corps : Action / Inputs lus / Décisions actives consultées / Modifications / Sources / Checks / Sortie).
- Valider le frontmatter. Write (nouveau fichier, append-only, règle dure 4).
- Régénérer
Logs/_Index.md puis _memory/_Index.md.
create_synthesis(id, jalon, content)
- Lire
config.example.md : vérifier que jalon est autorisé.
- Construire
YYYY-MM-DD-<slug-jalon>.md depuis templates/synthesis-template.md. Valider le frontmatter. Write.
- Régénérer
Synthèses/_Index.md puis _memory/_Index.md.
- Logguer l'opération (
log_action).
update_synthesis(id, synthesis_path, content_delta)
Une synthèse est Warm (permanent évolutif), donc l'Edit in-place est autorisé ici (contrairement aux décisions Cold).
- Read la synthèse. Edit pour annoter/compléter avec
content_delta. Mettre à jour la Date si pertinent.
- Régénérer
Synthèses/_Index.md puis _memory/_Index.md.
- Logguer l'opération (
log_action).
read_synthesis(id, jalon=None)
- Read
Synthèses/_Index.md. Read la synthèse du jalon demandé, ou la plus récente si jalon=None. Retourner le contenu. Lecture seule.
read_logs(id, limit=N, agent=None)
Lecture seule de la couche Hot, pour reconstituer la trace d'un run ou préparer une synthèse de jalon.
- Read
Logs/_Index.md. Read les N logs les plus récents (ou filtrés par agent). Retourner la liste structurée.
purge_logs(id, threshold_days, aggregate_to=None)
- Lire la politique de purge dans
config.example.md.
- Identifier les logs au-delà du seuil. Avant suppression : si
aggregate_to est fourni (ou par défaut selon config), create_synthesis/update_synthesis pour condenser les logs anciens en une synthèse Warm.
- Supprimer les fichiers de log au-delà du seuil. Régénérer
Logs/_Index.md puis _memory/_Index.md.
- Logguer la purge (
log_action) : plage de dates supprimée, nombre de fichiers, chemin de la synthèse d'agrégation. Ce log est lui-même soumis à la purge future.
rebuild_indexes(id)
Utilitaire de récupération : régénère tous les index à partir du contenu réel des dossiers.
- Pour chaque sous-dossier, lister les fichiers
.md (hors _Index.md), lire leur frontmatter, reconstruire l'_Index.md (cf. templates/index-template.md).
- Reconstruire le
_memory/_Index.md racine (Scope: top) en agrégeant les trois.
lint_memory(id, mode=quick)
Health-check du substrat. Corrige automatiquement la dérive d'index (déterministe, sûr) ; tout le reste est une PROPOSITION, jamais une action structurante silencieuse.
Mode quick (défaut, ~30 s) :
- Dérive d'index : pour chaque sous-dossier (
Décisions/, Synthèses/, Logs/), comparer le compteur déclaré dans _Index.md au nombre réel de .md (hors _Index.md), et la liste indexée aux fichiers présents. Idem pour le _memory/_Index.md racine vs la somme des trois. Écart -> corriger via rebuild_indexes (c'est la seule auto-correction autorisée).
- Conformité frontmatter : valider chaque fichier contre
references/frontmatter-standards.md (champ obligatoire manquant, valeur énumérée invalide, date non YYYY-MM-DD). Non conforme -> signaler (ne pas réécrire le corps).
- Intégrité Cold : pour chaque décision, vérifier la cohérence des liens de statut (
Révise pointe vers un fichier existant ; une Révisée/Abrogée n'est pas restée Active ; Révisé par pointe vers une décision Active). Incohérence -> signaler.
- Liens cassés : tout
[[cible]] dont le fichier n'existe pas -> signaler.
Mode full (~quelques min) : quick +
5. Décisions Active contradictoires : repérer deux décisions Active du même Domaine qui se contredisent (signal de revise_decision/abrogate_decision à proposer).
6. Logs au-delà du seuil de purge (cf. config.example.md) non encore agrégés en synthèse -> proposer purge_logs avec agrégation.
7. Décisions Active orphelines : aucune synthèse ni log récent ne les mentionne (conviction possiblement périmée) -> proposer une revue.
Sortie : un rapport structuré (tableau : check / statut OK-Corrigé-À revoir / détail). Les corrections d'index appliquées sont listées. Tout le reste est une liste de propositions. Logguer le lint (log_action, action=lint).
operator_run(id, cadence=hebdo)
Passe de maintenance autonome sur le _memory/. Une invocation = un run = un rapport = stop. Pas de question en cours de run, pas de boucle.
Trois cadences (hebdo, dreams, jalon), détaillées dans references/operator-cadences.md. Lire ce référentiel avant d'exécuter. En résumé :
hebdo : heartbeat léger (lint full + check conviction + détection de proximité de jalon). Log court de propositions.
dreams : re-lecture froide profonde, produit une synthèse + propositions. Cadence mensuelle.
jalon : même passe profonde que dreams, déclenchée par l'arrivée à un jalon ; la synthèse porte le jalon correspondant.
Règle dure transverse : l'operator propose, l'humain dispose. Ne JAMAIS créer/réviser/abroger une décision ni écrire une synthèse de fond sans validation. Failure handling et idle-timeout : si une étape échoue ou n'avance pas, la logguer et continuer le run.
Routines de maintenance & programmation (HITL)
lint_memory et operator_run peuvent tourner à la demande, ou être programmés. La programmation passe par une question explicite à l'humain (l'agent appelant, en contexte interactif, porte l'AskUserQuestion ; ce skill ne programme jamais rien seul).
Quand poser la question : à la fin de init_memory (création d'un nouveau projet) en contexte Cowork uniquement, et sur demande explicite ("programme une routine", "planifie un lint").
Mécanisme et défauts : voir references/operator-cadences.md (section Scheduling). En Cowork, proposer hebdo (hebdo) + dreams (mensuel) via le mécanisme de routines Cowork ; jalon reste événementiel. En Claude Code local, pas de scheduling autonome pour l'instant (routines on-demand).
Principe : les routines produisent des propositions dans un log, jamais des actions structurantes silencieuses. Sortie 100 % dans le _memory/ du projet (logs + cascade d'index), aucune notification externe par défaut. Démarrer en manuel quelques cycles, basculer en planifié seulement après accord humain.
Concurrence
En cas de sous-agents concurrents, sérialiser les écritures (un agent finit son opération, index compris, avant qu'un autre n'écrive dans le même dossier). Un garde-fou .lock déterministe par dossier _memory/ peut être ajouté si une corruption d'index sous concurrence est observée ; il n'est pas dans le périmètre par défaut.
Discipline côté consommateurs
La discipline "lire les décisions Active AVANT toute modification de livrable" est portée par les agents/skills consommateurs, pas par ce skill. Ici, read_active_decisions se contente de fournir le contexte ; c'est l'agent appelant qui doit l'invoquer en premier.
Convention de logging : les opérations qui écrivent dans Décisions/ ou Synthèses/, ainsi que purge_logs, s'auto-logguent (dernière étape de leur séquence) pour l'auditabilité. Le logging de l'activité métier plus large (paragraphes touchés dans le livrable, sources mobilisées par une section) reste à la charge de l'agent appelant via log_action.
1---2name: project-memory3description: Moteur de mémoire structurée à 3 couches (Cold / Warm / Hot) pour une mission de conseil. À utiliser dès qu'un agent ou un skill doit lire ou persister de la mémoire projet avant de modifier un livrable. Se déclenche pour : initialiser le substrat de mémoire d'un projet (init_memory, appelé par project-init), lire les décisions actives AVANT de réécrire un livrable, acter une décision structurante (cadrage, méthodo, hypothèse, arbitrage client), écrire une synthèse de jalon, logguer un run IA, ou lancer une passe de maintenance ("lint", "health-check de la mémoire", "operator run", "heartbeat", "dreams", "vérifie la mémoire du projet", "synthèse de jalon"). Lire les décisions actives EN PREMIER avant d'écraser toute saisie humaine. Utilise ce skill chaque fois que la mémoire d'un projet doit être lue, écrite ou maintenue, même si l'utilisateur ne nomme pas explicitement le "substrat" ou la "mémoire".4---56# project-memory78Substrat de mémoire structurée par mission, à 3 couches (Cold / Warm / Hot). Colonne vertébrale d'une mission de conseil : garantit que les décisions humaines (golden data) ne sont jamais écrasées par une régénération IA, mutualise la mémoire entre tous les agents/skills d'une mission, et rend la pensée auditable.910Ce skill est **LLM-driven** : tu exécutes chaque opération toi-même via Read / Write / Edit sur des fichiers `.md`. Il n'y a pas de moteur Python. La fiabilité du substrat dépend entièrement de ta discipline à suivre les gestes ci-dessous dans l'ordre.1112Ce skill est le **moteur** ; il est en général invoqué par `project-init` (à l'init) ou par un agent métier (en cours de mission). Le point d'entrée du cycle de vie d'un projet est `project-init`, pas ce skill.1314## Règles dures (jamais d'exception)15161. **Immuabilité Cold.** Ne jamais éditer le **corps** d'une décision au statut `Active`. Le seul Edit in-place autorisé sur un fichier `Décisions/` est le flip de statut dans le frontmatter (Active -> Révisée ou Abrogée, avec mise à jour de `Révisé par`), exécuté exclusivement par `revise_decision` ou `abrogate_decision`. Tout autre Edit d'une décision Active est une corruption du substrat.172. **Index après chaque écriture.** Après TOUTE écriture dans `Décisions/`, `Synthèses/` ou `Logs/`, régénérer immédiatement l'`_Index.md` du dossier touché, puis le `_memory/_Index.md` racine. C'est une étape à part entière, jamais omise.183. **Frontmatter conforme avant Write.** Vérifier le frontmatter contre `references/frontmatter-standards.md` avant chaque Write. Champ obligatoire manquant ou valeur énumérée invalide : corriger d'abord, ne pas persister un fichier non conforme.194. **Append-only Hot.** Un log = un nouveau fichier. Jamais d'Edit d'un log existant.2021## Référentiels (lire au besoin, progressive disclosure)2223- `references/memory-structure.md` : doctrine des 3 couches, règle de routage, structure de dossier.24- `references/frontmatter-standards.md` : les 4 frontmatters + règle de validation avant écriture.25- `references/templates/` : canevas de contenu (decision, synthesis, log, index).26- `references/claude-md-per-scope.md` : template du `CLAUDE.md` déposé dans chaque `_memory/`.27- `references/config.example.md` : domaines de décision, jalons, schéma `context.md`, politique de purge, locale. **À lire pour toute opération qui touche un `Domaine` ou un `Jalon`.**28- `references/operator-cadences.md` : détail des routines `lint_memory` / `operator_run` et du modèle à 3 cadences. **À lire avant d'exécuter ou de programmer une routine.**2930Le SKILL.md reste générique : les valeurs métier (domaines, jalons) vivent dans `config.example.md`.3132## Opérations3334Chaque opération est une séquence de gestes ordonnés. Exécuter dans l'ordre, sans sauter d'étape.3536### init_memory(id, locale, context_meta)37Crée la structure complète. Idempotent : si `_memory/` existe déjà, ne rien casser (compléter ce qui manque seulement).381. Déterminer la racine : la racine du dossier projet courant (`<racine projet>/_memory/`).392. Créer `_memory/` et les 3 sous-dossiers `Décisions/`, `Synthèses/`, `Logs/`.403. Lire `references/config.example.md` pour le schéma `context.md`, les domaines et jalons.414. Écrire `context.md` (frontmatter du schéma de `config.example.md` + corps : description courte). Substituer les `context_meta` fournis. Valider le frontmatter contre le schéma config (tous les champs présents, dates au format `YYYY-MM-DD`) avant Write.425. Écrire `_memory/CLAUDE.md` depuis `references/claude-md-per-scope.md`, en substituant id / locale et en **copiant les listes de domaines et jalons** depuis config.example.md (le CLAUDE.md doit être autoportant).436. Écrire un `_Index.md` vide (mais frontmatté) dans chacun des 3 sous-dossiers, puis le `_memory/_Index.md` racine (Scope: top).447. **Proposer la programmation des routines de maintenance** : si le contexte est Cowork, poser l'`AskUserQuestion` de programmation (cf. `references/operator-cadences.md`, section Scheduling). Si Claude Code local : ne pas proposer de scheduling (les routines restent on-demand). Défaut si pas de réponse : maintenance manuelle, aucune routine programmée.4546### read_context(id)471. Read `context.md`. Retourner les métadonnées (frontmatter + corps) à l'agent appelant.4849### read_active_decisions(id, domain=None)50**Appel obligatoire pour tout agent avant modification d'un livrable.** Chemin de sécurité : ne pas dépendre de l'`_Index.md` (qui peut être désynchronisé), scanner les fichiers directement.511. Lister tous les fichiers `.md` de `Décisions/` (hors `_Index.md`). Read le frontmatter de chacun.522. Filtrer ceux au statut `Active` (et par `domain` si fourni). Read le corps complet de chaque décision Active.533. Retourner la liste structurée : slug, domaine, décision retenue, conséquences. C'est le contexte anti-écrasement.5455### create_decision(id, slug, domain, content, options=None, consequences=None)561. Lire `config.example.md` : vérifier que `domain` est une valeur autorisée.572. Read `Décisions/_Index.md` : si une décision **Active** existe déjà sur le même `slug`, REFUSER et rediriger vers `revise_decision`.583. Construire le fichier `YYYY-MM-DD-<slug>.md` depuis `templates/decision-template.md` : frontmatter `Statut: Active`, `Révise: ""`, `Révisé par: ""` ; corps Contexte / Options / Décision retenue / Conséquences (Décision et Conséquences obligatoires).594. Valider le frontmatter (règle dure 3). Write le fichier.605. **Régénérer `Décisions/_Index.md` puis `_memory/_Index.md`** (règle dure 2).616. Logguer l'opération (`log_action`).6263### revise_decision(id, old_decision_path, new_slug, new_content, ...)64Ne jamais éditer le corps de l'ancienne décision (règle dure 1).651. Read l'ancienne décision (`old_decision_path`). **Si son statut n'est pas `Active` : REFUSER l'opération et expliquer l'état actuel.** Ne pas réviser une décision déjà `Révisée` ou `Abrogée`.662. Créer la nouvelle décision (`YYYY-MM-DD-<new_slug>.md`, `Statut: Active`, `Révise: <old_decision_path>`). Write.673. **Edit du frontmatter de l'ancienne uniquement** : `Statut: Active` -> `Révisée`, `Révisé par: <chemin de la nouvelle>`. Ne pas toucher au corps de l'ancienne.684. Valider les deux frontmatters. Régénérer `Décisions/_Index.md` puis `_memory/_Index.md`.695. Logguer l'opération (`log_action`).7071### abrogate_decision(id, old_decision_path, reason)721. Read l'ancienne décision. **Si son statut n'est pas `Active` : REFUSER et expliquer l'état actuel.**732. **Edit du frontmatter uniquement** : `Statut` -> `Abrogée`. Pas de `Révisé par` (pas de remplacement). Ne pas toucher au corps.743. Régénérer `Décisions/_Index.md` puis `_memory/_Index.md`.754. Logguer l'opération avec `reason` (`log_action`).7677### log_action(id, agent, skill, action_meta)781. Construire `YYYY-MM-DD-<slug-action>.md` depuis `templates/log-template.md` (frontmatter Log + corps : Action / Inputs lus / Décisions actives consultées / Modifications / Sources / Checks / Sortie).792. Valider le frontmatter. Write (nouveau fichier, append-only, règle dure 4).803. Régénérer `Logs/_Index.md` puis `_memory/_Index.md`.8182### create_synthesis(id, jalon, content)831. Lire `config.example.md` : vérifier que `jalon` est autorisé.842. Construire `YYYY-MM-DD-<slug-jalon>.md` depuis `templates/synthesis-template.md`. Valider le frontmatter. Write.853. Régénérer `Synthèses/_Index.md` puis `_memory/_Index.md`.864. Logguer l'opération (`log_action`).8788### update_synthesis(id, synthesis_path, content_delta)89Une synthèse est Warm (permanent évolutif), donc l'Edit in-place est autorisé ici (contrairement aux décisions Cold).901. Read la synthèse. Edit pour annoter/compléter avec `content_delta`. Mettre à jour la `Date` si pertinent.912. Régénérer `Synthèses/_Index.md` puis `_memory/_Index.md`.923. Logguer l'opération (`log_action`).9394### read_synthesis(id, jalon=None)951. Read `Synthèses/_Index.md`. Read la synthèse du `jalon` demandé, ou la plus récente si `jalon=None`. Retourner le contenu. Lecture seule.9697### read_logs(id, limit=N, agent=None)98Lecture seule de la couche Hot, pour reconstituer la trace d'un run ou préparer une synthèse de jalon.991. Read `Logs/_Index.md`. Read les N logs les plus récents (ou filtrés par `agent`). Retourner la liste structurée.100101### purge_logs(id, threshold_days, aggregate_to=None)1021. Lire la politique de purge dans `config.example.md`.1032. Identifier les logs au-delà du seuil. **Avant suppression** : si `aggregate_to` est fourni (ou par défaut selon config), `create_synthesis`/`update_synthesis` pour condenser les logs anciens en une synthèse Warm.1043. Supprimer les fichiers de log au-delà du seuil. Régénérer `Logs/_Index.md` puis `_memory/_Index.md`.1054. Logguer la purge (`log_action`) : plage de dates supprimée, nombre de fichiers, chemin de la synthèse d'agrégation. Ce log est lui-même soumis à la purge future.106107### rebuild_indexes(id)108Utilitaire de récupération : régénère tous les index à partir du contenu réel des dossiers.1091. Pour chaque sous-dossier, lister les fichiers `.md` (hors `_Index.md`), lire leur frontmatter, reconstruire l'`_Index.md` (cf. `templates/index-template.md`).1102. Reconstruire le `_memory/_Index.md` racine (Scope: top) en agrégeant les trois.111112### lint_memory(id, mode=quick)113Health-check du substrat. **Corrige automatiquement la dérive d'index (déterministe, sûr) ; tout le reste est une PROPOSITION, jamais une action structurante silencieuse.**114115Mode `quick` (défaut, ~30 s) :1161. **Dérive d'index** : pour chaque sous-dossier (`Décisions/`, `Synthèses/`, `Logs/`), comparer le compteur déclaré dans `_Index.md` au nombre réel de `.md` (hors `_Index.md`), et la liste indexée aux fichiers présents. Idem pour le `_memory/_Index.md` racine vs la somme des trois. **Écart -> corriger via `rebuild_indexes`** (c'est la seule auto-correction autorisée).1172. **Conformité frontmatter** : valider chaque fichier contre `references/frontmatter-standards.md` (champ obligatoire manquant, valeur énumérée invalide, date non `YYYY-MM-DD`). Non conforme -> signaler (ne pas réécrire le corps).1183. **Intégrité Cold** : pour chaque décision, vérifier la cohérence des liens de statut (`Révise` pointe vers un fichier existant ; une `Révisée`/`Abrogée` n'est pas restée `Active` ; `Révisé par` pointe vers une décision `Active`). Incohérence -> signaler.1194. **Liens cassés** : tout `[[cible]]` dont le fichier n'existe pas -> signaler.120121Mode `full` (~quelques min) : quick +1225. **Décisions Active contradictoires** : repérer deux décisions `Active` du même `Domaine` qui se contredisent (signal de `revise_decision`/`abrogate_decision` à proposer).1236. **Logs au-delà du seuil de purge** (cf. `config.example.md`) non encore agrégés en synthèse -> proposer `purge_logs` avec agrégation.1247. **Décisions Active orphelines** : aucune synthèse ni log récent ne les mentionne (conviction possiblement périmée) -> proposer une revue.125126Sortie : un rapport structuré (tableau : check / statut OK-Corrigé-À revoir / détail). Les corrections d'index appliquées sont listées. Tout le reste est une liste de propositions. Logguer le lint (`log_action`, action=lint).127128### operator_run(id, cadence=hebdo)129Passe de maintenance autonome sur le `_memory/`. **Une invocation = un run = un rapport = stop.** Pas de question en cours de run, pas de boucle.130131Trois cadences (`hebdo`, `dreams`, `jalon`), détaillées dans `references/operator-cadences.md`. **Lire ce référentiel avant d'exécuter.** En résumé :132- `hebdo` : heartbeat léger (lint full + check conviction + détection de proximité de jalon). Log court de propositions.133- `dreams` : re-lecture froide profonde, produit une synthèse + propositions. Cadence mensuelle.134- `jalon` : même passe profonde que `dreams`, déclenchée par l'arrivée à un jalon ; la synthèse porte le jalon correspondant.135136Règle dure transverse : l'operator **propose**, l'humain dispose. Ne JAMAIS créer/réviser/abroger une décision ni écrire une synthèse de fond sans validation. Failure handling et idle-timeout : si une étape échoue ou n'avance pas, la logguer et continuer le run.137138## Routines de maintenance & programmation (HITL)139140`lint_memory` et `operator_run` peuvent tourner à la demande, ou être **programmés**. La programmation passe par une question explicite à l'humain (l'agent appelant, en contexte interactif, porte l'`AskUserQuestion` ; ce skill ne programme jamais rien seul).141142**Quand poser la question** : à la fin de `init_memory` (création d'un nouveau projet) **en contexte Cowork uniquement**, et sur demande explicite ("programme une routine", "planifie un lint").143144**Mécanisme et défauts** : voir `references/operator-cadences.md` (section Scheduling). En Cowork, proposer `hebdo` (hebdo) + `dreams` (mensuel) via le mécanisme de routines Cowork ; `jalon` reste événementiel. En Claude Code local, pas de scheduling autonome pour l'instant (routines on-demand).145146**Principe** : les routines produisent des **propositions dans un log**, jamais des actions structurantes silencieuses. Sortie 100 % dans le `_memory/` du projet (logs + cascade d'index), aucune notification externe par défaut. Démarrer en manuel quelques cycles, basculer en planifié seulement après accord humain.147148## Concurrence149150En cas de sous-agents concurrents, sérialiser les écritures (un agent finit son opération, index compris, avant qu'un autre n'écrive dans le même dossier). Un garde-fou `.lock` déterministe par dossier `_memory/` peut être ajouté si une corruption d'index sous concurrence est observée ; il n'est pas dans le périmètre par défaut.151152## Discipline côté consommateurs153154La discipline "lire les décisions Active AVANT toute modification de livrable" est portée par les agents/skills consommateurs, pas par ce skill. Ici, `read_active_decisions` se contente de fournir le contexte ; c'est l'agent appelant qui doit l'invoquer en premier.155156Convention de logging : les opérations qui écrivent dans `Décisions/` ou `Synthèses/`, ainsi que `purge_logs`, s'auto-logguent (dernière étape de leur séquence) pour l'auditabilité. Le logging de l'activité métier plus large (paragraphes touchés dans le livrable, sources mobilisées par une section) reste à la charge de l'agent appelant via `log_action`.