# AccessMiner AI — MVP socle

Scanner de bases Microsoft Access qui produit un fichier projet `.amproj`
(SQLite autonome) contenant tout ce qu'on a pu extraire : schéma, VBA,
formulaires, états, macros, relations formelles et relations implicites
reconstituées depuis les JOIN SQL.

## Principe de travail (rappel ADR-022 v2)

On ne scanne **jamais** les bases originales. Pour chaque run de test,
Claude prépare un script PowerShell dans `mvp/runs/run_<timestamp>.ps1`
qui copie les bases sélectionnées vers `C:\ACCESS\tests\run_<timestamp>\`,
active le venv, et lance le scan. Marcel n'a qu'à double-cliquer le
script (ou le lancer dans PowerShell) — aucune manipulation de fichier.

L'output (`.amproj` + log) est écrit dans `mvp/runs/run_<timestamp>/`
pour que Claude puisse le relire immédiatement.

## 1. Pré-requis système (Windows)

- Windows 10/11, 64 bits
- **Access 2016+ ou Microsoft Access Runtime** installé (fournit le driver ACE + le moteur COM)
- Python **3.11+** 64 bits (déjà en place chez Marcel : 3.11.2)
- Accès au registre COM (lancer en session utilisateur normale, pas en admin)

## 2. Installation du venv

Un *virtual environment* (venv) est un Python isolé, dédié à ce projet.
Ça évite que les bibliothèques d'AccessMiner viennent polluer ton Python
système ou soient cassées par une autre mise à jour.

```powershell
# Depuis le dossier mvp/
cd "C:\Users\kamch\Dropbox\Mes sociétés\GMK Consulting\13 - Produits\AccessMiner AI\05 - Code Source\mvp"

# Création du venv (une seule fois)
python -m venv .venv

# Activation (à refaire à chaque nouveau PowerShell)
.\.venv\Scripts\Activate.ps1

# Tu dois voir (.venv) au début du prompt

# Installation des dépendances (une seule fois)
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```

Pour quitter le venv : `deactivate`.

## 3. Lancement d'un scan

```powershell
# venv activé
python -m accessminer.cli.scan `
    --project "SG3" `
    --client "GMK Consulting" `
    --input "C:\ACCESS\tests" `
    --output "C:\ACCESS\out\sg3.amproj"
```

Le fichier `sg3.amproj` est une base SQLite portable. Tu peux l'ouvrir
avec **DB Browser for SQLite** pour inspecter le contenu.

## 4. Structure du package

```
mvp/
├── requirements.txt
├── README.md                  ← ce fichier
└── accessminer/
    ├── __init__.py            ← version, docstring
    ├── parsing/
    │   ├── __init__.py
    │   ├── schema.py          ← pyodbc : tables, colonnes, index
    │   ├── com_layer.py       ← COM   : VBA, forms, reports, macros, relations
    │   └── sql_joins.py       ← sqlparse : reconstruction FK implicites
    ├── storage/
    │   ├── __init__.py
    │   ├── schema.sql         ← schéma SQLite .amproj
    │   └── store.py           ← ProjectStore (API de persistance)
    └── cli/
        ├── __init__.py
        └── scan.py            ← `python -m accessminer.cli.scan`
```

## 5. Ce qui est extrait

| Objet             | Source          | Notes                                  |
|-------------------|-----------------|----------------------------------------|
| Tables            | pyodbc          | hors `MSys*` et `~`                    |
| Colonnes          | pyodbc          | type, taille, nullable, ordinal        |
| Index             | pyodbc          | unique / non-unique                    |
| Tables liées ODBC | COM (Connect)   | backlog #2                             |
| Requêtes (SQL)    | COM (QueryDefs) |                                        |
| Relations FK      | COM (Relations) | confiance 1.0                          |
| FK implicites     | sqlparse        | reconstitué depuis JOIN, conf 0.8-0.95 |
| Modules VBA       | COM (VBE)       | code intégral                          |
| Formulaires       | COM (AllForms)  | RecordSource, contrôles, événements    |
| Etats             | COM (AllReports)|                                        |
| Macros            | SaveAsText      | contenu texte, backlog #1              |

## 6. Backlog POC → MVP : status

- [x] #1 : Contenu des macros via `SaveAsText acMacro`
- [x] #2 : Détection tables liées ODBC (`TableDefs.Connect`)
- [x] #3 : Reconstruction FK implicites depuis JOIN
- [x] #4 : Parsing SQL inline (queries + record sources)
- [x] #5 : Normalisation nom d'objet (accents, espaces) dans `store.normalize_name`
- [x] #7 : try/except par objet (backlog robustesse)
- [x] #8 : Détection base protégée par mot de passe
- [ ] #6 → v1.1 : optimisation boucle COM
- [ ] #9 → à exécuter sur base > 500 Mo pendant le POC final (8000 SG3 Gestion, slf_sg3_impexp2)

## 7. Enrichissement IA (jalon 2)

Une fois le `.amproj` produit par `scan`, on peut le faire enrichir par une
IA (OpenAI gpt-4o-mini par défaut) pour :

- générer une **description métier** (1-2 phrases FR) de chaque table,
  requête, formulaire, état, macro, module VBA ;
- proposer un ou deux **process métier** d'appartenance, avec un niveau de
  confiance ; les suggestions ≥ 90 % sont auto-acceptées, les autres
  arrivent dans l'onglet "Suggestions à valider" du viewer.

### Configuration

Crée un fichier `.env` à la racine de `mvp/` (le `.gitignore` l'exclut) :

```
OPENAI_API_KEY=sk-proj-...
OPENAI_MODEL=gpt-4o-mini   # optionnel
```

### Lancement

```powershell
# Mode complet : descriptions + suggestions de process
python -m accessminer.cli.enrich "runs\run_xxx\projet.amproj"

# Mode description seule (idempotent : ne re-décrit pas les déjà décrits)
python -m accessminer.cli.enrich "runs\run_xxx\projet.amproj" --describe-only

# Plus rapide : 8 batches en parallèle (3-5x plus rapide qu'en séquentiel)
python -m accessminer.cli.enrich "runs\run_xxx\projet.amproj" --workers 8

# Test rapide sur 20 objets
python -m accessminer.cli.enrich "runs\run_xxx\projet.amproj" --limit 20

# Tous les flags
python -m accessminer.cli.enrich projet.amproj \
    --provider openai \
    --threshold 0.90 \
    --batch-size 10 \
    --workers 4 \
    --kinds table,query,module,form,report,macro \
    --describe-only \
    --force-redescribe \
    --limit 50 \
    --dry-run
```

### Optimisation de la performance

Le pipeline parallélise les appels HTTP via un `ThreadPoolExecutor` (defaut
4 workers). Les écritures SQLite restent dans le thread principal pour
éviter les conflits single-writer. Repères mesurés sur ~1500 objets :

| Workers | Durée approx. | Speedup |
|---------|---------------|---------|
| 1       | ~19 min       | 1x      |
| 4       | ~5 min        | ~3.5x   |
| 8       | ~3 min        | ~6x     |

Au-delà de 8 workers, on est limité par les rate limits OpenAI tier 1
(500 RPM sur gpt-4o-mini). Coût constant ≈ $0.05-0.10 pour 1500 objets.

### Visualisation

```powershell
python -m accessminer.cli.view "runs\run_xxx\projet.amproj"
```

Onglet **Process** : badge "X objets décrits par IA", clic sur un process
pour le drilldown groupé par nature, clic sur une suggestion pendante pour
voir le contenu de l'objet et trancher.

Les listes Tables / Requêtes / Formulaires / États / Macros / Modules
affichent la colonne **Description IA** dès qu'au moins une description
existe pour ce kind.

## 8. Lineage métier — détection déterministe (couche 1)

Une fois le `.amproj` produit par le scan (et éventuellement enrichi par
l'IA), on peut lancer le **détecteur de flux de données**. Cette couche
parse déterministiquement les queries, modules VBA, macros, formulaires
et tables liées pour reconstituer les **inputs** et **outputs** métier
de chaque objet.

Elle ne consomme aucune API externe — c'est le cœur de propriété
intellectuelle d'AccessMiner AI, déployable on-premise sans dépendance.

### Lancement

```powershell
python -m accessminer.cli.lineage "runs\run_xxx\projet.amproj"

# Pour vider object_io avant de relancer (après changement de règles)
python -m accessminer.cli.lineage "runs\run_xxx\projet.amproj" --reset
```

Durée typique : quelques secondes pour 1500 objets (pas d'I/O réseau).

### Ce qui est détecté

| Source | Mécanisme détecté | Direction |
|---|---|---|
| `table.link_type=linked_odbc` | `odbc_link` (SAP/SQL Server/AS400…) | input |
| `table.link_type=linked_accdb` | `access_link` (base Access externe) | input |
| `table.link_type=linked_other` | `file_link` (Excel, TXT…) | input |
| Query `INSERT INTO` | `sql_insert` | output |
| Query `UPDATE ... SET` | `sql_update` | output |
| Query `DELETE FROM` | `sql_delete` | output |
| Query `SELECT ... INTO` | `sql_maketable` | output |
| Query `FROM` / `JOIN` | `sql_read` | input |
| Form avec `RecordSource` | `user_form` (saisie utilisateur) | input |
| VBA `DoCmd.TransferText acImport*` | `file_import_text` | input |
| VBA `DoCmd.TransferText acExport*` | `file_export_text` | output |
| VBA `DoCmd.TransferSpreadsheet acImport*` | `file_import_excel` | input |
| VBA `DoCmd.TransferSpreadsheet acExport*` | `file_export_excel` | output |
| VBA `DoCmd.OutputTo` | `output_to` | output |
| VBA `DoCmd.SendObject` | `email_send` | output |
| VBA `DoCmd.RunSQL "..."` | décompose le SQL et log | output |
| VBA `OpenRecordset` + `.AddNew/.Edit/.Delete` | `vba_recordset_write` | output |
| VBA `OpenRecordset` sans écriture | `vba_recordset_read` | input |
| Macro `TransferText` / `TransferSpreadsheet` | idem VBA | in/out |
| Macro `OutputTo` / `SendObject` | idem VBA | output |
| Macro `OpenQuery` | `sql_read` (cible la requête) | input |
| Macro `RunSQL` | décompose le SQL et log | output |

Chaque ligne `object_io` contient `object_id`, `direction`, `mechanism`,
`target` (nom de table, chemin fichier…), `evidence` (extrait du code
qui a déclenché la détection) et `confidence` (1.0 déterministe,
0.6-0.9 heuristique).

### Couche 2 : synthèse IA par process (livrée Session 4)

La couche 2 agrège les `object_io` de tous les objets taggués dans un
process métier, les envoie à l'IA (gpt-4o-mini) avec les descriptions
déjà générées, et produit 4 sections narratives en français par
process : entrées métier, sorties métier, règles métier reconstituées,
flux séquentiel. Stockage dans `process_analysis`.

```powershell
# Détection déterministe (couche 1) + synthèse IA (couche 2)
python -m accessminer.cli.lineage "C:\ACCESS\out\sg3.amproj" --synthesize --workers 4

# Synthèse IA seule (si la couche 1 est déjà OK)
python -m accessminer.cli.lineage "C:\ACCESS\out\sg3.amproj" --synthesize-only --workers 4
```

## 10. Export Word — dossier métier par process (Session 4)

Pour chaque process métier accepté, génère un `.docx` structuré en 8
sections : page de garde, synthèse, entrées métier, sorties métier,
règles métier, flux principal (couche 2 IA), entrées détectées, sorties
détectées (couche 1 déterministe), et la liste des objets Access
rattachés. Pour chaque table listée, le document affiche aussi
« Alimentée par » (macros, queries, modules VBA qui y écrivent) et
« Lue par » (objets qui la consomment), grâce à `object_io`.

Dépendance : `python-docx` (déjà dans `requirements.txt`).

```powershell
# Tous les process du projet (skip les vides, sortie par défaut dans <amproj>/exports/word/)
python -m accessminer.cli.export_word "C:\ACCESS\out\sg3.amproj"

# Un seul process (par ID numérique)
python -m accessminer.cli.export_word "C:\ACCESS\out\sg3.amproj" --process 3

# Dossier de sortie personnalisé + inclure les process sans objet rattaché
python -m accessminer.cli.export_word "C:\ACCESS\out\sg3.amproj" --out livrables\ --include-empty
```

Les fichiers sont nommés `process_<NN>_<slug>.docx` (par exemple
`process_03_facturation_client.docx`), un par process.

## 11. Export PPTX — synthèse management (Session 5)

Génère une présentation PowerPoint orientée management : KPIs globaux,
répartition par type d'objet, 1 slide par process avec synthèse IA,
slide d'alertes qualité, conclusion.

```powershell
python -m accessminer.cli.export_pptx "C:\ACCESS\out\sg3.amproj"
python -m accessminer.cli.export_pptx "C:\ACCESS\out\sg3.amproj" --out livrables\
```

## 12. Détection de patterns (Session 6)

Lance 4 détecteurs sur le `.amproj` pour identifier les problèmes
de qualité : clones de schéma, requêtes cassées, objets orphelins,
VBA mort. Les résultats sont persistés dans la table `findings`.

```powershell
python -m accessminer.cli.detect "C:\ACCESS\out\sg3.amproj"
```

Les findings sont visibles dans l'onglet **Alertes** du viewer et
intégrés automatiquement dans les exports Word et PPTX.

## 13. Export DOT — graphe Graphviz (Session 6)

Exporte le graphe de relations (FK formelles, JOIN implicites,
utilisation par formulaires) au format DOT pour visualisation Graphviz.

```powershell
# Vers stdout
python -m accessminer.cli.export_dot "C:\ACCESS\out\sg3.amproj"

# Vers un fichier
python -m accessminer.cli.export_dot "C:\ACCESS\out\sg3.amproj" --out relations.dot

# Filtrer par type d'edge
python -m accessminer.cli.export_dot "C:\ACCESS\out\sg3.amproj" --kinds joins_on,links_fk
```

Pour visualiser : installer Graphviz (https://graphviz.org), puis
`dot -Tpng relations.dot -o relations.png` ou ouvrir dans un viewer
en ligne comme https://dreampuf.github.io/GraphvizOnline.

## 14. Estimation du coût de scan (Session 6)

Avant de lancer un scan, estime le nombre d'objets et le temps requis
en ouvrant chaque base rapidement via DAO (< 1s/base).

```powershell
python -m accessminer.cli.estimate C:\ACCESS\bases
python -m accessminer.cli.estimate C:\ACCESS\bases --rate 60
```

Affiche le détail par base (objets, taille, ETA) et une estimation
du pipeline complet (scan + enrich + lineage + exports).

## 15. Installation automatisée

```powershell
# Clic droit > Exécuter avec PowerShell, ou :
.\install.ps1
```

Le script vérifie Python 3.11+, détecte Access/ACE, crée le venv,
installe les dépendances, et affiche un résumé des commandes.

## 9. Dépannage rapide

- **"pyodbc non installé"** alors que tu l'as installé : tu as utilisé un
  autre Python que celui du venv. Active le venv (`.\.venv\Scripts\Activate.ps1`)
  avant `pip install`.
- **"Cannot open database"** : la base est verrouillée par un Access
  ouvert en parallèle. Ferme Access et relance.
- **"Not a valid password"** : base protégée par mot de passe, pas prise
  en charge par le MVP (marquée `failed` dans `scan_status`).
- **"No module named 'docx'"** lors de `export_word` : `python-docx` n'est
  pas installé dans le venv. Lance `pip install python-docx` (venv activé)
  ou réinstalle l'ensemble des dépendances avec `pip install -r requirements.txt`.
- **"OPENAI_API_KEY not set"** lors de `enrich` ou `lineage --synthesize` :
  la clé API n'est pas chargée. Crée un fichier `.env` à la racine du `mvp/`
  avec `OPENAI_API_KEY=sk-...` (jamais commité), ou passe `--env` pour
  pointer vers un autre emplacement. La couche 1 (`lineage` sans
  `--synthesize`) et l'export Word fonctionnent **sans** clé API.
