Files
rpa_vision_v3/docs/QG_REVIEW_D1_NAVIGATE_COORDS_2026-07-02.md
Dom 931cf13217 feat(navigate): jalon partiel D1 — compile navigate + coercion coords sûre
Ferme Gap C : _edge_to_normalized_actions produit désormais une action navigate
(handler serveur atteignable). Ajoute _coerce_action_coords : cast x_pct/y_pct en
float APRÈS résolution des templates, JAMAIS de fallback (0,0) — template non
résolu / valeur invalide → pause_for_human (safety_level=high). Non-régression
prouvée sur mouse_click classiques (idempotent sur floats).

⚠️ NE FERME PAS le write-only : Gap A (P1-B) non livré — aucun step click/type ne
déclare encore consommer navigate_login_coords. TestCompilerGapLiteralFloats
assert l'état ouvert. Boucle complète = chantier suivant (P1-B + test e2e edge→action).

21 tests verts, boot OK. Revue croisée Claude (GO jalon partiel).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 18:49:32 +02:00

7.6 KiB

QG Review Framework — D1 NavigateCoords Patch

Auteur: Qwen
Date: 2026-07-02
Statut: EN ATTENTE patch Codex
Scope: Review du patch D1 (Option 1 — Compiler Injection) produit par Codex


Baseline test coverage (pré-patch)

Fichier Classes Tests Rôle
test_navigate_handler_e2e.py 4 8 Handler mock — nominal, OCR miss, no screenshot, never-fail
test_navigate_wiring.py 4 5 Import/wiring non-regression
test_action_resolver.py 6 10 NavigateCoords, NavigateResult, grounded_to_coords, navigate_login
test_coords_consumption_gap.py 3 10 GAP DOCUMENTATION — résolution viable, compiler gap, navigate→[]
Total 17 33

Tests critiques à mettre à jour après D1 patch:

  • test_coords_consumption_gap.py::test_navigate_action_type_unknown — affirme actuellement actions == []; doit affirmer len(actions) >= 1 et actions[0]["type"] == "navigate" après D1
  • test_coords_consumption_gap.py::TestCompilerGapLiteralFloats — 4 tests documentant le gap literal-floats; après D1, les tests coords_var doivent affirmer templates strings ARE produites quand coords_var présent

Point d'insertion exact D1:

  • Fichier: replay_engine.py
  • Entre elif action_type == "llm_generate" (retourne [normalized] ~L1949) et else: clause (~L1953)
  • Navigate branch: elif action_type == "navigate"normalized["type"] = "navigate" + parameters dict → return [normalized]

P1-C root cause:

  • _resolve_runtime_vars_in_str (L2025): return str(value) — tout {{var.field}} résolu devient string "0.35" pas float 0.35
  • Coercion helper _coerce_action_coords doit agir APRÈS _resolve_runtime_vars (L4335), AVANT type_ = action.get("type") (L4337)

Critères de review — Checklist

C1 : Branche navigate dans _edge_to_normalized_actions (Gap C)

# Critère GO NOGO
C1-1 Branche elif action_type == "navigate" ajoutée entre llm_generate (L1949) et else (L1951) Present, position correcte Absente ou mal positionnée
C1-2 normalized["type"] = "navigate" Oui Type incorrect
C1-3 Parameters dict avec login_coords_var, password_coords_var, submit_coords_var Noms exacts, valeurs default Noms divergent ou absents
C1-4 Retourne [normalized] (1 action serveur-side) [normalized] [] ou autre
C1-5 Test TR-1 : test_navigate_action_type_unknown mis à jour — affirme len(result) >= 1 et result[0]["type"] == "navigate" Test updated + passes Test non mis à jour ou fails

C2 : coords_var dans branches mouse_click / text_input (Gap A)

# Critère GO NOGO
C2-1 coords_var = action_params.get("coords_var") check dans mouse_click Present Absent
C2-2 Si coords_var → x_pct = f"{{{{{coords_var}.x_pct}}}" et y_pct = f"{{{{{coords_var}.y_pct}}}" Template strings correctes Syntaxe template incorrecte ou .y_pct pour x_pct
C2-3 Si coords_var absent → literal floats comme avant (fallback existant) Branch else intacte Branch else modifiée ou supprimée
C2-4 normalized["coords_var"] = coords_var ajouté pour traçabilité Oui Absent
C2-5 Même mécanisme dans text_input branch Identique à mouse_click Absent ou divergent
C2-6 BUG vérifié : text_input x_pct template = {{coords_var.x_pct}} (pas .y_pct deux fois) Correct y_pct en double

C3 : _coerce_action_coords() helper (Gap B / P1-C)

# Critère GO NOGO
C3-1 Helper défini dans api_stream.py (pas replay_engine.py) api_stream.py Autre fichier
C3-2 Appel APRÈS _resolve_runtime_vars (L4335), AVANT type_ = action.get("type") (L4337) Position correcte Avant resolver ou après type_ check
C3-3 float pass-through : isinstance(val, float) → continue Idempotent sur actions existantes Pas de float check → conversion inutile
C3-4 string→float : try: action[key] = float(val) Conversion correcte Pas de try/except → crash possible
C3-5 Template non résolu → pause_for_human (pas fallback 0.0/0.0) val.startswith("{{") and val.endswith("}}") → pause_for_human Fallback 0.0/0.0 ou autre coords dangereux
C3-6 Conversion impossible → pause_for_human ValueError/TypeError → pause_for_human Exception non catchée
C3-7 _skip_reason documenté pour debug Oui Absent
C3-8 safety_level = "high" pour pause_for_human Oui Absent ou autre valeur
C3-9 Retourne action mutée (pas de new dict) Mutation in-place Copie → risque race
C3-10 Keys itérées = ("x_pct", "y_pct") uniquement Pas de sur-itération Autres keys modifiées

C4 : Never-fail contract

# Critère GO NOGO
C4-1 _handle_navigate_action ne lance jamais d'exception non catchée Contract preserved Nouvelle exception possible
C4-2 _coerce_action_coords ne lance jamais — tout cas couvert par try/except ou pause_for_human Contract preserved Exception possible

C5 : Limites de scope POC

# Critère GO NOGO
C5-1 Maximum 4 fichiers modifiés ≤ 4 > 4
C5-2 Pas de changement schema VWB dans POC patch Pas de modification VWB code VWB code modifié
C5-3 Pas de nouvelle dépendance pip 0 nouvelles deps Nouvelle dep
C5-4 Pas de modification OmniParser wiring _omniparser_available = False intact Modifié

C6 : Test coverage

# Critère GO NOGO
C6-1 TR-1 : navigate compile à 1 action (pas []) Passes Fails
C6-2 TR-2 : coords_var template resolution + float conversion Passes Fails
C6-3 Test _coerce_action_coords : float pass-through Passes Absent
C6-4 Test _coerce_action_coords : string→float conversion Passes Absent
C6-5 Test _coerce_action_coords : template non résolu → pause_for_human Passes Absent
C6-6 Test _coerce_action_coords : conversion impossible → pause_for_human Passes Absent
C6-7 Test idempotence : action existante float non modifiée Passes Absent
C6-8 pytest tests/unit/ passe en intégralité 0 failures ≥1 failure

C7 : Risques additionnels (3 identifiés dans PLAN_D1)

# Risque Mitigation attendue GO NOGO
C7-1 Résolution partielle (x_pct résolu, y_pct template) _coerce_action_coords → pause_for_human si ANY key unresolved Mitigation presente Pas de mitigation
C7-2 Idempotence sur mouse_click existant isinstance(val, float) → continue Idempotent Risque de double conversion
C7-3 Race condition sur variables dict partagé BFS séquentiel garantit navigate→click ordre Note dans code/doc Pas de mention

Procédure de review

  1. Lire le patch : git diff sur les fichiers modifiés par Codex
  2. Vérifier chaque critère C1-C7 : GO/NOGO par ligne
  3. Exécuter les tests : cd /home/dom/ai/rpa_vision_v3 && .venv/bin/python -m pytest tests/unit/ -x -v
  4. Produire le verdict : Table GO/NOGO avec justification + verdict global

Format verdict

## QG Verdict — D1 NavigateCoords Patch

| Critère | GO/NOGO | Note |
|---------|---------|------|
| C1      | GO      | Branche navigate correcte |
| C2      | NOGO    | BUG: y_pct en double dans text_input |
| ...     | ...     | ... |

**Verdict global**: GO / NOGO (avec réserves listées)

Qwen — framework QG prêt, awaiting Codex patch pour exécution.