Files
rpa_vision_v3/docs/CARTE_FONCTIONNELLE_2026-05-08.md
2026-05-09 11:32:52 +02:00

278 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Carte fonctionnelle RPA Vision V3 — 2026-05-08
Branche : `feature/qw-suite-mai` | HEAD : `731b5bcae`
Vue produit (pas code). Inventaire des fonctionnalités telles qu'elles existent réellement dans le repo à cette date.
---
## 1. Modes opérationnels de Léa (agent_v1)
Le client Léa V1 (`agent_v0/agent_v1/`) n'expose **pas** d'enum `MODE_*` discret. Son comportement runtime est piloté par trois booléens cumulables dans `AgentState` (`ui/shared_state.py`) :
| Mode | Module(s) concerné(s) | Activation | Statut |
|---|---|---|---|
| Capture / enregistrement | `ui/shared_state.py:30` (`_recording`), `core/captor.py`, `vision/capturer.py` | Bouton "Démarrer" dans systray (`smart_tray.py:377`) ou ChatWindow → `state.start_recording(name)` | actif |
| Replay (polling serveur) | `main.py:130` (`_replay_poll_loop`), `core/executor.py:510-1900` | Boucle daemon permanente, lancée à l'init de `AgentV1` indépendamment de toute session — poll `GET /replay/next` toutes les 1 s sur `agent_{user_id}` | actif |
| Heartbeat permanent (background) | `main.py:131` (`_background_heartbeat_loop`) | Daemon permanent, screenshot toutes les 5 s vers `POST /traces/stream/image` (session `bg_{machine_id}`) | actif |
| Heartbeat session | `main.py:434` (`_heartbeat_loop`) | Démarre seulement quand `session_id` actif (pendant un enregistrement) | actif |
| Watchdog fichier `command.json` | `main.py:247` (`_command_watchdog_loop`) | Poll fichier `C:\rpa_vision\command.json` toutes les 1 s, exécute `execute_normalized_order` | actif (legacy GHOST replay) |
| Capture à la demande HTTP | `ui/capture_server.py` | Mini-serveur HTTP local port 5006 lancé au boot | actif |
| Auto-stop session | `main.py:160` (`_auto_stop_loop`) | Notifie 10 min avant et stoppe à `MAX_SESSION_DURATION_S` | actif |
**Modes "shadow / copilot / assisté / autonomous"** : ils n'existent **pas** côté client Léa V1. Côté serveur, `execution_mode` est un paramètre de replay (`"autonomous"` par défaut, voir `api_stream.py:2969`, `replay_engine.py:1520`). Les valeurs détectées : `"autonomous"`, `"verified"`, `"supervised"` (déduit du test `_exec_mode != "autonomous"` à `api_stream.py:2974`). Le frontend VWB définit en plus `'basic' | 'intelligent' | 'debug' | 'verified'` (`types.ts:15`) — **ce sont des modes VWB, pas des modes Léa**. [À VÉRIFIER PAR DOM]
Endpoints `/api/v1/shadow/*` (start/stop/feedback/build/understanding) existent côté serveur (`api_stream.py:1661-1820`) mais aucun n'est appelé depuis le client Léa V1 (grep dans `agent_v0/agent_v1/` : zéro hit). [À VÉRIFIER PAR DOM]
---
## 2. Capacités du serveur (rpa-streaming + dépendances)
54 endpoints exposés par `agent_v0/server_v1/api_stream.py`.
### 2.1 Streaming session / heartbeat
- `POST /api/v1/traces/stream/register` — Enregistrer une session (session_id + machine_id)
- `POST /api/v1/traces/stream/event` — Pousser un événement clavier/souris/fenêtre
- `POST /api/v1/traces/stream/image` — Pousser un screenshot (heartbeat ou shot d'action)
- `POST /api/v1/traces/stream/finalize` — Clore une session
- `GET /api/v1/traces/stream/processing/status` — État de la file de traitement
- `POST /api/v1/traces/stream/processing/requeue` — Re-traiter une session déjà finalisée
- `GET /api/v1/traces/stream/stats` — Statistiques globales du serveur
- `GET /api/v1/traces/stream/machines` — Liste machines enrôlées
- `GET /api/v1/traces/stream/sessions` — Liste sessions (filtrable par machine_id)
### 2.2 Replay (next/report/resolve_target/pause)
- `POST /api/v1/traces/stream/replay` — Lancer un replay depuis un workflow_id
- `POST /api/v1/traces/stream/replay/raw` — Lancer un replay depuis une liste d'actions brutes
- `POST /api/v1/traces/stream/replay-session` — Re-rejouer une session enregistrée
- `POST /api/v1/traces/stream/replay/single` — Enqueuer une action unique
- `POST /api/v1/traces/stream/replay/plan` — Lancer depuis un ExecutionPlan (V4)
- `POST /api/v1/traces/stream/workflow/compile` — Compiler session → WorkflowIR + ExecutionPlan
- `GET /api/v1/traces/stream/replay/next` — Action suivante à exécuter (pollée par Léa)
- `POST /api/v1/traces/stream/replay/result` — Rapport d'exécution d'une action
- `POST /api/v1/traces/stream/replay/error_callback` — Callback erreur configurable
- `GET /api/v1/traces/stream/replay/{replay_id}` — État d'un replay
- `GET /api/v1/traces/stream/replays` — Liste des replays
- `POST /api/v1/traces/stream/replay/{replay_id}/resume` — Reprendre après pause supervisée
- `POST /api/v1/traces/stream/replay/{replay_id}/cancel` — Annuler un replay
- `POST /api/v1/traces/stream/replay/resolve_target` — Résoudre la position d'une ancre (cascade vLLM/Ollama)
- `POST /api/v1/traces/stream/replay/pre_analyze` — Pré-analyse de l'écran avant action
### 2.3 Extraction (text / table / décision T2A)
Pas d'endpoint HTTP dédié — ces actions sont enqueuées côté serveur via le replay et traitées sans round-trip Léa par `replay_engine.py:_handle_extract_text_action / _handle_extract_table_action / _handle_t2a_decision_action` (modules `core/llm/ocr_extractor.py` et `core/llm/t2a_decision.py`).
### 2.4 Federation / learning packs
- `GET /api/v1/traces/stream/learning-pack/export` — Export anonymisé (par client_id)
- `POST /api/v1/traces/stream/learning-pack/import` — Import + merge dans FAISS global
### 2.5 Health / monitoring
- `GET /health` — Healthcheck simple
- `GET /api/v1/traces/stream/workflows` — Liste workflows visibles
- `POST /api/v1/traces/stream/reload-workflows` — Rechargement à chaud
- `GET /api/v1/traces/stream/workflow/{workflow_id}` — Détail workflow
- `GET /api/v1/traces/stream/session/{session_id}` — Détail session
- `GET /api/v1/audit/history` — Historique audit (RGPD/IA Act)
- `GET /api/v1/audit/summary` — Résumé audit
- `GET /api/v1/audit/export` — Export audit
### 2.6 Autres
- `POST /api/v1/shadow/start` — Démarrer un observateur shadow (existe, voir §1)
- `POST /api/v1/shadow/stop` — Arrêter
- `POST /api/v1/shadow/feedback` — Feedback humain sur une étape observée
- `GET /api/v1/shadow/{session_id}/understanding` — Lire la compréhension construite
- `POST /api/v1/shadow/build` — Compiler en workflow
- `POST /api/v1/task` — Tâche planifiée (TaskPlanner)
- `GET /api/v1/task/capabilities` — Capacités déclarées (action types)
- `POST /api/v1/chat/session` — Créer une session de chat serveur
- `POST /api/v1/chat/{session_id}/message` — Envoyer message
- `GET /api/v1/chat/{session_id}/history` — Historique
- `POST /api/v1/chat/{session_id}/confirm` — Confirmer un plan
- `GET /api/v1/chat/sessions` — Liste sessions chat
- `POST /api/v1/agents/enroll` — Enrôler un nouvel agent (nouvelle machine)
- `POST /api/v1/agents/uninstall` — Désenrôler
- `GET /api/v1/agents/fleet` — État de la flotte
---
## 3. Stack VLM / grounding active
Synthèse de `docs/HISTORIQUE_VLM_IMPLEMENTATIONS_2026-05-08.md` (§1, §6).
| Modèle | Backend | Module appelant | Statut |
|---|---|---|---|
| `InfiX-ai/InfiGUI-G1-3B` 4-bit NF4 | Transformers in-process (Flask) | `core/grounding/server.py` (port 8200) | câblé mais inactif (pas dans la cascade actuelle) |
| `InfiX-ai/InfiGUI-G1-3B` 4-bit NF4 | Transformers subprocess one-shot | `core/grounding/infigui_worker.py` | câblé mais inactif (utilisé en fallback de la socket) |
| `InfiX-ai/InfiGUI-G1-3B` 4-bit NF4 | Transformers daemon Unix socket `/run/rpa/grounding.sock` | `core/grounding/infigui_server.py` (service systemd `rpa-grounding.service`) | service présent — `rpa-grounding.service.parked` détecté dans `/etc/systemd/system/` [À VÉRIFIER PAR DOM] |
| `Qwen/Qwen2.5-VL-7B-Instruct-AWQ` | vLLM HTTP OpenAI-compat (port `VLLM_PORT=8100`) | `agent_v0/server_v1/resolve_engine.py:785-816` (`_resolve_by_grounding`) | utilisé en prod — essai 1 (fallback Ollama) [À VÉRIFIER PAR DOM si vLLM tourne] |
| `qwen2.5vl:7b` | Ollama HTTP `/api/chat` | `resolve_engine.py:818-832` (fallback de vLLM) | utilisé en prod — fallback principal de la cascade |
| `qwen2.5vl:7b` | Ollama HTTP `/api/chat` | `resolve_engine.py:2536-2585` (`_locate_popup_button`) | utilisé en prod — cas spécifique popup |
| `qwen3-vl:8b`, `gemma4:e4b` | Ollama HTTP | `core/detection/ollama_client.py` (utilisé par `ui_detector.py`, `som_engine.py`, `vram_orchestrator.py`) | utilisé en prod — détection UI + SoM côté core/detection |
| `qwen2.5vl:3b` | Ollama HTTP | `visual_workflow_builder/backend/api_v3/capture.py:245` (description anchor) | utilisé en prod — chaîne capture VWB |
| `qwen3-vl:8b` | Ollama HTTP | `visual_workflow_builder/backend/api_v3/dag_execute.py:468` (LLMActionHandler) | utilisé en prod — DAG executor LLM |
| `qwen2.5vl` | Ollama HTTP | `visual_workflow_builder/backend/catalog_routes_v2_vlm.py` | utilisé en prod — catalog UI |
| OpenAI-compat cloud (OpenAI/Gemini/Anthropic) | HTTP cloud (opt-in `VLM_ALLOW_CLOUD=true`) | `visual_workflow_builder/backend/vlm_provider.py` | câblé mais inactif (cloud désactivé par défaut, contraire à la directive 100% local) |
| `cckevinn/SeeClick` (Qwen-VL) | Transformers in-process | `core/detection/seeclick_adapter.py` | téléchargé non utilisé (signalé "cassé" par commit `d1b556b6c`, exporté par `__init__.py` mais zéro call site actif) |
| `Owlv2` (Google OWL-v2) | Transformers in-process | `core/detection/owl_detector.py` (via `ui_detector.py:31,113,126`) | câblé mais inactif (présent dans la chaîne de détection — bench récent inconnu) [À VÉRIFIER PAR DOM] |
| `ByteDance-Seed/UI-TARS-1.5-7B` | Transformers (référencé) | `tools/start_grounding_server.sh` | référencé en doc seulement (modèle remplacé par InfiGUI dans le code par commit `77faa03ec`) |
---
## 4. Capacités du VWB (visual_workflow_builder)
### 4.1 Modes de construction de workflows
Trois voies coexistent :
1. **Capture interactive** : sélection de zones/ancres via `POST /api/v3/capture/screen` + `POST /api/v3/capture/select` (frontend `CapturePanel.tsx`, `CaptureLibrary.tsx`).
2. **Édition manuelle dans le canvas** : ajout d'étapes via `POST /api/v3/workflow/{id}/step` (frontend `StepNode.tsx`, `ToolPalette.tsx`, `PropertiesPanel.tsx`).
3. **Import de workflow appris par Léa** : `POST /api/v3/learned-workflows/{id}/import` lit les workflows produits côté streaming server (sessions enregistrées) et les insère en SQLite VWB.
### 4.2 Types d'actions supportées
36 types listés dans `frontend_v4/src/types.ts:40-82` (constante `ACTIONS`).
**Souris** :
- `click_anchor` — Clic gauche sur élément visuel — needs anchor : oui
- `double_click_anchor` — Double-clic — needs anchor : oui
- `right_click_anchor` — Clic droit (menu contextuel) — needs anchor : oui
- `hover_anchor` — Survol — needs anchor : oui
- `drag_drop_anchor` — Glisser-déposer vers cible — needs anchor : oui
- `scroll_to_anchor` — Défiler jusqu'à élément — needs anchor : oui
- `focus_anchor` — Donner focus clavier — needs anchor : oui
**Clavier** :
- `type_text` — Saisir texte (templating `{{var}}`) — needs anchor : non
- `type_secret` — Saisir secret depuis coffre-fort — needs anchor : non
- `keyboard_shortcut` — Combinaison touches — needs anchor : non
**Attente** :
- `wait_for_anchor` — Attendre apparition élément — needs anchor : oui
**Données** :
- `extract_text` — OCR EasyOCR fr+en sur dernier screenshot → variable — needs anchor : non
- `extract_table` — OCR + filtre regex → liste structurée → variable — needs anchor : oui
- `screenshot_evidence` — Capture preuve — needs anchor : non
- `download_to_folder` — Télécharger fichier — needs anchor : non
- `db_save_data` / `db_read_data` — BDD locale — needs anchor : non
- `import_excel` / `db_foreach` — Boucle Excel/CSV → BDD — needs anchor : non
**Logique** :
- `visual_condition` — Branchement si ancre trouvée — needs anchor : oui (hidden : true)
- `loop_visual` — Boucle tant qu'ancre visible — needs anchor : oui (hidden : true)
- `pause_for_human` — Pause supervisée + safety_checks (QW4) — needs anchor : non
- `t2a_decision` — Analyse DPI urgences via LLM local (qwen2.5:7b par défaut) — needs anchor : non
**IA (Ollama vision/text)** :
- `ai_ocr` — OCR IA sur ancre — needs anchor : oui
- `ai_summarize` — Résumé LLM — needs anchor : non
- `ai_extract` — Extraction structurée IA — needs anchor : oui
- `ai_classify` — Classification — needs anchor : non
- `ai_analyze_text` — Analyse libre — needs anchor : non
- `ai_custom` — Appel IA libre avec system prompt — needs anchor : non
**LLM via DAGExecutor (parallèle)** :
- `llm_analyze` / `llm_translate` / `llm_extract_data` / `llm_generate` — needs anchor : non
**Fichiers** :
- `file_list_dir` / `file_create_dir` / `file_move` / `file_copy` / `file_sort_by_ext` — needs anchor : non
**Validation** :
- `verify_element_exists` — needs anchor : oui
- `verify_text_content` — needs anchor : oui
### 4.3 Intégration avec Léa
Le VWB **ne pousse pas** un workflow à Léa : il l'**enregistre** côté streaming server. Mécanisme :
1. Workflow sauvé en SQLite VWB (`workflows.db`).
2. `POST /api/v3/workflow/{id}/export-for-lea` (`learned_workflows.py:413`) sérialise et envoie au streaming server (proxy `STREAMING_SERVER_URL=http://localhost:5005`).
3. Lancement : frontend appelle `POST /api/v3/execute/start` (`execute.py:1528`) qui transite vers `POST /api/v1/traces/stream/replay` côté streaming server.
4. Léa V1 récupère ensuite les actions une à une via son polling `GET /replay/next` (cf. §1).
### 4.4 Bibliothèque de captures
Disponible. Architecture v2 (avril 2026) :
- PNG HD écrit dans `data/library_captures/{id}.png` (source de vérité)
- `data/capture_library.json` = métadonnées + thumbnail base64 640×360 q85 (rapide à charger pour la grille)
- Endpoints : `GET/POST /api/v3/capture/library`, `POST /api/v3/capture/library/upload`, `GET /api/v3/capture/library/{id}/full`, `DELETE /api/v3/capture/library/{id}`
- Permet à l'utilisateur de réutiliser des captures (ancres) entre workflows sans recapturer.
---
## 5. Capacités de l'agent_chat
### 5.1 Endpoints
23 routes Flask dans `agent_chat/app.py` :
- `GET /` — UI principale chat
- `GET /classic` — UI classique
- `GET /api/status` — Statut serveur
- `GET /api/workflows` — Liste workflows disponibles
- `POST /api/workflows/refresh` — Recharger
- `GET /api/machines` — Liste machines
- `POST /api/search` — Recherche workflow
- `POST /api/execute` — Exécuter un workflow nommé
- `GET /api/history` — Historique conversations
- `POST /api/chat` — Endpoint chat principal (routage NLP)
- `POST /api/gpu/<action>` — Contrôle GPU (start/stop/status)
- `GET /api/llm/status` — Statut Ollama
- `POST /api/llm/model` — Changer modèle actif
- `POST /api/agent/plan` — Planifier (autonomous_planner)
- `POST /api/agent/execute` — Lancer plan
- `GET /api/agent/status` — Statut agent
- `GET /api/gestures` — Catalogue de gestures réflexes
- `POST /api/chat/upload` — Upload pièce jointe
- `GET /api/help` — Aide
- `POST /api/urgences/parse` — Parsing intent "traite N dossiers" (gemma3:1b)
- `POST /api/urgences/start` — Démarre l'orchestrateur urgences
- `GET /api/urgences/status/<orch_id>` — État orchestrateur
- `GET /api/urgences/list` — Liste orchestrations en cours
### 5.2 Cas d'usage métier
- **Orchestration urgences GHT** (`urgences_orchestrator.py`) : reçoit "traite N dossiers" en chat, parse via `gemma3:1b`, ouvre Chrome (Win+R) sur la maquette Easily Assure via `/replay/raw`, extrait la liste IPP avec `extract_table`, puis pour chaque IPP lance le workflow `Urgence_unit` via `/replay` avec `variables={"patient_id": ipp}`. Synthèse finale postée dans le chat. État pollable via `/api/urgences/status/<id>`.
- **Recherche/exécution workflow par nom naturel** (`/api/search` + `/api/execute`) — résolution sémantique nom utilisateur → workflow_id.
- **Plan autonome** (`/api/agent/plan` + `/api/agent/execute`) — `autonomous_planner.py` planifie un workflow inédit à partir d'un objectif libre via `qwen2.5:7b`.
### 5.3 Modèles LLM utilisés
- `gemma3:1b` — NLP intent parsing urgences (`urgences_orchestrator.py:58`, env `LEA_NLP_MODEL`)
- `qwen2.5:7b` — chat principal + autonomous_planner (`app.py:229,319`, `intent_parser.py:283,690`)
- `qwen3:8b` — modèle Léa par défaut env `LEA_LLM_MODEL` (`app.py:675`), avec `think=False` désactivé (qwen3)
---
## 6. Modules orphelins (code présent mais non câblé)
| Module | Chemin | Pourquoi orphelin (factuel) | Mentionné en commit ou doc ? |
|---|---|---|---|
| `core/grounding/fast_pipeline.py` | `core/grounding/` | Référencé uniquement par `core/execution/observe_reason_act.py:1639` (lui-même semi-orphelin, voir ci-dessous). Zéro import depuis `agent_v0/server_v1/`, `visual_workflow_builder/backend/`, `agent_chat/`. | commit `b30d4b665` (Phase 4 FAST→SMART→THINK) |
| `core/grounding/fast_detector.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `ea36bba5c` (Phase 1-2) |
| `core/grounding/smart_matcher.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `ea36bba5c` |
| `core/grounding/think_arbiter.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `e4a48e78b` (Phase 3) |
| `core/grounding/shadow_learning_hook.py` | `core/grounding/` | Zéro import dans `agent_v0/server_v1/`, `visual_workflow_builder/`, `agent_chat/`. | commit `73cea2385` (Phase 6) ; mémoire mentionne "ShadowLearningHook non branché" |
| `core/grounding/template_matcher.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `9da589c8c` (création) |
| `core/grounding/pipeline.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `9da589c8c` |
| `core/grounding/element_signature.py` | `core/grounding/` | Zéro import depuis le code actif. | commit `e4a48e78b` |
| `core/grounding/server.py` (Flask 8200) | `core/grounding/` | Daemon Flask single-thread alternatif à `infigui_server.py` (Unix socket). Pas de service systemd actif pointant dessus. | doc `tools/start_grounding_server.sh` (toujours obsolète, pointe UI-TARS) |
| `core/detection/seeclick_adapter.py` | `core/detection/` | Encore exporté par `core/detection/__init__.py` mais zéro call site actif. Signalé "cassé" par commit `d1b556b6c`. | commit `21bfa3b33` (création) ; `d1b556b6c` (suppression call site) |
| `core/learning/target_memory_store.py` | `core/learning/` | Référencé par `agent_v0/server_v1/replay_memory.py:62` et `replay_learner.py:210`**pas orphelin** (semi-actif via replay_memory). | mémoire "V3/V4 découplés au runtime" |
| `core/learning/continuous_learner.py` | `core/learning/` | Zéro import depuis code actif. | — |
| `core/learning/feedback_processor.py` | `core/learning/` | Zéro import. | — |
| `core/learning/versioned_store.py` | `core/learning/` | Zéro import. | — |
| `core/execution/target_resolver.py` | `core/execution/` | Zéro import depuis code actif. | mémoire "TargetResolver cross-frame bug" |
| `core/execution/target_memory.py` | `core/execution/` | Zéro import. | — |
| `core/execution/action_executor.py` | `core/execution/` | Zéro import. | — |
| `core/execution/execution_robustness.py` | `core/execution/` | Zéro import. | — |
| `core/execution/recovery_strategies.py` | `core/execution/` | Zéro import. | — |
| `core/execution/observe_reason_act.py` | `core/execution/` | Importé par `visual_workflow_builder/backend/api_v3/execute.py:1431,1955` (mode `verified` ORALoop). Pas pleinement orphelin mais activé seulement dans ce mode. | mémoire "Phase 5 intégration FAST→SMART→THINK dans ORA" |
| `core/healing/healing_engine.py` + `confidence_scorer.py` + `recovery_logger.py` + `learning_repository.py` | `core/healing/` | Zéro import depuis `agent_v0/server_v1/` et `visual_workflow_builder/backend/api_v3/`. Seul `execution_integration.py` est référencé (2 occurrences). | — |
| Service systemd `rpa-streaming.service` | `deploy/systemd/` | Présent dans le repo mais `/etc/systemd/system/rpa-streaming.service.parked`**inactif** sur la machine de Dom. | — |
| Service systemd `rpa-grounding.service` | `deploy/systemd/` | `/etc/systemd/system/rpa-grounding.service.parked`**inactif**. | commit `3d6868f02` |
| Service systemd `rpa-vision-v3-api.service` / `rpa-vision-v3-worker.service` / `rpa-vision-v3-dashboard.service` / `rpa-agent-chat.service` | `deploy/systemd/` | Tous trouvés `.parked` dans `/etc/systemd/system/`. | — |
| `agent_v0/server_v1/safety_checks_provider.py` | `agent_v0/server_v1/` | **Pas orphelin** : importé par `api_stream.py:2980` (QW4 build_pause_payload). Listé pour contexte. | mémoire "QW4 safety_checks hybrides" |
| Endpoints `/api/v1/shadow/*` | `agent_v0/server_v1/api_stream.py:1661-1820` | Définis côté serveur, **aucun appelant identifié** dans `agent_v0/agent_v1/` (Léa client) ni dans `visual_workflow_builder/`, ni dans `agent_chat/`. | — [À VÉRIFIER PAR DOM] |
---
## 7. À vérifier avec Dom (synthèse des `[À VÉRIFIER PAR DOM]`)
- **Modes Léa "shadow / copilot / assisté"** : seuls les booléens `_recording` / `_replay_active` existent côté client. Confirme-tu qu'aujourd'hui Léa V1 n'a effectivement que ces deux modes runtime (et que les modes VWB `basic/intelligent/debug/verified` ne pilotent rien du client) ?
- **Endpoints `/api/v1/shadow/*`** côté serveur : zéro appelant identifié dans le repo. Sont-ils consommés par un script externe / une démo, ou candidats à archivage ?
- **Service `rpa-grounding.service`** : présent dans `deploy/systemd/` mais en `.parked` sur la machine. La cascade vLLM→Ollama tourne donc sans `infigui_server.py` ? Confirmer que le grounding Transformers est bien désactivé en prod actuellement.
- **Service `rpa-streaming.service`** : trouvé `.parked` dans `/etc/systemd/system/`. Le streaming server tourne-t-il via `svc.sh` / `run.sh` au lieu de systemd ?
- **`core/detection/seeclick_adapter.py`** : encore exporté par `__init__.py` mais signalé cassé. Sortir de l'export ou tenter une réparation pour Qwen3-VL ?
- **`core/detection/owl_detector.py` (Owlv2)** : câblé via `ui_detector.py` mais aucun bench récent. Encore appelé en prod ou candidat à l'archivage ?
- **vLLM (port 8100)** : code prêt dans `resolve_engine.py:785-816`. Confirmer si vLLM tourne actuellement ou si la cascade saute systématiquement à Ollama.
- **Mode VWB `verified`** : seul mode qui active `core/execution/observe_reason_act.py` (ORALoop). Est-il utilisé en démo GHT ou réservé au debug ?