Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .GCC/branches/plan_modular_architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Execution Plan: Modular Architecture Scaffolding (Issue #129)

## 📋 Target Invariant & Pre-requisites
- **Target Invariant**: CI 100% vert (Ruff, Mypy, Pytest). Arborescence modulaire importable.
- **Pre-requisites**: Branche `refactor/modular-architecture-issue-129`. Restauration complète du contexte (Protocole A) validée avant toute modification hors `.GCC/`.

## 🛠️ Step-by-Step Sequence

### Step 0: Validation des prérequis et verrouillage d'alignement (Protocole A)
- [x] **Action**: Vérification de l'alignement GCC et interdiction de modifications hors `.GCC/` avant confirmation.
- [x] **Verify**: `python3 -c "c1 = open('.GCC/main.md', encoding='utf-8').read(); c2 = open('.GCC/resume.md', encoding='utf-8').read(); assert len(c1) > 100 and len(c2) > 100; print('PASS')"`
- **Verification Proof**:
```text
PASS
```

### Step 1: Restauration du macro-état projet (Protocole A - Étape 1)
- [x] **Action**: Lecture de `.GCC/main.md` pour charger les objectifs, milestones et branches actives.
- [x] **Verify**: `python3 -c "content = open('.GCC/main.md', encoding='utf-8').read(); assert len(content) > 100 and '## 🎯 Objective' in content; print('PASS')"`
- **Verification Proof**:
```text
PASS
```

### Step 2: Restauration de l'état de transition technique (Protocole A - Étape 2)
- [x] **Action**: Lecture de `.GCC/resume.md` pour charger les directives de transition immédiates.
- [x] **Verify**: `python3 -c "content = open('.GCC/resume.md', encoding='utf-8').read(); assert len(content) > 100 and '## 🎯 Functional Outcome' in content; print('PASS')"`
- **Verification Proof**:
```text
PASS
```

### Step 3: Déploiement arborescence et modules initiaux
- [x] **Action**: `mkdir -p gui_agent/{core,layers,utils}` et création des modules initiaux typés.
- [x] **Verify**: `python3 -c "import gui_agent.core, gui_agent.layers, gui_agent.utils; print('PASS')"`
- **Verification Proof**:
```text
PASS
```

### Step 4: Ajustement dépendances et validation CI
- [x] **Action**: Ajout de la dépendance conditionnelle `evdev` dans `pyproject.toml`, synchronisation de `uv.lock`, et mise à jour des paquets système dans `install.sh`.
- [x] **Verify**: `uv lock --check && ./ci.sh`
- **Verification Proof**:
```text
$ uv lock --check
Resolved 100 packages in 1ms
```
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 RÉSUMÉ D'EXÉCUTION CI (CI Summary)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| Étape de Validation | Statut | Durée |
|--------------------------------------------|------------|------------|
| Compilation Bytecode Python (compileall) | PASS | 209ms |
| Validation Workflows GitHub Actions | PASS | 82ms |
| Linter de Code (Ruff Check) | PASS | 123ms |
| Formatage de Code (Ruff Format) | PASS | 62ms |
| Typage Statique Strict (Mypy) | PASS | 572ms |
| Suite de Tests Pytest | PASS | 36352ms |
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎉 Toutes les étapes CI sont validées avec succès !
```

## ⚠️ Mitigations & Edge Cases
- **Risk & Mitigation**: Process group SIGKILL et vidange défensive contre les processus orphelins.
11 changes: 8 additions & 3 deletions .GCC/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
- [2026-08-27] Bornage Déterministe et Deadline Globale pour le Listing X11 (PR #55, Confidence Score 5/5 Greptile)

## 🎯 Objective
High-performance, monolithic FastMCP server engineered for direct, low-latency Computer Use on Linux (X11/XWayland) and Windows desktop environments (<50 MB RAM, 21 tools, zero-leak process lifecycle).
High-performance FastMCP server engineered with a decoupled modular architecture (core, layers, utils) for direct, low-latency Computer Use on Linux (X11/XWayland) and Windows desktop environments (<50 MB RAM, 21 tools, zero-leak process lifecycle).

## 🛡️ Protocole de Validation par Pull Request & Critères 5/5 Inviolables
- **Mode de travail exclusif par Pull Request (PR)** : Toute évolution, correctif de sécurité ou refactorisation est développée sur une branche dédiée et soumise via PR.
Expand Down Expand Up @@ -49,6 +49,10 @@ High-performance, monolithic FastMCP server engineered for direct, low-latency C
- *P1 - Course TOCTOU lors de la suppression par chemin* : La séquence `os.stat()` puis `os.unlink(filename, dir_fd)` permet à un attaquant de remplacer l'entrée entre les deux appels et d'entraîner la suppression de son fichier tiers. Solution : bannir la suppression destructive basée sur le nom dans un répertoire concurrent ; retenir le descripteur ouvert de la réservation à l'écriture, ou s'abstenir de tout `unlink` non lié de manière exclusive.

## 🧠 Decisions Made
- [2026-09-11] Architecture Modulaire Découplée (core, layers, utils #129)
- **Context**: Monolithe historique couplant REPL, gestion PTY, drivers bas niveau et helpers.
- **Discarded Options**: Monolithe persistant ; micro-paquets distribués séparément.
- **Rationale**: Découpage en 3 sous-packages (core: REPL/PTY/SDK, layers: accessibilité/fenêtres/entrées/OCR, utils: géométrie/vidéo/cinématique) garantissant isolation et testabilité unitaire sans régression.
- [2026-08-28] Support Bivalent Multi-Versions SDK MCP (1.x et 2.x+)
- **Context**: Dependabot et les environnements clients récents migrent vers `mcp>=2.0.0`. Le test unitaire `test_fastmcp_tools_registration` dépendait d'attributs privés fragiles (`_tool_manager`), et `gui_agent/server.py` restreignait explicitement la compatibilité à la version 1.x.
- **Discarded Options**: Bloquer strictement sur `mcp<2.0.0` (empêche les montées de versions et mises à jour de sécurité de Dependabot) ; réécrire l'intégralité du serveur en MCP bas niveau (complexe et inutile car FastMCP est préservé en v2).
Expand Down Expand Up @@ -107,6 +111,7 @@ High-performance, monolithic FastMCP server engineered for direct, low-latency C
- **Rationale**: Geler la structure jusqu'à la revue utilisateur afin de ne pas invalider les chemins de son audit, et reporter les corrections futures dans l'audit.

## 🌿 Active Branches / Plans
- `refactor/modular-architecture-issue-129` : Déploiement arborescence modulaire (#129) ([plan_modular_architecture.md](branches/plan_modular_architecture.md)).
- `fix/ci-verify-workflows-logic` : Enrichissement de `verify_workflows.py` pour valider la logique métier et les invariants de sécurité des workflows GitHub Actions ([plan_verify_workflows_logic.md](branches/plan_verify_workflows_logic.md)).
- `main` : Stable production release with complete bilingual landing pages, 64/64 Zero-Slop test harness, hardened screenshot rollback lifecycle, bounded X11 timeouts and thread-safe video recording.
- `organize_repo` : Plan de réorganisation et harmonisation gouvernance/CI ([plan_organize_repo.md](branches/plan_organize_repo.md)) — *En attente de revue utilisateur*.
Expand All @@ -123,11 +128,11 @@ High-performance, monolithic FastMCP server engineered for direct, low-latency C
- Fermeture des issues résolues (#42, #56, #69, #106, #70, #68, #63, #59, #46, #45, #13, #107, #43).
- Nettoyage et suppression de l'ensemble des branches résiduelles distantes et locales.
- Validation CI 64/64 tests, quality gate PASS, Greptile CLI 5/5 sur l'arbre de travail.
- 🔄 In progress: Aucun (arbre propre sur `main`).
- 🔄 In progress: refactor/modular-architecture-issue-129 (déploiement de l'arborescence modulaire et durcissement des primitives d'exécution #129).
- ⏳ Pending:
- 1. **Assainissement Gouvernance/CI/Hooks** : Traiter #34 (épinglage versions uv run), #33 (matrice Python 3.10-3.13), #32 (fallback silencieux pip dev) et #24 (Mypy strict).
- 2. **Refactoring Arborescence (#30)** : Migrer vers `src/gui_agent/` selon le plan `plan_organize_repo.md`.
- 3. **Bugs Fonctionnels & Prérequis (#39, #38, #37, #31, #18, #17, #19, #20, #21)**.

## 👉 Next Session Direction
Démarrer le traitement d'une nouvelle issue prioritaire sur une branche dédiée (ex: #34, #39 ou #37).
Finaliser la validation et préparer la fusion de la PR #136.
61 changes: 40 additions & 21 deletions .GCC/resume.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,58 @@
# Session Handoff

## 🎯 Functional Outcome & Task Reality
- **Requested Task**: Rendre le projet compatible avec `mcp>=2.0.0` (support bivalent 1.x et 2.x+) suite aux échecs de CI sur les PRs Dependabot.
- **Requested Task**: Audit, durcissement et validation de la PR #136 (`refactor/modular-architecture-issue-129` : https://github.com/leandre755/gui_agent/pull/136) pour obtenir un score Greptile de 5/5 sans commentaire résiduel, faire approuver et lever toute change request de CodeRabbit (0 finding), et synchroniser la branche distante.
- **Functional Status**: SUCCESS
- **Behavioral Proof**: Exécution intégrale du pipeline `./ci.sh` : 64/64 tests passés avec succès, 0 erreur Mypy, 0 warning Ruff, compilation bytecode propre.
- **Behavioral Proof**:
- `greptile review --json` : Confidence Score 5/5, 0 constat.
- `coderabbit review --agent --base origin/main` : 0 finding sur l'ensemble des 20 fichiers audités.
- `./ci.sh` : 65/65 tests Pytest passés avec succès sous Xvfb, Mypy strict 17 fichiers PASS, Ruff check & format PASS.
- Synchronisation Git distante : commits `4050217` et `113a0ed` poussés sur `origin/refactor/modular-architecture-issue-129`.
- Gouvernance du dépôt : 729 lignes modifiées au total (`git diff --numstat origin/main...HEAD`), strictement sous la limite de 1000 lignes.

## ⚡ Technical Diffs / Atomic Modifications
- **File**: `pyproject.toml`
- **Scope**: Dépendances core
- **Exact Technical Change**: Plage de dépendance élargie de `"mcp>=1.2.0,<2.0.0"` vers `"mcp>=1.2.0,<3.0.0"`.
- **File**: `gui_agent/server.py`
- **Scope**: Import FastMCP
- **Exact Technical Change**: Neutralisation de la mention restrictive "version 1.x" dans le message d'erreur d'importation.
- **File**: `gui_agent/core/pty_session.py`
- **Scope**: Gestionnaire de session pseudo-terminal PTY
- **Exact Technical Change**: Ajout du bornage configurable `max_output_chars` (défaut 1_000_000) dans les boucles de lecture et de vidange, détection de timeout dans la boucle de drain final avec terminaison du groupe de processus (`_kill_pty`), et appel inconditionnel à `_kill_pty(proc)` dans le bloc `finally:` pour éradiquer tout processus orphelin en arrière-plan détaché dans le groupe de session.
- **File**: `gui_agent/utils/coordinates.py`
- **Scope**: `check_display_env`
- **Exact Technical Change**: Utilisation de `not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY")` pour considérer les valeurs vides comme absentes et lever de manière déterministe un `RuntimeError`.
- **File**: `gui_agent/core/repl.py`
- **Scope**: Moteur CodeAct local REPL
- **Exact Technical Change**: Bloc `finally:` garantissant le nettoyage du groupe de processus et la fermeture des descripteurs, factorisation de `_write_input` (complexité cognitive McCabe < 25), et troncature stricte de la sortie via `_clamp_output`.
- **File**: `tests/test_package.py`
- **Scope**: `test_fastmcp_tools_registration`
- **Exact Technical Change**: Implémentation d'une inspection multi-niveaux robuste pour inspecter les 21 outils FastMCP enregistrés (compatible architectures internes v1 et v2).
- **Scope**: Suite de tests unitaires
- **Exact Technical Change**: Ajout de régressions validant le bornage du buffer PTY, l'éradication déterministe d'un processus fils détaché en arrière-plan via `os.kill(bg_pid, 0)`, et la détection d'environnement d'affichage vide.
- **File**: `.GCC/main.md`
- **Scope**: Registre architectural du projet
- **Exact Technical Change**: Mise à jour de la section Objective décrivant l'architecture modulaire découplée (core, layers, utils).
- **File**: `.GCC/branches/plan_modular_architecture.md`
- **Scope**: Plan tactique d'exécution
- **Exact Technical Change**: Restructuration de la séquence (Step 0 prérequis et Steps 1 & 2 consommant l'intégralité des documents de contexte), validation `uv lock --check`, et insertion des preuves brutes de terminal.

## 🛠️ Static Codebase Health
- **Verification Command Run**: `./ci.sh`
- **Linter/Compiler Status**:
- **Linter/Compiler Status**:
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 RÉSUMÉ D'EXÉCUTION CI (CI Summary)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| Étape de Validation | Statut | Durée |
|--------------------------------------------|------------|------------|
| Compilation Bytecode Python (compileall) | PASS | 2194ms |
| Validation Workflows GitHub Actions | PASS | 88ms |
| Linter de Code (Ruff Check) | PASS | 579ms |
| Formatage de Code (Ruff Format) | PASS | 90ms |
| Typage Statique Strict (Mypy) | PASS | 2490ms |
| Suite de Tests Pytest | PASS | 18042ms |
| Compilation Bytecode Python (compileall) | PASS | 258ms |
| Validation Workflows GitHub Actions | PASS | 77ms |
| Linter de Code (Ruff Check) | PASS | 268ms |
| Formatage de Code (Ruff Format) | PASS | 74ms |
| Typage Statique Strict (Mypy) | PASS | 16461ms |
| Suite de Tests Pytest | PASS | 25153ms |
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎉 Toutes les étapes CI sont validées avec succès !
```

## 🚧 Unfinished Work & Technical Failures
- Aucun échec ni bloqueur. Le support 1.x / 2.x+ est opérationnel et validé.
- Aucun bug résiduel. Tous les constats de revue Greptile et CodeRabbit sont résolus à 100%.

## 👉 Handover Directives for the Next Agent
1. **Target File**: `pyproject.toml`
2. **Immediate Action**: Créer la branche / PR pour fusionner la compatibilité `mcp>=1.2.0,<3.0.0`.
3. **Verification Command**: `./ci.sh`
1. **Target File**: `PR #136` sur GitHub
2. **Immediate Action**: Procéder à la fusion (merge) de la PR #136 vers `main`.
3. **Verification Command**: `gh pr view 136`
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ credentials.json
assets/
*.excalidraw
mermaid_diagrams.txt
todo.md

7 changes: 7 additions & 0 deletions gui_agent/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Moteur d'exécution local CodeAct et SDK unifié mcp_core."""

from gui_agent.core.mcp_core import mcp_core
from gui_agent.core.pty_session import PTYSession
from gui_agent.core.repl import execute_script

__all__ = ["PTYSession", "execute_script", "mcp_core"]
30 changes: 30 additions & 0 deletions gui_agent/core/mcp_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""SDK Python unifié mcp_core injecté dans l'espace REPL."""

from __future__ import annotations

from gui_agent import layers


class MCPCoreSDK:
"""Interface unifiée exposant l'ensemble des primitives système."""

activate_window = staticmethod(layers.activate_window)
find_text = staticmethod(layers.find_text)
get_app_state = staticmethod(layers.get_app_state)
key_tap = staticmethod(layers.key_tap)
mouse_click_at = staticmethod(layers.mouse_click_at)
mouse_drag_smooth = staticmethod(layers.mouse_drag_smooth)
mouse_scroll = staticmethod(layers.mouse_scroll)
perform_action = staticmethod(layers.perform_action)
process_list = staticmethod(layers.process_list)
process_run = staticmethod(layers.process_run)
screen_capture = staticmethod(layers.screen_capture)
set_value = staticmethod(layers.set_value)

@property
def mcp_core(self) -> MCPCoreSDK:
return self


mcp_core = MCPCoreSDK()
__all__ = ["MCPCoreSDK", "mcp_core"]
Loading
Loading