docs: track design docs, plans, audits, coordination infrastructure, handoffs
- 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
This commit is contained in:
174
docs/AUDIT_GAPS_APPLI_100PCT_2026-06-10.md
Normal file
174
docs/AUDIT_GAPS_APPLI_100PCT_2026-06-10.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Audit — Ce qui manque pour une appli 100% fonctionnelle
|
||||
|
||||
- **Date** : 2026-06-10
|
||||
- **Demandeur** : Dom
|
||||
- **Auteur** : Claude (audit read-only par 4 sous-agents d'exploration + contre-vérifications manuelles)
|
||||
- **Périmètre** : agent client Windows (Léa), chaîne d'apprentissage, capacité de replay, maturité produit/fleet
|
||||
- **Statut findings** : les fichier:ligne proviennent d'agents d'exploration. Les 3 contradictions majeures ont été re-vérifiées à la main (voir annexe). **Avant d'engager du code sur un item, revalider le point au cas par cas** (méthode habituelle).
|
||||
- **Avis croisé Qwen** : reçu 2026-06-10 23:30 (`inbox_claude/2026-06-10_2330_qwen-to-claude_AVIS-GAPS-APPLI-100PCT.md`) — intégré en **Addendum (§7)**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Diagnostic central
|
||||
|
||||
L'appli aujourd'hui, honnêtement qualifiée : **un record-and-replay supervisé robuste, avec une couche sémantique réelle au grounding, mais dont la boucle d'apprentissage n'est pas fermée et dont les filets de sécurité sont écrits mais débranchés.**
|
||||
|
||||
Trois promesses produit non tenues dans le code qui tourne :
|
||||
|
||||
1. **La boucle d'apprentissage est ouverte** — Shadow observe et construit des workflows, mais ils n'arrivent jamais dans VWB (import jamais déclenché).
|
||||
2. **L'exécution ne se vérifie pas elle-même** — verify, healing, recovery : tout existe, tout est désactivé ou non branché.
|
||||
3. **Pas de généralisation** — un workflow appris ne survit pas à un changement de poste/résolution ; FAISS est construit au training mais jamais consulté au replay.
|
||||
|
||||
Point structurel transverse : **deux chemins d'exécution aux capacités différentes** :
|
||||
- `visual_workflow_builder/backend/api_v3/execute.py` (exécution locale VWB, Legacy + ORA)
|
||||
- `agent_v0/server_v1/replay_engine.py` → agent Windows Léa (chemin POC)
|
||||
|
||||
Certains manques n'existent que sur l'un des deux. `t2a_decision` et le templating profond `{{var.field.sub}}` sont **implémentés sur le chemin Léa** (replay_engine.py:1922 et :2017) mais absents du chemin local. Cette asymétrie a piégé jusqu'aux agents d'audit eux-mêmes — c'est un coût de maintenance et un risque d'erreur permanent.
|
||||
|
||||
---
|
||||
|
||||
## 2. Axe agent client Windows (Léa) — ~80% fonctionnel, 1 bug critique
|
||||
|
||||
### Ce qui marche (vérifié wired)
|
||||
- Capture complète : clics/double-clics, clavier+buffer texte, scroll, multi-écrans, DPI awareness, floutage sensible, dédup pHash.
|
||||
- Résilience réseau : buffer SQLite persistant, retry 3×, backoff 1→30s, heartbeat 5s.
|
||||
- Purge captures après ACK serveur (`PURGE_AFTER_ACK=1` défaut).
|
||||
- Enroll Bearer token + machine_id ; détection dialogues système UAC/CredUI/SmartScreen **fail-closed** (pause supervisée).
|
||||
- Rétention logs 180 j (conforme Règlement IA art. 12).
|
||||
|
||||
### Gaps
|
||||
|
||||
| # | Gap | Sévérité | Preuve | Type |
|
||||
|---|-----|----------|--------|------|
|
||||
| A1 | **Timeout HTTP client 5s** : étape serveur > 5s (extract_text, t2a) → client coupe, action déjà sortie de la queue → **perdue silencieusement**. Incident documenté 8 mai (4 actions perdues, pause step 18). | 🔴 BLOQUANT POC | `agent_v1/core/executor.py:1786` ; `docs/REPLAY_BLOCAGE_NOTES_MEDICALES_2026-05-08.md` | Bug |
|
||||
| A2 | **Watchdog `_retry_pending` absent** côté serveur : actions perdues jamais republiées. | 🔴 BLOQUANT POC | `network/streamer.py:99-105` (constat) | Non implémenté |
|
||||
| A3 | Écran verrouillé non détecté : agent capture noir, tape dans le vide. | 🟠 Important | — | Non implémenté |
|
||||
| A4 | RecoveryEngine client : code complet, jamais appelé. | 🟡 Nice-to-have | `agent_v1/core/recovery.py` | Écrit non branché |
|
||||
| A5 | Long-polling HTTP fragile par construction (vs SSE/WebSocket). | 🟡 Post-POC | `main.py:287-366` | Architecture |
|
||||
|
||||
Note : la suspicion « appel Ollama de commentaire d'action orphelin côté client » **ne se confirme pas** côté agent_v1 (`OLLAMA_HOST` défini dans config mais aucun appel client). Le commentaire d'action est côté serveur.
|
||||
|
||||
---
|
||||
|
||||
## 3. Axe chaîne d'apprentissage — marche jusqu'au dernier mètre, puis s'arrête
|
||||
|
||||
### Ce qui marche (vérifié wired)
|
||||
- Chaîne Shadow complète : streaming → LiveSessionManager → `_worker_queue.txt` → `run_worker.py` → ScreenAnalyzer → CLIP → FAISS indexation → GraphBuilder DBSCAN → workflow JSON dans `data/training/workflows/{machine_id}/`.
|
||||
- Apprentissage post-replay : ReplayLearner (JSONL `data/learning/replay_results/`) + TargetMemoryStore (SQLite `data/learning/target_memory.db`), consultés avant résolution, alimentés après succès/échec.
|
||||
|
||||
### Gaps
|
||||
|
||||
| # | Gap | Sévérité | Preuve | Type |
|
||||
|---|-----|----------|--------|------|
|
||||
| L1 | **Workflows Shadow jamais importés dans VWB** : `import_core_workflow()` existe (`visual_workflow_builder/backend/api/workflows.py:622`) mais aucun appel automatique post-finalize. La boucle d'apprentissage produit des fichiers que personne ne voit. | 🔴 BLOQUANT promesse produit | grep `import_core_workflow` depuis server_v1 = 0 hit | Écrit non branché |
|
||||
| L2 | ShadowLearningHook jamais importé (état avril 2026 inchangé). | 🟠 Important | `core/grounding/shadow_learning_hook.py` | Écrit non branché |
|
||||
| L3 | **FAISS construit mais jamais interrogé au replay** — la mémoire sémantique ne sert pas à la résolution. | 🟠 Important | `core/embedding/faiss_manager.py` | Écrit non branché |
|
||||
| L4 | Pas de généralisation cross-résolution/cross-poste : workflows cloisonnés par machine_id, ancres dépendantes du poste source. | 🟠 Important | `core/models/workflow_graph.py` | Non implémenté |
|
||||
| L5 | **Copilot : inexistant** (aucun moteur de suggestion). **Autonomous : AutonomousPlanner isolé du replay engine.** Le cycle Shadow→Copilot→Autonomous est aujourd'hui Shadow→(rien)→exécution déclenchée manuellement. | 🔴 BLOQUANT promesse produit | `agent_chat/autonomous_planner.py`, `agent_v0/server_v1/execution_plan_runner.py` | Squelettes |
|
||||
| L6 | Recapture anchor VWB : pas de revalidation/régénération PNG post-modification (bug connu mai 2026). | 🟠 Important | `visual_workflow_builder/backend/services/anchor_image_service.py` | Non implémenté |
|
||||
|
||||
---
|
||||
|
||||
## 4. Axe replay/exécution — ça clique bien, mais ça ne sait pas si ça a marché
|
||||
|
||||
### Ce qui marche (vérifié wired)
|
||||
- Cascade de résolution active : template matching → CLIP → OCR/UI-TARS → VLM.
|
||||
- DialogHandler branché (détection popups pré-step).
|
||||
- Pause supervisée avec choix utilisateur (skip/static/coords, timeout 120s).
|
||||
- Chemin Léa : `t2a_decision` (replay_engine.py:1922, handlers :2045+), templating profond `{{var.field.sub}}` (`path.split('.')` :2017), extract_text.
|
||||
|
||||
### Gaps
|
||||
|
||||
| # | Gap | Sévérité | Preuve | Type |
|
||||
|---|-----|----------|--------|------|
|
||||
| R1 | **`verify_level='none'` en dur** : aucune vérification post-action que le clic a produit l'effet attendu (seul pHash d'attente d'écran). Contraire au principe « vérif avant + après chaque clic ». | 🟠 Important (🔴 avant clinique) | `execute.py:1545` | Branché désactivé |
|
||||
| R2 | **VLM pre-check `if False:` en dur** : pas de validation que l'élément trouvé = l'élément attendu. | 🟠 Important | `core/execution/observe_reason_act.py:1707` | Branché désactivé |
|
||||
| R3 | Healing engine implémenté, jamais appelé. | 🟠 Important | `core/healing/healing_engine.py:21-150` | Écrit non branché |
|
||||
| R4 | **Aucune reprise après crash** : crash au step N → redémarrage à 0, pas de checkpoint. | 🔴 BLOQUANT clinique | `execute.py:1732` (thread daemon sans checkpoint) | Non implémenté |
|
||||
| R5 | **OCR-DIRECT « centre de ligne »** : substring d'une ligne docTR → coordonnées du centre de la ligne entière. Sur une barre d'onglets, Imagerie/Notes/Synthèse ≈ mêmes coords. Latent et sournois. | 🟠 Important | `agent_v0/server_v1/resolve_engine.py:1447-1527` | Bug |
|
||||
| R6 | Timeout VWB→serveur 30s vs étapes longues (t2a/Ollama lent) → 504. | 🟠 Important | `server_client.py:207` | Bug config |
|
||||
| R7 | Reporting d'exécution pauvre : méthode de grounding utilisée et raison d'échec non tracées. | 🟠 Important | ExecutionStep DB | Incomplet |
|
||||
| R8 | Popup détecté mais gestion échouée → continue (log seul), pas de pause. | 🟡 Nice-to-have | `execute.py:283` | Incomplet |
|
||||
| R9 | 3 systèmes de grounding morts (code zombie) : `fast_detector`, `smart_matcher`, `template_matcher` standalone. | 🟡 Ménage | `core/grounding/` | Poids mort |
|
||||
| R10 | TitleVerifier aveugle en VM (crop EasyOCR 45px illisible). | 🟡 Connu | `core/grounding/title_verifier.py:34-67` | Limitation |
|
||||
|
||||
---
|
||||
|
||||
## 5. Axe maturité produit / fleet — OK pour 5 TIM supervisés, pas au-delà
|
||||
|
||||
### Ce qui marche (vérifié)
|
||||
- Fleet : enroll/uninstall/revoke SQLite (`agent_registry.py`), `_guard_agent_registry_access`, last_seen heartbeat.
|
||||
- Sessions concurrentes thread-safe ; uploads images rate-limités sans sérialisation.
|
||||
- Healthcheck multi-composants + timer systemd (API, dashboard, worker heartbeat, disque).
|
||||
- Export ZIP workflows ; dashboard HTTP Basic fail-closed.
|
||||
|
||||
### Gaps
|
||||
|
||||
| # | Gap | Sévérité | Preuve | Type |
|
||||
|---|-----|----------|--------|------|
|
||||
| P1 | **DETTE-006/010 — grounding Qwen3-VL instable** (`smart_resize` non déterministe, config checkpoint factor 28 vs 32). LE risque technique du calendrier POC. | 🔴 BLOQUANT POC | `docs/MIGRATION_VLM_PLAN_2026-05-09.md`, DETTE_TECHNIQUE.md | En cours |
|
||||
| P2 | **1 seul replay simultané** (verrou global `_replay_lock`). Acceptable POC séquentiel, bloquant au-delà. | 🟠 Important post-POC | `api_stream.py` | Limitation |
|
||||
| P3 | Opérabilité non-dev : pas d'onglet « état systèmes », pas de monitoring GPU/Ollama, erreurs JSON brut. Acceptable seulement avec Dom en SSH derrière. | 🟠 Important | `web_dashboard/app.py` | Incomplet |
|
||||
| P4 | Export ZIP sans **restore** en masse ; backup exporte les JSON, pas la DB (DETTE-015 : symlink tient pour le POC). | 🟠 Important | `core/system/backup_exporter.py:58-160` | Incomplet |
|
||||
| P5 | Multi-users/RBAC : 1 user statique. Accepté POC (lié DETTE-016). | 🟡 Post-POC | `web_dashboard/app.py:67` | Accepté |
|
||||
| P6 | Pas de rotation des logs serveurs (`logs/*.log`) — artifact_retention ne couvre que les données. | 🟡 Nice-to-have | `core/system/artifact_retention.py` | Incomplet |
|
||||
| P7 | DETTE-013 : tests unit non exécutables sans `RPA_API_TOKEN` (sys.exit à l'import). | 🟠 Important dev | `agent_v0/server_v1/api_stream.py:135` | Bug |
|
||||
| P8 | Ménage pré-POC (~9-10 j-h, `MENAGE_PRE_POC_2026-05-29.md`) non engagé ; ~21 modules core/ orphelins documentés. | 🟡 Planifié | docs/POC/ | Dette |
|
||||
|
||||
---
|
||||
|
||||
## 6. Priorisation proposée
|
||||
|
||||
### Horizon 1 — avant le M2 live (jours) : fiabiliser la chaîne qui existe
|
||||
1. **A1** Timeout client 5s → 30s (1 constante) + **A2** watchdog `_retry_pending` serveur — le duo qui a tué la session du 8 mai.
|
||||
2. **P1** Trancher DETTE-006/010 (calibration grounding Qwen3-VL sur DGX) avant le bench J+6.
|
||||
3. **A3** Détection écran verrouillé.
|
||||
|
||||
### Horizon 2 — avant la clinique (semaines) : les filets de sécurité
|
||||
4. **R1/R2** Réactiver verify (au moins post-condition légère) + pre-check.
|
||||
5. **R5** Fix OCR centre-de-ligne (span du substring, pas centre de ligne).
|
||||
6. **R4** Reprise sur crash (checkpoint step) + **R7** tracer la méthode de résolution.
|
||||
7. **R6** Timeout VWB 30s → adapté aux étapes longues (ou polling asynchrone).
|
||||
|
||||
### Horizon 3 — la promesse produit (post-POC) : fermer la boucle
|
||||
8. **L1** Pont auto Shadow→VWB (`import_core_workflow` post-finalize) — LA pièce qui transforme l'outil en produit apprenant.
|
||||
9. **L3** FAISS consulté au replay + **L4** début de généralisation cross-poste.
|
||||
10. **L5** Copilot (moteur de suggestion) puis branchement AutonomousPlanner.
|
||||
11. Unifier les deux chemins d'exécution (execute.py local vs replay_engine.py Léa).
|
||||
12. **P2** Replays parallèles, **P3** opérabilité TIM, **P4** restore, RBAC.
|
||||
|
||||
---
|
||||
|
||||
## 7. Addendum — Avis croisé Qwen (historien/QG, 2026-06-10 23:30)
|
||||
|
||||
### Convergences avec l'audit code
|
||||
- **DETTE-006/010 = les deux vrais risques démo** (« si le grounding dérive, les clics ratent. Démo morte. ») — aligné avec P1/Horizon 1.
|
||||
- **Monitoring/alerting productif absent** (P3) : « si un worker crashe à 3h du matin sur un TIM, personne ne le saura ».
|
||||
- Écarts doc vs réalité confirmés par son registre : ContinuousLearner/Shadow hook orphelins (L2), cascade YOLO et OmniParser neutralisées (DETTE-004), ~1900 lignes de code mort jamais câblé (autonomous_planner, seeclick…) — cohérent avec L5/R9.
|
||||
|
||||
### Apports nouveaux de Qwen (absents de l'audit code)
|
||||
1. **Multi-TIM jamais testé > 1 agent simultané** : le Fleet existe, mais routage session, isolation mémoire et contention GPU sous charge réelle sont **inconnus**. Mon audit avait noté le verrou replay global (P2) ; Qwen élargit : c'est toute la concurrence multi-agents qui n'a aucune preuve d'exécution.
|
||||
2. **Le pipeline complet record → replay → compétence n'a jamais tourné en conditions réelles** : M2 live n'a pas encore eu lieu. « Le premier vrai test sera devant le client » si on ne fait pas M2 avant.
|
||||
3. **Incidents récurrents de son registre** : worker zombie 5 jours (résolu par watchdog N3), tunnel Ollama instable (stabilisé systemd), UI-TARS 500 non détecté (toujours 0 test dédié), OOM VRAM GB10 (fixé).
|
||||
4. **DETTE-015 jugée fragile** : le symlink a déjà cassé une fois (P0-1) ; peut resurgir si cwd change.
|
||||
|
||||
### Point de tension à arbitrer en M2 (pas tranché)
|
||||
Qwen affirme : « si le serveur redémarre, les agents Windows tombent — pas de reconnexion automatique ». Mon audit client a trouvé buffer SQLite persistant + retry + backoff + health-check 30s (`streamer.py`). Les deux peuvent être vrais : le **transport** se reconnecte, mais la **session/replay en cours** ne reprend probablement pas après un restart serveur. À vérifier explicitement pendant M2 (test : restart serveur en cours de session).
|
||||
|
||||
### Verdict Qwen
|
||||
- **1 TIM en démo contrôlée : prêt** (sous réserve DETTE-006/010).
|
||||
- **5 TIM réels en clinique : pas prêt** — le gap n'est pas dans le code métier (OCR, VLM, grounding) mais dans l'**infra multi-utilisateur** : sessions, isolation, monitoring, résilience.
|
||||
|
||||
Ce verdict est compatible avec la priorisation §6 et la renforce : l'Horizon 2 doit inclure un **test de charge multi-agents** (2-3 agents simultanés minimum) avant la clinique, en plus des filets de sécurité.
|
||||
|
||||
---
|
||||
|
||||
## Annexe — Contradictions inter-agents résolues (contre-vérifiées à la main)
|
||||
|
||||
| Affirmation agent d'audit | Verdict après vérification |
|
||||
|---|---|
|
||||
| « t2a_decision non implémenté » | **FAUX sur le chemin Léa** : implémenté `agent_v0/server_v1/replay_engine.py:1922` + handlers :2045+. Vrai uniquement pour le chemin local execute.py. |
|
||||
| « `{{var.field.sub}}` ne marche pas » | **FAUX sur le chemin Léa** : `path.split('.')` replay_engine.py:2017. Vrai uniquement chemin local. |
|
||||
| « Le chemin replay vers Léa est démis / Léa n'existe plus » | **FAUX** : pont `learned_workflow_bridge.py` côté VWB + polling `/replay/next` côté client actifs. Les deux chemins coexistent — c'est l'asymétrie connue. |
|
||||
|
||||
Leçon : tout audit ou modification doit d'abord identifier **sur quel chemin d'exécution** il porte.
|
||||
Reference in New Issue
Block a user