# Roadmap Travaux planifiés, par lot. Chaque lot est livrable indépendamment. Constats issus de la session de diagnostic du **24/08/2026** (profil `LIMAGRAIN`, host `10.255.255.2`, tenant `LIMAGRAI2512`), déclenchée par un rapport d'usage d'une session Cowork. Toutes les anomalies ci-dessous ont été **reproduites** contre le WMS réel — ce ne sont pas des hypothèses. Les décisions actées vivent dans [DECISIONS.md](DECISIONS.md) ; ce fichier ne contient que ce qui reste à faire. --- ## Lot 4 — Modèle de données et applications Deux angles morts constatés le 24/08/2026, plus larges que les lots 2 et 3. Les chiffres ci-dessous sont mesurés sur le tenant `LIMAGRAI2512`. ### L4.1 (reliquat) — Explorer le contexte Metrics L'exposition de `query_type` est livrée (D25). Reste l'investigation : le contexte `Metrics` (`QueryType: 3`, `ApplicationMetricDataContext`) mérite une exploration à part — c'est probablement là que vivent les données agrégées produites par les jobs `MetricGatherer`. Livrable : un rapport, pas du code (même phase d'investigation que L4.4). ### L4.3 — Identifier le MCP dans les logs du WMS Les requêtes du MCP apparaissent dans les logs du WMS sous `Execute error. Client: GNA` — le client OAuth partagé — donc indistinguables de celles du vrai client GNA. **La piste `ClientModule` est invalidée** (mesuré le 24/08/2026, lot 1) : le champ est bien accepté par `QueryExecute` (pas d'erreur), mais il est **sans effet observable**. Une requête en échec envoyée avec `ClientModule: "MCP-WMS"` est tracée `Execute error. Client: GNA`, et ni `MCP-WMS` ni `ClientModule` n'apparaissent nulle part dans `ApplicationService.log` ni `HttpResponseTime.log`. Le `Client:` des logs vient du client OAuth, pas du payload — le champ n'a donc **pas** été renseigné. Piste restante (non vérifiée) : un client OAuth dédié au MCP côté EasySTS changerait le `Client:` des logs, mais suppose une configuration côté WMS. ### L4.4 — Historique d'exécution des workflows par API `ApplicationService` expose une API `WorkflowLog` que le MCP n'utilise pas : | Endpoint | Usage | |---|---| | `GET /WorkflowLog/GetInstances?processDefinitionId=&skip=&take=&startDateFrom=&startDateTo=` | instances d'un workflow sur une plage de dates, filtrables par attribut | | `GET /WorkflowLog/GetInstance?processId=` | une instance | | `GET /WorkflowLog/GetLogs?processId=&skip=&take=&logDateFrom=&logDateTo=` | journal d'exécution d'une instance | | `GET /WorkflowLog/Validate?applicationName=&processDefinitionId=` | validation d'une définition | Endpoints joignables et fonctionnels — `Validate` renvoie `{"Success":true,"ErrorMessage":null,"Warnings":[]}`. `GetInstances` répond `[]` sur le workflow testé : à confirmer sur un workflow ayant réellement tourné, la journalisation n'étant pas forcément active partout. **Peut remettre en cause D16** (historique des shipment templates jugé hors de portée faute de logs fichier) : si l'historique d'exécution est disponible par API, la conclusion change. À vérifier avant d'écrire quoi que ce soit. ### L4.5 — Champs de `QueryExecute` inexploités La référence de l'API documente des champs que le MCP n'envoie jamais : | Champ | Intérêt | |---|---| | `Parameters` | requêtes **paramétrées** (dictionnaire `nom -> {TypeName, Value}`) — supprimerait toute concaténation de chaîne dans les filtres, et pourrait débloquer D13 (`Select`) | | `CommandTimeout` | timeout par requête, au lieu du timeout HTTP global de 30 s | | `QueryId` + `POST /QueryCancel` | annulation d'une requête longue | | `POST /QueryExecuteStream` | résultats en flux — piste long terme pour les sorties volumineuses, au-delà du bornage signalé de D24 | Autres endpoints jamais utilisés, à évaluer : `QueryEvents`, `QueryCommands`, `QueryCorrelationEvents`, `QuerySnapshots` (event sourcing — utile en debug), `GET /Metadata/Commands|Events|Aggregates` et leurs variantes `…All`, `GET /configuration/applications` (liste les applications **avec leur version**, plus riche que `/AD/api/Application/GetAll`), `GET /healthcheck?tenantCode=` et `GET /ready?tenantCode=` (sondes de disponibilité, répondent 200). --- --- ## Lot 5 — Clore la famille D24 (rejets client sur sorties volumineuses) Mesures du 25/08/2026 (protocole, LIMAGRAIN), toutes au-dessus du seuil de rejet client (~70 000 caractères, D24) : | Appel | Taille | |---|---:| | `query_wms_entities("Products", limit: 200)` — Reading ordinaire | **957 234** | | `search_wms_data("PAL")` | **847 543** | | `get_workflow_details(CST_SendRejectContainersToPK)` | ~101 800 | | `call_query_api("Products", query_type: 1, limit: 1)` — **une seule ligne** Writing | **95 288** | ### L5.2 — Garde de taille sur les outils de requête Une ligne Writing = un agrégat complet sérialisé (95 288 caractères là où la même ligne Reading en fait ~4 500) ; 200 lignes Reading = ~957 000 ; `search_wms_data` = ~848 000. Garde de taille commune sur `query_wms_entities`, `call_query_api` et `search_wms_data` : lignes entières écartées, `truncated`/`returned`/`omitted`/`hint` (D24). Ne pas réduire `MAX_QUERY_ROWS` ni les limites par défaut. ### L5.3 — Champ `tool` absent des erreurs construites localement Les `catch` locaux d'`api-tools.js` renvoient `{ success: false, error }` sans le champ `tool` du contrat (convention 3) — antérieur au lot 4. Balayer tous les modules d'outils pour le même motif. ### L5.4 — Rendre les autres applications découvrables depuis `search_workflows` Cas réel (25/08/2026, session Cowork sur LIMAGRAIN) : une session cherchant des workflows `CST_*` sans passer `application: "CustomApp"` a conclu à tort « l'AD contient 4 012 workflows, aucun CST_ » — alors que `CST_PickingTasksSequencing_PR` et `CST_ChooseDestinationFromPS` existent bien dans CustomApp (vérifié en révision). Le paramètre `application` (D26) existe, mais rien dans la **réponse** ne signale qu'on n'a regardé qu'une application. Ajouter aux réponses de `search_workflows` (et `search_ad_elements`) un rappel peu coûteux : l'application interrogée, et — quand la recherche renvoie peu ou pas de résultats — un hint listant les autres applications (la liste allégée d'`Application/GetAll` est déjà en cache, D26) avec renvoi vers le paramètre `application`. Aucun préchargement des autres applications (D26). --- ## Écarté | Proposition | Raison | |---|---| | Uniformiser les noms de paramètres (`entity_type` / `query` partout) | Casse les usages existants ; les alias de transition doublent la surface à maintenir. La cause réelle est traitée par L2.2. | | Exposer un `indexStatus` sur `generic_search` | `TotalDocuments: 0` est déjà le signal. Le MCP n'a aucun moyen d'interroger l'état de l'index de recherche. | | Outil dédié `get_query_syntax_help` | L'information doit se trouver dans le message d'erreur, là où elle est lue (L2.1), pas dans un outil qu'il faut penser à appeler. | --- ## Points ouverts (hors lots) - **Profil `AD` : tenant introuvable** (mesuré le 24/08/2026). `npm test -- --all` échoue 0/4 sur ce profil ; le STS de `10.255.255.2` répond `400 {"error":"invalid_request","error_description":"Tenant not found"}` pour le tenant `AD`. L'hôte et le STS fonctionnent (LIMAGRAIN, même hôte, passe 4/4) : c'est la valeur `AD_TENANT` du `.env` qui ne correspond plus à un tenant existant. Correction côté propriétaire du dépôt (mettre à jour ou retirer le profil) — pas un bug du code. Depuis L3.2, le corps de la réponse du STS (`Tenant not found`) remonte dans les erreurs d'outils et du smoke test. - **Bascule de profil concurrente aux appels en vol** (mesuré le 25/08/2026, révision du lot 2). Le serveur traite les `tools/call` **en concurrence** : en envoyant une rafale de requêtes dans une même session, les réponses reviennent dans le désordre, et un `switch_wms_profile` émis pendant que des requêtes sont en vol les fait partir sur le nouveau profil (observé : une requête destinée à EUROTRAFIC exécutée sur l'hôte `10.255.255.2` après la bascule suivante). Conséquence du singleton d'état global (D8). Sans gravité pour un usage conversationnel séquentiel, mais Claude peut émettre des appels d'outils **en parallèle** : à traiter si un cas réel de mélange de profils est observé (piste : sérialiser les `tools/call` ou figer le profil résolu au début de chaque appel). - **`select_expression`** : les projections via le paramètre `Select` provoquent des erreurs de compilation côté serveur (D13). Irritant principal restant. - **Déploiement SSH sur la VM** : l'exécutable est validé, la configuration SSH reste à faire. - **Historique des shipment templates** : hors de portée, les logs concernés n'existent pas sur l'hôte joignable (D16).