- 21 docs/*.md: audits, design notes, deployment plans, checklists, memos - Coordination: ROLES, runbooks (DGX reboot, Lea live), patches, registre, syntheses, systemd, QG template - Handoffs: 6 Codex handoff documents + README + template
9.7 KiB
Plan de remise au carré — chaîne d'apprentissage & rejeu de Léa
Date: 2026-06-27Auteur: Claude (mandat Dom)Statut: actif — formalise l'analyse du 27/06 ; n'invente rien, chapeautePLAN_ACTION_SUITE_2026-06-23(axe « Rejeu intelligent ») etCARTO_APPRENTISSAGE_FONDS_COMMUN_2026-06-16.Contrainte cardinale (Dom 27/06): câbler la chaîne ET rendre Léa correcte AVANT la dernière manip manuelle de Dom (= avant la perte de l'accès hands-on / on-site). Cette contrainte est la barre d'acceptation de ce plan. (À préciser : quoi exactement, et quelle date.)
1. Pourquoi ça ne marche pas (vérifié le 27/06)
En une phrase : la chaîne a été diagnostiquée (16/06), décidée (23/06) et planifiée (R1→R7), puis la livraison clinique a absorbé les 2 semaines — le câblage end-to-end n'a jamais démarré. Le blocage est d'EXÉCUTION, pas de décision.
Faits vérifiés (grep/fichier, ce jour) — la chaîne n'est pas câblée au runtime :
| Maillon | Preuve vérifiée 27/06 | Effet |
|---|---|---|
| Worker d'enrichissement | data/training/_worker_queue.txt = 0 octet, mtime 11/06 |
enrichissement à l'arrêt depuis 16 j |
| Import auto session→workflow | ShadowLearningHook() instancié uniquement dans son propre fichier, jamais dans finalize/runtime |
l'appris n'est pas rendu rejouable sans geste manuel |
| Lecture du fonds au rejeu | GlobalFAISSIndex.search() → grep = 0 appel ; TargetResolver.lookup() jamais appelé par replay-session |
rejeu = coords figées, pas cible apprise |
| Dé-silo | filtre machine_id à 5 points de stream_processor.py (3199, 3285, 4499, 4530, 5062) |
apprentissage siloté par poste |
Causes racines (au-delà du « c'est débranché ») :
- Les 2 semaines = infra de survie (portage DGX ARM, installateur EXE, réseau/firewall/VPN, reprise panne secteur + reboot, watchdog OVMF, enrôlement, streaming, push-log). Indispensable pour livrer — mais 0 h sur le câblage de la boucle.
- Découpage par composant, jamais par boucle. Hook, FAISS, TargetMemory bâtis et validés isolément (sessions/agents différents). Personne n'a possédé ni testé la boucle entière sur une vraie session → trous accumulés à chaque soudure, invisibles.
- Le raccourci démo est devenu permanent. Le rejeu
Urgence_aivamarchait en coords figées + templating{{var}}(seule pièce câblée). « Ça marchait » → le chemin intelligent n'a jamais été allumé.
⚠️ À confirmer en amont (audit runtime Qwen, NON vérifié indépendamment) : « 11/15 postes heartbeat-only, 0 % résolution vision/OCR/anchors ». Si avéré, le premier problème n'est pas l'apprentissage mais que les postes ne font pas encore le geste du POC (pas de vraie capture, cascade vision non exercée). → à prouver, chiffré, AVANT tout recâblage (Phase 0).
1bis. CARTE DE CÂBLAGE VÉRIFIÉE (28/06 — 3 agents read-only, sourcé code)
Cette section corrige le §1 sur deux points (diagnostic affiné, moins grave qu'annoncé).
Deux corrections vérifiées (mes affirmations antérieures étaient fausses) :
- « sessions → squelettes sans action » = FAUX. Les actions (clics/saisies) sont attachées au workflow sur les edges (
WorkflowEdge.action,graph_builder.py:1457), pas surnode.variants(qui = variantes visuelles d'écran, champ non peuplé au runtime). 48/71 workflows auto-appris portent leurs actions ; 23 sont vides (sessions trop courtes). - « rejeu = coords figées » = FAUX. Léa résout chaque cible par la vue à chaque rejeu (cascade OCR→template→YOLO→VLM sur anchors,
resolve_engine.py:1804). Coords = fallback ultime seulement. Conforme 100 % vision.
Ce qui MARCHE : capture→workflow avec actions ; worker traite ; 36/71 atteignent AUTO_CANDIDATE ; rejeu visuel (VWB-DB 226 click_anchor + JSON auto-appris non vides) ; R2 à moitié branché (TargetMemoryStore consulté en tête de _resolve_target_sync, resolve_engine.py:1862).
Les 4 vrais trous (sourcés) :
| # | Trou | Preuve | Type |
|---|---|---|---|
| 1 (P0) | 11/15 postes n'enregistrent rien | démarrage capture 100 % manuel (clic TIM « Apprenez-moi », smart_tray.py:349 / chat_window.py:1716) ; heartbeats auto (main.py:378). Risque : dialogue consentement Tk() (smart_tray.py:54) invisible en RDP/Citrix pythonw |
amont / UX (à confirmer bug vs usage par logs client) |
| 2 | Apprentissage incrémental débranché | LearningManager non instancié serveur ; mute WorkflowStats mémoire non re-persisté ; record_observation (learning_manager.py:54) 0 appelant. Seul GraphBuilder écrit learning_state, fige sur OBSERVATION si qualité faible (graph_builder.py:400) |
promotion jamais déclenchée |
| 3 | 2 mondes disjoints : JSON auto-appris ≠ DB VWB rejouable | stores/loaders/matchers séparés ; une session apprise ne devient pas un workflow DB rejouable | = R1 (pont JSON→DB) |
| 4 | Fonds commun jamais lu au rejeu | GlobalFAISSIndex.search() = 0 appel (seul add_pack écrit) |
= R3 (FAISS au rejeu) |
Points d'insertion confirmés : R1 = worker _process_session après _persist_workflow (réutiliser import_learned_workflow/learned_workflow_bridge, idempotence par workflow_trajectory_signature existante). R2/R3 = resolve_engine.py:1862-1878 (élargir memory_lookup + insérer GlobalFAISSIndex.search()).
Priorité (contrainte « Léa correcte avant dernière manip ») : #1 (amont) d'abord — si 11/15 postes ne capturent pas, l'aval est sans objet. Test décisif = grep logs client "Session … en cours" vs "Session finalisée" (Qwen).
2. État des décisions (rappel — la plupart sont déjà prises)
Tranchées le 23/06 (DECISIONS_PRODUIT_EN_ATTENTE_2026-06-23.md) → on exécute, on ne re-décide pas :
- F2-1/F14-1 : rejeu intelligent = OUI, prérequis (consulter le fonds appris, pas de coords figées).
- F1-1 : critère de fusion = signature de trajectoire (create-or-update).
- F9-1 : DB = vérité, JSON = échange ; métrique = workflows rejouables validés.
- F6-1 : mutualisation cross + intra-clinique (fédération anonymisée dans le périmètre + lever silo
machine_id).
Reste ouvert (1 seule, vraie décision) :
- Q-F2-2 — Provider Léa au runtime : quel modèle/route sert la résolution au rejeu. ⚠️ Gap tracé 23/06 : le point d'entrée actif = agent_chat 5004 →
SemanticMatcher.find_workflow()sur fichiers JSON, pas la DB → contredit F9-1. Se résout en chemin à la Phase 2 (où la résolution est recâblée). Reco modèle : Qwen3-VL-4B grounder + gemma4 (bench 13/06).
Décisions potentiellement induites par la Phase 0 : si « 0 % vision » confirmé, une décision « comment forcer/garantir la capture vision réelle sur poste » surgira (priorité absolue, avant R1).
3. Plan d'exécution (séquencé, chirurgie supervisée)
Les chantiers R1→R7 détaillés sont dans
PLAN_ACTION_SUITE_2026-06-23(§ Axe central) — non dupliqués ici. Ce plan ajoute la Phase 0 de mesure (nouvelle) et l'ordre/critères.
Phase 0 — MESURER (avant tout recâblage). Établir la vérité terrain : par poste, nb de vraies sessions, la cascade vision est-elle déclenchée (compteur de résolutions par méthode), captures reçues, état queue. C'est ce que push-log + une télémétrie vision apportent (lien direct avec briques 1-4 livrées). → Mission Qwen (accès runtime DGX). Critère de sortie : on sait, chiffré, ce que font les 15 postes.
Phase 1 — RECONNECTER L'AMONT (R1). Import auto session→workflow post-finalize + relancer le worker (queue morte 11/06). Critère : une session TIM réelle devient un workflow rejouable sans geste manuel.
Phase 2 — RECONNECTER L'AVAL (R2+R3) + résoudre Q-F2-2. Câbler TargetResolver.lookup() + lecture FAISS au rejeu, fallback obligatoire sur coords figées (non négociable Qwen — enrichir, pas casser) ; aligner le point d'entrée résolution sur la DB (F9-1). Critère : Léa résout par cible apprise, retombe sur coords si échec.
Phase 3 — BOUCLE + DÉ-SILO (R4/R5/R6). verify post-condition (échec → pause supervisée), réécriture du fonds, lever silo machine_id + brancher fédération (GlobalFAISSIndex.search()).
4. Gouvernance (corrige la cause racine #2)
- Un seul propriétaire de la boucle entière (pas un découpage par composant).
- Critère d'acceptation = un test end-to-end sur une session réelle, pas une validation par brique.
- Chirurgie itérative supervisée : un maillon = un test ≤ 2 min = GO Dom ; démo
Urgence_aivaintacte à chaque étape ; reconfirmer le wiring runtime avant chaque modif (imports lazy = verdicts « orphelin » non fiables). - Merge prod supervisé Dom.
5. Lien avec la « dernière manip manuelle » (deadline)
La contrainte de Dom fait de ce plan un chemin critique : tant que Léa n'est pas correcte (au moins Phase 0 + Phase 1-2 sur 1 poste pilote), la dernière manip manuelle ne doit pas avoir lieu — sinon plus d'accès hands-on pour réparer. → Définir avec Dom : quelle est cette manip, et sa date butoir, pour caler le séquencement.
6. Première action concrète
Phase 0 confiée à Qwen (chiffres runtime). Doc + page décisions = ce fichier. Reste : GO Dom sur le séquencement + définition de la deadline « dernière manip ».
Plans sources (ne pas dupliquer) : PLAN_ACTION_SUITE_2026-06-23, CARTO_APPRENTISSAGE_FONDS_COMMUN_2026-06-16, DECISIONS_PRODUIT_EN_ATTENTE_2026-06-23, PLAN_CHANTIER_UNIFICATION_LEA_VWB_2026-06-17.