# Assistant V2.1 ObsiGate — Phase 0 : Socle sûr (purge, mémoire, politiques, exécution fiable) | Champ | Valeur | |---|---| | Phase | **0 sur 5** — fondation de toute la solution | | Document parent | `ASSISTANT-V2.1.md` — en particulier §2 (P1–P16), §5, §9, §10, §15, §16, §19 | | Version | 1.0 — 9 octobre 2026 | | Auteur | Spark, pour Bruno | | Statut | Prêt à implémenter | | Tranches | **#191** (purge Ollama), **#192** (mémoire socle amendée), **#193** (miroir markdown), **#213** (politiques & taint), **#206** (exécution fiable), amorce de **#212** (harnais golden tasks) | | Effort estimé | 15–19 jours (dont 1–2 j d'amorce #212 ; le solde de #212 est continu, phases 1–5) | | Prérequis | ObsiGate actuel : boucle agent `backend/agent/loop.py`, registre `backend/tools/registry.py`, scheduler #170, notifications #168, Web Push #67, recherche #70 — tels que décrits dans l'inventaire V2.1 §4 | | Dépendances | Aucune (première phase) | | Débloque | Phase 1 (tâches et planification s'appuient sur les runs et la mémoire), et toutes les écritures externes ultérieures (#213/#206 sont le prérequis de sécurité des phases 3–4) | > **Résultat visible à la fin de cette phase.** Le conteneur Ollama a disparu. L'assistant possède une mémoire long terme : il enregistre des faits (avec historique bi-temporel), des entités (personnes, projets, lieux) et des procédures, les montre dans `99_Assistant/Profil.md` — éditable à la main, les éditions étant reprises comme des faits de confiance maximale — et les injecte dans chaque conversation via un compileur de contexte dont chaque section cite son origine. Surtout, **tout ce que l'assistant exécute devient un run persistant** : plan affiché avant les écritures, approbation par run, étapes journalisées avec preuves de post-condition, reprise sans doublon après interruption, annulation quand l'inverse existe. Et un moteur de politiques déterministe décide ce qui est autorisé, approuvé ou refusé — jamais le modèle. --- ## Table des matières 1. [Objectif et principe directeur](#1-objectif-et-principe-directeur) 2. [Périmètre](#2-périmètre) 3. [État d'entrée — ce qui existe](#3-état-dentrée--ce-qui-existe) 4. [Modèle de données](#4-modèle-de-données) 5. [Tickets de travail](#5-tickets-de-travail) 6. [API livrée par la phase](#6-api-livrée-par-la-phase) 7. [Comportements détaillés](#7-comportements-détaillés) 8. [Tests et golden tasks](#8-tests-et-golden-tasks) 9. [Critères d'acceptation de la phase](#9-critères-dacceptation-de-la-phase) 10. [Risques spécifiques et vigilance](#10-risques-spécifiques-et-vigilance) 11. [Ordre d'exécution](#11-ordre-dexécution) 12. [Définition de « terminé »](#12-définition-de--terminé-) --- ## 1. Objectif et principe directeur Le principe : **on ne donne pas plus de pouvoir à l'assistant avant d'avoir rendu son pouvoir actuel sûr, traçable et réversible.** La V2 livrait la mémoire puis les connecteurs ; la V2.1 intercale, dès la phase 0, les deux mécanismes qui rendent toutes les phases suivantes délégables : le **moteur de politiques** (#213 — qui a le droit de faire quoi, avec quelles données, venues d'où) et l'**exécution fiable** (#206 — plan, preuves, reprise, annulation). Corollaires qui guident chaque ticket : - **La mémoire est un index du vault, pas un silo.** Faits confirmés → miroir markdown ; la base ne détient en propre que les états de travail (`pending`, historique de runs). - **Un run est l'unité de tout.** Conversation, tâche planifiée (phase 2), automatisation (phase 2), MCP : à la fin de la phase, toute exécution d'outils par un agent produit une ligne `agent_runs` et ses `agent_steps`. Les journaux épars d'aujourd'hui convergent là. - **La politique est déterministe.** Risque du registre × niveau d'autonomie × provenance × sensibilité × réversibilité → décision. Aucun appel LLM dans le chemin d'autorisation, jamais. - **Pas de succès sans preuve.** Un run n'est `succeeded` que si ses post-conditions vérifiables sont vraies (§7.3). ## 2. Périmètre ### 2.1 Inclus - #191 : retrait du service/volume Ollama des trois compose, défauts provider nettoyés, notes de migration (repris tel quel de la V2 §9). - #192 : `backend/memory/` — store SQLite amendé (faits bi-temporels, sensibilité, provenance, procédures), entités et relations, recall et **compileur de contexte** (§9.4 du parent), outils `memory.*`, `entity_resolve`, `procedure_get`, API mémoire, cartes de validation des faits `pending` (forme simple — la file unifiée arrive en phase 1, #203). - #193 : `mirror.py`, dossier `99_Assistant/`, `Profil.md` à balises gérées avec re-parse des éditions humaines, `Journal.md` des consolidations, `Personnes.md` en **coquille** (le peuplement riche est en phase 4, #211). - #213 : provenance/taint sur tous les contenus entrant dans un contexte ou un run, moteur de politiques `backend/agent/policies.py` évalué avant chaque appel d'outil, règles du §15.2 du parent, journal des refus, tests d'injection. - #206 : plans d'exécution, `agent_runs`/`agent_steps` dans `data/assistant.sqlite3`, idempotence et reprise, post-conditions déclarées dans le registre (`verify`), inverses (`inverse`), niveaux d'autonomie 0–3 et délégations bornées datées, API runs + progression SSE. - #212 (amorce) : harnais de golden tasks (`tests/golden/`, fixtures de vault, connecteurs simulés) et les scénarios G3, G6, G7 de la phase. ### 2.2 Exclu (phases ultérieures) - La **consolidation nocturne** (#194) : la phase 0 livre le store, le recall et la création de faits en conversation ; l'extraction automatique nocturne arrive en phase 2, quand `agent_prompt` (#200) existe. - La **vue Aujourd'hui**, la file d'approbations unifiée et le centre de contrôle complet (#203, phase 1) : la phase 0 livre les cartes mémoire simples et une liste de runs basique dans les Configurations. - Les **tâches** (#202, phase 1) et tout connecteur (#195+, phase 3). - La politique « contenu connecteur » est livrée comme **mécanisme** (provenances `connector:` reconnues) ; son premier usage réel est en phase 3. ## 3. État d'entrée — ce qui existe | Élément | État | Rôle en phase 0 | |---|---|---| | Boucle agent + tool calling natif | ✅ `backend/agent/loop.py`, `backend/ai_chat.py` | Moteur des runs ; étendu, pas remplacé (P2) | | Registre `@tool` (risque/scope/confirmation/audit/rate-limit) | ✅ `backend/tools/registry.py` | Reçoit les champs `verify` et la provenance ; la politique s'y branche | | Historique de conversation persistant | ✅ #95, `backend/ai_history.py` | Mémoire épisodique brute (source future de #194) | | Recherche TF-IDF + sémantique RRF | ✅ #70 | Recall : fusion faits + recherche | | Cache SQLite (patron) | ✅ `backend/tools/webcache.py` | Modèle des stores SQLite de la phase | | Audit + redaction des secrets | ✅ `backend/audit.py`, `secret_redactor.py` | Journal des runs et des refus ; args toujours redactés | | Providers LLM multi-fournisseurs | ✅ `backend/ai.py` | Routage par type de job : amorce posée (§16.3 du parent), table complète en phases suivantes | | Ollama comme conteneur | ✅ présent | **Retiré** par #191 ; le provider `ollama` reste une option de configuration (desktop local) | ## 4. Modèle de données Repris du parent : `facts` amendée (§9.2 — `entity_id`, `valid_from`, `valid_to`, `recorded_at`, `sensitivity`, `provenance_trust`, `kind` étendu à `procedure`), `entities` et `relations` (§9.3), `consolidation_runs` (créée dès cette phase, alimentée en phase 2), `agent_runs` et `agent_steps` (§10.2), auxquelles s'ajoute la table des délégations : ```sql CREATE TABLE delegations ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, domain TEXT NOT NULL, -- 'vault'|'tasks'|'email'|'calendar'|… level INTEGER NOT NULL, -- niveau accordé (0–3, §10.4 du parent) scope_json TEXT, -- périmètre : chemins, connecteur, budgets granted_at TEXT NOT NULL, review_at TEXT NOT NULL, -- défaut +90 j status TEXT NOT NULL DEFAULT 'active' -- active|expired|revoked ); ``` Stores : `data/memory.sqlite3` (faits, entités, relations, runs de consolidation) et `data/assistant.sqlite3` (runs, steps, délégations ; recevra `inbox_items`, `commitments`, `approvals` en phases 1 et 4 — le fichier est créé ici, les tables arrivent avec leurs tranches). Règles transverses : toute table porte `user_id` ; aucun secret ni contenu brut de connecteur dans ces bases ; les args d'étapes sont stockés **redactés** ; les stores sont reconstructibles ou journalisés (jamais de contenu de Bruno irremplaçable hors du vault — P4). ## 5. Tickets de travail *Convention : chaque ticket est indépendamment testable ; « Fichiers » donne les points d'ancrage d'après la V2.1 — à confirmer contre le code réel au démarrage du ticket.* ### Purge Ollama — #191 **P0-T01 — Retrait du conteneur Ollama.** Fichiers : `docker-compose.yml`, `docker-compose.test-linux.yml`, `docker-compose.test-win.yml`, docs d'installation. Travail : supprimer service, volume `ollama_data`, variables `OLLAMA_BASE_URL`/`OLLAMA_MODEL` et mentions du port 11434 ; procédure de suppression du volume documentée dans le CHANGELOG. Acceptation : `docker compose config` ne connaît plus Ollama ; l'instance démarre et l'agent fonctionne sur deepseek/openrouter/gemini. **P0-T02 — Défauts provider nettoyés.** Fichiers : `backend/ai.py`, `model_capabilities.py`, tests d'isolation. Travail : conserver le provider `ollama` comme option explicite (desktop), retirer tout défaut pointant vers le réseau interne ; le mode par défaut de la mémoire fonctionne sans embeddings (TF-IDF + RRF + faits). Acceptation : aucun test ni défaut ne référence `http://ollama:11434` ; la recherche sémantique se dégrade proprement sans sentence-transformers. ### Mémoire socle — #192 **P0-T03 — Store mémoire : faits amendés, entités, relations.** Fichiers : nouveau `backend/memory/store.py` (patron `webcache.py`), création/ouverture de `data/memory.sqlite3`. Travail : DDL du §4 ; CRUD faits avec clôture bi-temporelle (supersede = `valid_to`, jamais d'écrasement) ; planchers de confiance V2 (< 0,7 → `pending`) ; dossiers sensibles configurables → `pending` + `sensitivity='sensitive'` ; renforcement `last_seen_at` et decay par `kind` (les `procedure` et `decision` ne décroissent pas). Acceptation : G7 passe (changement de dentiste : ancien fait clos, nouveau actif, requête historique datée correctement répondue) ; aucun fait `sensitive` créé directement en `confirmed`. **P0-T04 — Entités et résolution de noms.** Fichiers : `backend/memory/entities.py`. Travail : CRUD entités (person/place/project/org/topic, alias) ; `resolve(name)` → candidates scorées ; **ambiguïté = pas de fusion** (renvoyer les candidates, la décision est une carte, phase 2 pour la consolidation) ; relations bi-temporelles. Acceptation : deux « Marie » distinctes coexistent sans fusion ; une relation fermée n'apparaît plus dans le recall actuel mais reste interrogeable à date. **P0-T05 — Recall et compileur de contexte.** Fichiers : `backend/memory/recall.py`, `backend/memory/compiler.py`. Travail : score explicite et journalisé (RRF × confiance × fraîcheur × boost entité, parent §9.4) ; assemblage du bloc `` à budget adaptatif (défaut 2 500 tokens) avec sections profil/procédures, entités du sujet, faits liés, engagements (vide cette phase), dernier briefing (absent cette phase — section omise proprement) ; chaque section cite son origine ; le bloc est visible dans les étapes du panneau avec le détail du score au survol. Acceptation : un fait sous le seuil n'entre pas dans le bloc ; le même bloc est reproduit à l'identique pour la même requête et le même état (déterminisme de structure) ; aucun contenu `sensitivity='sensitive'` dans un contexte destiné à un outil externe. **P0-T06 — Outils mémoire et API.** Fichiers : `backend/tools/memory.py`, `backend/routers/memory.py`. Travail : les 5 outils V2 (`memory_recall`, `memory_save`, `memory_update`, `memory_forget`, `profile_get`) + `entity_resolve` (READ) et `procedure_get` (READ) ; `memory_save` passe par la politique (approbation selon niveau, défaut 2) ; endpoints CRUD faits (liste/filtre statut, validation `pending`, édition, oubli) et export JSON complet du domaine mémoire. Acceptation : un fait proposé en chat apparaît en carte, validé il est au miroir (T08) et au recall suivant ; `memory_forget` le retire du recall et du miroir, avec trace d'audit. ### Miroir markdown — #193 **P0-T07 — Miroir `Profil.md` à balises gérées.** Fichiers : `backend/memory/mirror.py`. Travail : création de `99_Assistant/` dans le vault mémoire (`OBSIGATE_MEMORY_VAULT`, mode multi-utilisateur du §5.3 du parent) ; rendu des sections gérées (préférences, procédures, objectifs connus) ; hash de section stocké en base ; écritures idempotentes (rendu deux fois = fichier identique). Acceptation : supprimer un fait validé régénère le miroir sans toucher au hors-balises ; deux rendus consécutifs produisent un diff vide. **P0-T08 — Re-parse des éditions humaines.** Travail : avant chaque écriture, comparer le hash stocké au contenu courant ; une section modifiée à la main est re-parsée en faits `source='user'`, confiance 1.0, `confirmed`, puis régénérée ; une suppression dans le miroir = fait `rejected` en base ; le hors-balises n'est jamais touché. Acceptation : éditer `Profil.md` à la main (ajout + suppression) puis déclencher un rendu donne des faits conformes aux éditions, sans perte du texte libre hors balises. **P0-T09 — `Personnes.md` (coquille) et `Journal.md`.** Travail : `Personnes.md` rendu depuis les entités personnes (nom, type de relation, dernière interaction connue) — en lecture structurée simple cette phase ; `Journal.md` alimenté par les événements mémoire (faits ajoutés/validés/rejetés, rendus du miroir) en lecture seule. Acceptation : une entité personne créée en T04 apparaît au miroir ; le journal trace chaque validation de carte. ### Politiques & taint — #213 **P0-T10 — Provenance de bout en bout.** Fichiers : `backend/agent/loop.py`, `backend/tools/registry.py`, `backend/ai_chat.py`. Travail : chaque contenu entrant dans un contexte ou un résultat d'outil reçoit une provenance (`user`, `vault`, `connector:`, `web`, `mcp:`, `automation`) portée dans les messages et les steps ; les résultats d'outils sont sanitisés (redaction existante) et étiquetés avant retour au modèle ; les prompts système distinguent explicitement blocs « instructions » et blocs « données ». Acceptation : un test d'intégration montre la provenance présente sur chaque résultat d'outil d'un run ; aucun résultat n'est injecté sans étiquette. **P0-T11 — Moteur de politiques.** Fichiers : nouveau `backend/agent/policies.py` ; branchement dans le registre (évaluation **avant** chaque appel d'outil). Travail : décision déterministe `autorisé | approbation_run | approbation_renforcée | refusé` = f(risque registre, niveau d'autonomie du domaine, provenance, sensibilité des données, réversibilité) ; règles du parent §15.2 (une instruction de contenu non-`user` ne crée/lève aucune approbation ; action externe justifiée uniquement par un contenu non-`user` → refus + carte ; données `private|sensitive` interdites vers web/connecteurs en écriture/MCP externe) ; journal des refus avec motif, lisible dans l'audit. Acceptation : G3 passe (courriel piégé simulé → refus, carte à Bruno, zéro appel d'envoi) ; la décision est couverte par des tests unitaires exhaustifs sur la matrice des facteurs (aucun LLM dans le chemin). **P0-T12 — Registre étendu : `verify`, inverses, sensibilité des paramètres.** Fichiers : `backend/tools/registry.py`, outils existants (annotations). Travail : champs optionnels du décorateur `@tool` : `verify` (post-condition vérifiable), `inverse` (constructeur d'inverse ou `None` explicite), `data_classes` (classes de données acceptées en entrée) ; annoter les outils vault et documents existants ; un outil d'écriture sans `verify` déclaré est listé dans un rapport de couverture (pas bloquant cette phase, bloquant pour les outils externes des phases 3+). Acceptation : le rapport de couverture existe et est revu ; `create_file`/`edit_file` déclarent leur post-condition et leur inverse (backup). ### Exécution fiable — #206 **P0-T13 — Stores de runs.** Fichiers : `backend/agent/runs.py`, `data/assistant.sqlite3`. Travail : DDL `agent_runs`/`agent_steps` du parent §10.2 ; cycle de vie complet des statuts ; écriture des steps au fil de l'exécution par la boucle existante (toute exécution d'outils crée ou rattache un run, `origin` renseignée) ; plafonds : itérations et budget tokens existants + durée murale et nombre d'écritures (`OBSIGATE_RUN_MAX_WALL_SECONDS`, `OBSIGATE_RUN_MAX_WRITES`). Acceptation : tuer le processus pendant un run laisse un run `running` orphelin détectable au redémarrage (marqué `paused` reprenable, jamais `succeeded`). **P0-T14 — Plans d'exécution et approbation par run.** Travail : pour toute demande ≥ 2 écritures ou 1 outil DANGEROUS, génération d'un plan (étapes : outil, args résumés, effet attendu, post-condition, inverse) persisté dans `plan_json` ; affichage dans le panneau avant la première écriture ; validation en un clic = approbation du run entier (pas par étape) ; un plan refusé n'exécute rien et le run passe `cancelled` avec motif. Acceptation : une demande multi-écritures ne produit aucun effet avant validation ; le plan affiché correspond exactement aux steps exécutés ensuite. **P0-T15 — Idempotence et reprise.** Travail : `idempotency_key` par step d'écriture (hash run+seq+args) respectée par les outils de création (vérification d'existence par clé en métadonnée) ; reprise d'un run interrompu à la première step non `done`, re-vérification des post-conditions incertaines, steps WRITE incertaines → `awaiting_approval` plutôt que rejeu aveugle. Acceptation : G6 passe (run tué à mi-parcours, repris : aucun doublon créé, état final vérifié). **P0-T16 — Vérification et annulation.** Travail : exécution des `verify` après chaque step d'écriture ; statut final `succeeded` seulement si toutes les post-conditions vérifiables sont vraies, sinon `partially_succeeded` détaillé ; « Annuler ce run » exécute les inverses sûrs en ordre décroissant comme un run lié ; absence d'inverse affichée comme telle (« non annulable »). Acceptation : un outil dont la post-condition échoue (fixture) produit `partially_succeeded`, jamais `succeeded` ; l'annulation d'un run de création de fichiers restaure l'état initial via les backups. **P0-T17 — Niveaux d'autonomie et délégations.** Fichiers : réglages Configurations, `delegations` (§4). Travail : niveaux 0–3 par domaine (défauts : vault = 2, tout domaine externe = 0/1 selon existence) ; création de délégation bornée (périmètre + budget + `review_at` +90 j) depuis une approbation (« toujours autoriser ce périmètre ») ou les Configurations ; expiration automatique → retour au niveau inférieur ; **aucun niveau ne couvre** paiements, envois externes sans relecture, suppressions définitives, changements de sécurité (codé en politique, pas en réglage). Acceptation : une délégation expirée cesse de s'appliquer sans intervention ; tenter de déléguer un envoi externe est refusé par l'UI et par l'API. **P0-T18 — API runs et progression.** Fichiers : `backend/routers/runs.py`. Travail : `GET /api/runs` (filtres statut/origine), `GET /api/runs/{id}` (plan, steps, preuves), actions `pause`/`resume`/`cancel`/`undo` ; progression en SSE sur le flux existant ; liste de runs basique dans les Configurations (le centre de contrôle complet est en phase 1). Acceptation : un run en cours est observable en direct ; pause puis reprise depuis l'API aboutit au même résultat qu'une exécution continue. ### Évaluation — amorce #212 **P0-T19 — Harnais golden tasks.** Fichiers : `tests/golden/` (fixtures de vault, connecteurs simulés, harnais d'exécution headless). Travail : infrastructure de scénarios rejouables en CI (état initial → demande → assertions sur les stores, le vault et les runs) ; livrer G3 (injection), G6 (reprise), G7 (bi-temporalité) ; gabarit documenté pour les phases suivantes (chaque phase ajoute les siens). Acceptation : les trois scénarios tournent en CI et échouent si le comportement régresse (démontré par mutation volontaire en développement). ### Finitions **P0-T20 — i18n, docs, guides.** Travail : clés FR/EN pour tout libellé nouveau (`ai.step.*` mémoire/runs/politiques, cartes, réglages d'autonomie) ; fiches `docs/features/` pour #191, #192/#193, #213, #206 ; guide utilisateur « Mémoire et contrôle de l'assistant » ; CHANGELOG + ROADMAP. Acceptation : DoD du §12 vérifiée point par point. ## 6. API livrée par la phase | Route | Rôle | Ticket | |---|---|---| | `GET/POST/PATCH /api/memory/facts` | CRUD faits, validation des `pending` | P0-T06 | | `GET /api/memory/entities` · `/api/memory/export` | Entités ; export du domaine mémoire | P0-T04/T06 | | `GET /api/runs` · `GET /api/runs/{id}` | Liste et détail (plan, steps, preuves) | P0-T18 | | `POST /api/runs/{id}/pause|resume|cancel|undo` | Pilotage d'un run | P0-T18 | | `GET/POST/DELETE /api/delegations` | Délégations bornées par domaine | P0-T17 | Toutes suivent l'authentification et les permissions par vault existantes ; les nouveaux outils `@tool` sont exposés au MCP automatiquement (scopes IN_APP+MCP, propose/apply déjà gérés). ## 7. Comportements détaillés ### 7.1 Qui peut faire quoi La mémoire, les runs et les délégations sont **par utilisateur** (`user_id` partout, parent §5.3). Un administrateur ne voit pas la mémoire d'un autre utilisateur ; l'audit montre les refus de politique sans le contenu sensible qui les a motivés. ### 7.2 Fait `pending` : durée de vie Un fait `pending` reste en carte jusqu'à action (valider/éditer/oublier) — pas d'expiration silencieuse. Au-delà de 30 jours, il est regroupé dans un rappel hebdomadaire unique (pas une notification par fait ; le budget d'interruption P15 s'applique dès cette phase aux cartes). ### 7.3 Post-conditions : la règle du succès `verify` absent ≠ succès présumé : le step est marqué `verified = NULL` et le run ne peut prétendre qu'à `succeeded` si **aucun** step d'écriture n'est simultanément `done` et non vérifié *alors qu'un `verify` existait*. Le rapport de couverture (P0-T12) rend la dette visible au lieu de la cacher. ### 7.4 Reprise après crash du conteneur Au démarrage, tout run `running` sans heartbeat récent passe `paused` avec le motif `interrupted` ; la reprise est manuelle (API ou panneau) cette phase — la reprise automatique des runs `origin='scheduled'` arrive avec #200 en phase 2. ## 8. Tests et golden tasks - Unitaires : store mémoire (clôture bi-temporelle, decay, planchers), résolution d'entités (ambiguïté), moteur de politiques (matrice complète des facteurs), idempotence (rejouer une step ne crée pas de doublon), miroir (idempotence du rendu, re-parse). - Intégration : run complet avec plan → approbation → exécution → vérification ; kill en cours de run → reprise ; édition manuelle de `Profil.md` → faits `source='user'`. - Golden tasks de la phase : **G3** (injection), **G6** (reprise), **G7** (bi-temporalité) — définitions au parent §16.1. - Non-régression : l'assistant actuel (sans mémoire activée) se comporte à l'identique ; `OBSIGATE_MEMORY_ENABLED=false` éteint la phase proprement. ## 9. Critères d'acceptation de la phase 1. Le conteneur Ollama n'existe plus et l'assistant fonctionne sur les providers API. 2. Un fait dit en conversation, validé par carte, est dans `Profil.md`, au recall de la conversation suivante, et son remplacement ultérieur conserve l'historique interrogeable à date. 3. Éditer `Profil.md` à la main modifie la mémoire (source `user`, confiance 1.0) ; rien hors balises n'est jamais écrasé. 4. Un run multi-écritures affiche son plan, n'exécute rien avant approbation, prouve chaque post-condition, et un run tué reprend sans doublon. 5. Le scénario d'injection G3 est refusé par la politique, journalisé, et présenté à Bruno en carte. 6. Les golden tasks G3/G6/G7 sont verts en CI. ## 10. Risques spécifiques et vigilance | Risque | Vigilance | |---|---| | Le compileur de contexte consomme le budget du modèle en silence | Le bloc est plafonné, son détail est visible (P0-T05) ; la métrique « tokens de contexte mémoire / conversation » est journalisée dès cette phase (alimente #212) | | Approbation par run trop grossière (tout ou rien) | Le plan affiche chaque step ; un step peut être **exclu** du plan avant validation (case par step) — l'approbation reste unique, le périmètre est ajustable | | Le miroir et une édition collaborative (Yjs) se marchent dessus | Le miroir écrit via le même chemin de sauvegarde que l'éditeur (backup préalable) et compare les hashs avant/après (règle durcie en phase 2 pour la consolidation) | | Dérive du périmètre : vouloir les tâches dès la phase 0 | Les tâches sont la phase 1 ; la phase 0 ne livre que les fondations qu'elles consommeront (runs, politique, mémoire) | ## 11. Ordre d'exécution ``` P0-T01 → T02 (#191, indépendant, à faire en premier) P0-T03 → T04 → T05 → T06 (#192) P0-T07 → T08 → T09 (#193, après T03/T06) P0-T10 → T11 → T12 (#213, T10 tôt : la provenance sert les runs) P0-T13 → T14 → T15 → T16 → T17 → T18 (#206, après T11) P0-T19 (harnais tôt, scénarios au fil des tickets) → P0-T20 (clôture) ``` ## 12. Définition de « terminé » DoD V2 §13 (tests unitaires + non-régression, JSDOM si UI, ruff/mypy 0 erreur, i18n FR/EN, CHANGELOG, ROADMAP, fiche par tranche, guide si exposé, CI verte, commit conventionnel référençant l'ID) **plus** les ajouts V2.1 (parent §21) : golden tasks du périmètre vertes ; toute écriture déclare sa post-condition et son inverse ou son absence ; toute source de contenu déclare sa provenance.