# Roadmap Update — Fevrier 2026

**Date**: 2026-02-22 (mise a jour: S3 termine)
**Version courante**: 1.0.0
**DuckDB**: 1.4.1-r.5 (pin exact, compatibilite DuckPGQ v0.2.7)
**MCP SDK**: 1.26.0 (security fixes appliques)

---

## Contexte

Suite a l'audit de compatibilite DuckPGQ (fierce-analyse.md) et a l'audit des dependances,
trois chantiers prioritaires ont ete identifies. L'issue #17 (Mastra Epic) est mise en pause :
l'architecture deposium_MCPs couvre deja la majorite des use cases decrits, et le seul apport
reel de Mastra (HITL/elicitation) est desormais disponible nativement dans le MCP SDK 1.26+.

## Vue d'ensemble

| Chantier                     | Priorite | Effort estime | Cible   | Statut  |
| ---------------------------- | -------- | ------------- | ------- | ------- |
| S1: Stabiliser les tests     | CRITIQUE | ~17h          | v0.11.2 | TERMINE |
| S2: Enrichir DuckPGQ (F1-F5) | HAUTE    | ~20h          | v1.0.0  | TERMINE |
| S3: Bridge MCP SDK + HITL    | MOYENNE  | ~12h          | v1.0.0  | TERMINE |

---

## S1 — Stabiliser les tests (133 echecs → 0) ✅ TERMINE

**Objectif**: Passer de 289/446 (64.8%) a 446/446 (100%) tests verts.
**Resultat**: **422/422 tests verts, 24 skipped, 0 echecs** (21/21 fichiers)

### Bilan des corrections

| Vague | Commit    | Tests corriges                                                             | Technique principale                    |
| ----- | --------- | -------------------------------------------------------------------------- | --------------------------------------- |
| V1    | `f10c9d5` | ~43 (MCPClient, NativeService, mcp-server)                                 | Mocks class-based ESM                   |
| V2    | `c9ced21` | 28 (transports.test.ts)                                                    | Reecriture complete des mocks transport |
| V3    | `3e06480` | 54 (SpaceContext 14, ResourceRegistry 4, QueryRouter 8, ConnectionPool 28) | Source + test alignment                 |
| V4    | `f577eda` | 6 (process-tools-median) + fix flaky suite                                 | Parquet export + vitest isolate:true    |

### Problemes transverses resolus

- **ESM constructor mock pattern**: `vi.fn().mockImplementation()` n'est pas constructable en ESM strict — toujours utiliser des classes mock
- **vi.useFakeTimers() + setInterval**: MetricsCollector non-mocke causait des boucles infinies — mocker systematiquement les modules avec timers
- **isolate: false dans vitest.config**: Causait des fuites de mocks entre fichiers — corrige en `isolate: true`
- **DNS leaks**: Hostnames fictifs (server1, server2) causaient des exceptions EAI_AGAIN — utiliser 127.0.0.1 avec ports differents

### Plan de correction (ordre recommande)

#### Vague 1 — Quick wins (3h, debloque 43 tests)

**T1.1** `MCPClient.test.ts` — Corriger le mock factory (15 min, +26 tests)

```
Probleme: vi.mock retourne () => { return instance } au lieu de instance directement
Fix: Retirer le wrapper vi.hoisted(), retourner l'instance depuis le constructeur mock
```

**T1.2** `mcp-server.simple.test.ts` + `mcp-server.test.ts` — Remplacer spies par mocks (1.5h, +7 tests)

```
Probleme: expect(server.server.connect).toHaveBeenCalled() echoue car connect n'est pas un spy
Fix: Utiliser vi.spyOn() sur les methodes ou restructurer les mocks pour tracker les appels
Note: Aligner le mock connect() avec le nouveau comportement SDK 1.26.0 (throw si deja connecte)
```

**T1.3** `DuckDBMcpNativeService.test.ts` + `.unit.test.ts` — Corriger les mock constructeurs (1.5h, +12 tests)

```
Probleme: vi.mock() factory n'est pas utilisable comme constructeur
Fix: Retourner une classe mock avec vi.fn() au lieu d'une fonction
```

#### Vague 2 — Mocks transport (3h, debloque 28 tests)

**T1.4** `transports.test.ts` — Reimplementer les mocks transport (3h, +28 tests)

```
Probleme: Les mocks WS/TCP/HTTP n'emettent pas les events dans le bon ordre
Fix:
  - WebSocket: emettre 'open' apres construction, puis 'message'/'close'
  - TCP: simuler le handshake connect → data → end
  - HTTP: mocker fetch/axios avec reponses structurees
  - SDKTransportAdapter: implementer .connect(), .on(), .close() sur le mock
```

#### Vague 3 — Logique metier (5h, debloque 26 tests)

**T1.5** `SpaceContext.test.ts` — Corriger la double qualification (2.5h, +14 tests)

```
Probleme: qualifyTableName('public.users') retourne 'space_tenant.public.users'
Fix:
  - Detecter les noms deja qualifies (contiennent '.')
  - Implementer CREATE/DROP TABLE dans applyToQuery()
  - Ajouter getTableMappings() et __prepareSLMContext()
  - Valider format space_id dans le constructeur
```

**T1.6** `QueryRouter.test.ts` + `ResourceRegistry.test.ts` — Enrichir les fixtures (2h, +12 tests)

```
Probleme: Mock registry/pool retourne [] pour resources et tools
Fix: Creer des fixtures de test avec resources, tools, et clients fonctionnels
```

#### Vague 4 — Async et integration (6h, debloque 34 tests)

**T1.7** `ConnectionPool.test.ts` — Resoudre les timeouts fake timers (3.5h, +28 tests)

```
Probleme: vi.useFakeTimers() bloque les boucles de maintenance du pool
Fix:
  - Option A: Remplacer fake timers par real timers + await flushPromises()
  - Option B: Injecter les timers dans ConnectionPool (dependency injection)
  - Option C: Mocker setInterval/clearInterval directement sans useFakeTimers
Preference: Option B (meilleure testabilite long terme)
```

**T1.8** `process-tools-median.test.ts` — Isoler des variables d'environnement (2.5h, +6 tests)

```
Probleme: Tests appellent le vrai handleProcessCompose() qui requiert PROCESS_STEPS_URL
Fix:
  - Mocker getParquetUrl() pour retourner un chemin local de test
  - Ou: injecter le service DuckDB via parametres au lieu de l'env
  - Verifier l'algo median: [5,15]=10, [0,5,10,15]=7.5
```

### Criteres de succes S1

- [x] 422/422 tests verts (0 echecs, 24 skipped intentionnels)
- [x] `npm test` passe sans erreur (suite stable sur runs multiples)
- [x] Aucune regression sur les 289 tests qui passaient
- [ ] Coverage cible: branches 15%, functions 20%, lines 20% (a traiter en S2/S3)

---

## S2 — Enrichir DuckPGQ F1-F5 pour deposium_MCPs ✅ TERMINE

**Objectif**: Exposer les algorithmes de graphes valides dans fierce-analyse comme outils MCP
reutilisables par deposium_MCPs.

**Resultat**: 8 outils MCP, 19 tests d'integration, publie en v1.0.0 (22 fev 2026).
Commit: `b089a57` — `feat(graph): add 8 graph algorithm MCP tools (S2: F1-F5)`

### Etat des lieux

L'audit fierce-analyse a valide 5 families de features sur DuckDB 1.4.1 + DuckPGQ v0.2.7.
Les algorithmes natifs DuckPGQ (`pagerank()`, `weakly_connected_component()`) sont
**casses sur 1.4.x** (erreur `csr_cte does not exist`), mais des workarounds SQL iteratifs
fonctionnent parfaitement.

deposium_MCPs a deja :

- `graph.betweenness` et `graph.closeness` (CTE-based)
- `graph.components` (composantes connexes)
- `graph.search`, `graph.path`, `graph.khop`, `graph.multihop`
- Query optimizer avec fallback natif → CTE

Il manque :

- PageRank, community detection, weighted paths, temporal graphs, export multi-format

### Nouveaux outils MCP a implementer

#### F1: Centralite avancee

**T2.1** `graph.pagerank` — PageRank iteratif (4h)

```
Algorithme: SQL iteratif (20 iterations, damping=0.85)
Pattern valide: 35ms sur 10 noeuds (fierce-f1-isolated.ts)
Implementation:
  1. CREATE TEMP TABLE pr_rank (node_id, rank=1/N)
  2. Boucle TypeScript x20: UPDATE rank = (1-d)/N + d * SUM(neighbor_rank/out_degree)
  3. Retourner top-K noeuds par rank
Schema MCP:
  Input: { graph_name, damping?, iterations?, top_k? }
  Output: { nodes: [{ id, name, rank, out_degree }], convergence }
Fichier: src/tools/graph-algorithms.ts (nouveau)
```

**T2.2** `graph.eigenvector` — Centralite de vecteur propre (2h)

```
Algorithme: Power iteration (iteratif, similaire PageRank)
Implementation: Meme pattern que PageRank mais sans damping, normalisation L2
```

#### F2: Detection de communautes

**T2.3** `graph.community_detect` — Label Propagation (4h)

```
Algorithme: SQL iteratif (chaque noeud adopte le label majoritaire de ses voisins)
Pattern valide: fierce-f2f5.ts
ATTENTION: PAS de recursive CTE (cause segfault sur DuckPGQ 1.4.x)
Implementation:
  1. CREATE TEMP TABLE labels (node_id, label=node_id)
  2. Boucle TypeScript x20: UPDATE label = mode(neighbor_labels)
  3. GROUP BY label pour extraire les communautes
Schema MCP:
  Input: { graph_name, max_iterations?, min_community_size? }
  Output: { communities: [{ id, members: [], size, density }], modularity }
Fichier: src/tools/graph-algorithms.ts
```

**T2.4** `graph.modularity` — Score de modularite (1h)

```
Formule: Q = (1/2m) * SUM[ A_ij - k_i*k_j/(2m) ] * delta(c_i, c_j)
Input: resultat de community_detect
Output: score Q entre -0.5 et 1.0
```

#### F3: Chemins ponderes

**T2.5** `graph.weighted_path` — Chemins avec fonctions de cout (4h)

```
3 modes valides dans fierce-analyse:
  a) Strongest chain: produit des confidences (multiplicatif)
  b) Cheapest path: Bellman-Ford avec cout = 1 - confidence
  c) Max combined: somme de confidence * support

Implementation: BFS iteratif TypeScript (pas de recursive CTE!)
Schema MCP:
  Input: { source_id, target_id, cost_function: 'strongest'|'cheapest'|'combined',
           max_hops?, period? }
  Output: { paths: [{ chain, cost, hops }], algorithm_used }
Fichier: src/tools/graph-algorithms.ts
```

#### F4: Graphes temporels

**T2.6** `graph.temporal_filter` — Sous-graphe par periode (2h)

```
Pattern valide: creation de PROPERTY GRAPH par periode
Implementation:
  1. Filtrer edges par colonne period/date_range
  2. Creer table temporaire + PROPERTY GRAPH
  3. Executer la requete sur le graphe filtre
Schema MCP:
  Input: { graph_name, period_start, period_end, query? }
  Output: { nodes, edges, period_stats }
```

**T2.7** `graph.compare_periods` — Detection de changement (2h)

```
Pattern valide: JOIN drives early/late + delta confidence/lag
Implementation:
  1. Extraire edges pour chaque periode
  2. JOIN pour trouver les paires communes
  3. Calculer delta confidence, delta lag, tendance
Schema MCP:
  Input: { graph_name, period_a, period_b }
  Output: { changes: [{ src, dst, trend: 'STRENGTHENED'|'WEAKENED'|'STABLE',
            delta_conf, delta_lag }], summary }
```

#### F5: Export multi-format

**T2.8** `graph.export` — Export multi-format (3h)

```
Formats valides: JSON, CSV/Gephi, D3.js, GraphML, Parquet
Implementation:
  - JSON: COPY TO '/tmp/*.json' (FORMAT JSON)
  - CSV/Gephi: COPY TO avec colonnes Id/Label/Source/Target/Weight
  - D3.js: json_object() pour nodes[] et links[]
  - GraphML: string_agg() pour construire XML
  - Parquet: COPY TO (FORMAT PARQUET)
Schema MCP:
  Input: { graph_name, format: 'json'|'csv'|'d3'|'graphml'|'parquet',
           output_path?, period? }
  Output: { format, path?, content?, size_bytes }
Fichier: src/tools/graph-export.ts (nouveau)
```

### Architecture des fichiers

```
src/tools/
  graph-algorithms.ts  (NOUVEAU) — T2.1-T2.5: PageRank, Eigenvector, LabelProp, Modularity, WeightedPath
  graph-temporal.ts    (NOUVEAU) — T2.6-T2.7: TemporalFilter, ComparePeriods
  graph-export.ts      (NOUVEAU) — T2.8: Export multi-format
  graph-advanced.ts    (EXISTANT) — betweenness, closeness, khop, multihop (inchange)

tests/
  graph-algorithms.test.ts  (NOUVEAU) — Tests unitaires F1-F3
  graph-temporal.test.ts    (NOUVEAU) — Tests unitaires F4
  graph-export.test.ts      (NOUVEAU) — Tests unitaires F5
```

### Criteres de succes S2

- [x] 8 nouveaux outils MCP fonctionnels (pagerank, eigenvector, community_detect, modularity, weighted_path, temporal_filter, compare_periods, export)
- [x] 19 tests d'integration avec DuckDB reel (441 total, 0 echecs)
- [x] Performance: tous < 200ms sur 6 noeuds / 15 edges
- [ ] Performance: a valider sur le dataset deposium (62 noeuds, 2000 edges)
- [x] Aucun recursive CTE (iteratif avec temp tables uniquement)
- [x] Documentation API dans README.md + CHANGELOG.md
- [ ] Integration testee dans deposium_MCPs via `@seed-ship/duckdb-mcp-native/graph`

---

## S3 — Bridge MCP SDK 1.26.0 + HITL

**Objectif**: Aligner l'implementation sur les changements du SDK 1.26.0 et implementer
les bases du pattern HITL (Human-in-the-Loop) via l'API d'elicitation MCP.

### Changements SDK 1.26.0 a integrer

| Changement                                  | Impact   | Action                                               |
| ------------------------------------------- | -------- | ---------------------------------------------------- |
| `Protocol.connect()` throw si deja connecte | LOW      | Adapter les mocks, ajouter garde dans `start()`      |
| Types stricts (plus de `passthrough()`)     | LOW      | Verifier que nos messages n'ont pas de champs custom |
| `WebStandardStreamableHTTPServerTransport`  | MEDIUM   | Evaluer pour remplacer notre HTTP transport partiel  |
| Types Elicitation disponibles               | HIGH     | Base pour HITL                                       |
| Security: cross-client data leak fix        | RESOLVED | Deja corrige par update a 1.26.0                     |
| Security: ReDoS UriTemplate                 | RESOLVED | Deja corrige                                         |

### Plan d'implementation

#### Vague 1 — Alignement SDK (4h)

**T3.1** Adapter `mcp-server.ts` au nouveau comportement `connect()` (1h)

```
- Ajouter garde: verifier si deja connecte avant d'appeler connect()
- Ajouter close() propre avant reconnexion si necessaire
- Mettre a jour le pin minimum SDK dans package.json: "^1.26.0"
```

**T3.2** Evaluer `WebStandardStreamableHTTPServerTransport` (2h)

```
- Notre HTTP transport (src/protocol/http-transport.ts) a des problemes d'initialisation
- Le nouveau transport SDK standard pourrait le remplacer entierement
- Evaluer: compatibilite avec Express, performance, API surface
- Decision: remplacer ou garder notre implementation custom
```

**T3.3** Mettre a jour les types strict (1h)

```
- Verifier tous les messages JSON-RPC construits manuellement
- S'assurer qu'aucun champ custom n'est utilise
- Aligner les schemas Zod avec les nouveaux types SDK
```

#### Vague 2 — Foundation HITL (5h)

**T3.4** Implementer le support Elicitation cote serveur (3h)

```
L'elicitation MCP permet au serveur de demander une confirmation utilisateur pendant
l'execution d'un outil. C'est le mecanisme HITL natif du protocole MCP.

Use case principal:
  - Mode production: confirmer avant d'executer du SQL destructif (DROP, DELETE, ALTER)
  - Mode production: confirmer avant d'acceder a des donnees sensibles
  - Graph enrichment: confirmer les relations inferees avant de les persister

Implementation:
  1. Detecter la capability elicitation du client
  2. Creer un helper sendElicitation(options) dans mcp-server.ts
  3. Integrer dans le handler CallToolRequestSchema pour les outils critiques
  4. Fallback gracieux si le client ne supporte pas l'elicitation

Types disponibles dans SDK 1.26.0:
  - ElicitCreateRequest / ElicitCreateResult
  - Form-based elicitation (champs structures)

Note: L'API haut niveau n'existe pas encore dans 1.26.0.
Utiliser sendRequest() low-level avec methode 'elicitation/create'.
```

**T3.5** Integrer HITL dans le mode securite production (2h)

```
Fichier: src/server/mcp-server.ts (handler CallToolRequestSchema)

Avant d'executer un query_duckdb en mode production:
  1. Analyser la requete SQL
  2. Si destructive (DROP/DELETE/ALTER/TRUNCATE):
     → Envoyer elicitation: "Confirmer l'execution de: {sql}"
     → Attendre la reponse utilisateur
     → Executer ou refuser selon la reponse
  3. Si lecture seule: executer directement

Pattern similaire pour graph_analyze avec des operations d'ecriture.
```

#### Vague 3 — Tests et documentation (3h)

**T3.6** Tests pour les changements SDK (1.5h)

```
- Test: connect() ne peut pas etre appele deux fois
- Test: elicitation envoyee pour SQL destructif en mode production
- Test: fallback quand client ne supporte pas elicitation
- Test: mode development bypass l'elicitation
```

**T3.7** Documentation HITL (1.5h)

```
- Documenter le flow elicitation dans docs/TRANSPORTS.md
- Exemples d'integration pour les clients MCP
- Guide de migration pour les consumers de @seed-ship/duckdb-mcp-native
```

### Criteres de succes S3

- [x] `connect()` gere proprement les reconnexions (guard via `server.transport` getter)
- [x] Decision prise sur HTTP transport: conservation (client-side only, distinct du SDK server-side)
- [x] Elicitation fonctionnelle pour SQL destructif en mode production
- [x] Fallback gracieux si client ne supporte pas l'elicitation (block par defaut)
- [x] Tests couvrant les 3 scenarios HITL (confirm, reject, unsupported) + 28 tests total
- [x] Documentation a jour (TRANSPORTS.md, README.md, CHANGELOG.md)

---

## Planning previsionnel

```
Semaine 1-2 (fev 2026):   S1 Vague 1+2  — Quick wins + mocks transport       ✅ FAIT
Semaine 3   (fev 2026):   S1 Vague 3    — Logique metier                     ✅ FAIT
Semaine 4   (fev 2026):   S1 Vague 4    — Async + integration                ✅ FAIT
  → Release v0.11.2 (S1 complete)
Semaine 4   (fev 2026):   S2 F1-F5      — 8 graph tools en un seul sprint    ✅ FAIT (21 fev)
Semaine 5   (fev 2026):   S2+S3 — Graph tools + SDK alignment + HITL + docs     ✅ FAIT (22 fev)
  → Release v1.0.0 (S1+S2+S3 complete)
```

## Dependances

- S1 est prerequis pour S2 (base de tests stable)
- S2 est independant de S3 (pas de dependance MCP SDK pour les algos graph)
- S3 peut demarrer en parallele de S2 si besoin (equipes differentes)
- S2 se deploie d'abord dans duckdb_mcp_node, puis s'integre dans deposium_MCPs

## Decisions en attente

1. **HTTP Transport**: Remplacer notre implementation par `WebStandardStreamableHTTPServerTransport` du SDK ?
2. **SDK version**: Monter a 1.27.0 (ajoute streaming elicitation) ou rester sur 1.26.0 ?
3. **eslint 10**: Planifier la migration majeure pour resoudre les 9 vulns minimatch restantes ?
4. **Issue #17 (Mastra)**: Fermer ou mettre en standby ? L'architecture deposium_MCPs + HITL natif couvre les use cases decrits.
