Deux anomalies préexistantes au lot 1, mesurées le 24/08/2026 :
- get_workflow_details({}) renvoyait success: true avec le premier
workflow du cache : getWorkflowDetails() comparait w.Id/w.Code/w.Name,
clés qui n'existent pas sur les objets AD réels (minuscules, D5) —
undefined === undefined matchait. Clés mortes supprimées (id et name
seuls existent, les parseInt sur des GUID étaient morts aussi), garde
d'entrée rejetant workflow_id absent avec renvoi vers search_workflows.
- search_logs({}) plantait en "Cannot read properties of undefined
(reading 'toLowerCase')" : garde d'entrée nommant "keyword" avec un
exemple d'appel.
Le wrapper D23 rejette déjà ces appels via required — les gardes côté
code restent, la validation SDK n'étant pas garantie pour les appelants
directs des services.
Mesures :
- via le protocole, les deux appels {} -> "Paramètre(s) requis
manquant(s) pour ... " (wrapper D23)
- gardes appelées en direct (sans wrapper) :
getWorkflowDetails(undefined) jette "workflow_id est requis (id ou nom
exact du workflow)..." ; search_logs({}) répond success: false avec le
message nommant keyword
- get_workflow_details avec un id réel (2e workflow du cache, pas le
premier) -> objet brut complet ($id, validFrom, ..., data), id/name
conformes à la recherche
ROADMAP : L2.3 retirée, lot 2 soldé.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
10 KiB
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 ; ce fichier ne contient que ce qui reste à faire.
Lot 3 — Ergonomie et documentation
Le lot 2 (résolution Name -> TableName, rejet des paramètres inconnus,
garde-fous d'arguments manquants) est livré — voir D21 et D23.
L3.1 — Bornage des sorties volumineuses
get_system_parameters: ajouterlimit/offset, aujourd'hui absents (sortie constatée : 70 000 caractères, rejetée par le client).search_logs: garde-fou de taille.max_resultsexiste déjà, mais lescontext_linesmultiplient le volume (88 000 caractères pour 50 résultats).- Renvoyer
truncated: trueexplicitement plutôt que de laisser le client se faire rejeter.
L3.2 — Erreurs d'authentification muettes
authenticate() (api-service.js) ré-enveloppe l'erreur axios en
new Error('Authentication failed: ' + error.message) : le corps de la
réponse du STS est perdu, alors qu'il contient le diagnostic complet.
Preuve (24/08/2026, profil AD) : le smoke test affiche seulement
Authentication failed: Request failed with status code 400 ; en rejouant la
même requête à la main, le corps était
{"error":"invalid_request","error_description":"Tenant not found"} — le
diagnostic exact, invisible depuis les outils comme depuis le smoke test.
Faire remonter error.response.data dans le message, comme L1.1 l'a fait pour
les outils. Même contrainte : ne jamais logguer les credentials.
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 — Le modèle Writing est inatteignable
QueryType est figé à 0 (Reading) en dur dans api-service.js
(executeQuery et executeScalarQuery). Or QueryContextType a quatre
valeurs. Testées une à une :
| Valeur | Contexte | Résultat sur LIMAGRAI2512 |
|---|---|---|
0 |
Reading | opérationnel (seul utilisé aujourd'hui) |
1 |
Writing | opérationnel — Context.Products répond |
2 |
DataWarehouse | non configuré : Could not resolve serviceType 'IDataWarehouse…' |
3 |
Metrics | contexte présent (ApplicationMetricDataContext), modèle non exploré |
Exposer query_type sur les outils de requête, défaut 0. Attention : D3 reste
vrai — en Writing les champs de statut sont des énumérations, donc
== "Release" échoue. La bascule doit être un choix explicite et documenté.
Le contexte Metrics mérite une exploration à part : c'est probablement là que
vivent les données agrégées produites par les jobs MetricGatherer.
L4.2 — Une seule application sur neuf est visible
Application vient de WMS_APPLICATION dans .env, partagé par tous les
profils, sans surcharge par appel ni paramètre d'outil. Le MCP n'interroge donc
jamais que EasyWMS.
POST /AD/api/Application/GetAll en déclare 9 :
| Application | Workflows | Queries | Entities |
|---|---|---|---|
| EasyWMS | 4012 | 2239 | 338 |
| CustomApp | 153 | 54 | 11 |
| AGV | 71 | 14 | 5 |
| Notifications | 26 | 35 | 24 |
| GalileoFaults | 9 | 20 | 24 |
| Common | 1 | 7 | 25 |
| SmartUI, User, WarehouseWebDesigner | 0 | 0–8 | 0 |
CustomApp porte le spécifique client — ses workflows sont préfixés CST_
(CST_SendRejectContainersToPK, CST_Task, CST_Container…). C'est
précisément ce qu'on cherche en debug, et c'est aujourd'hui invisible. Au total
260 workflows et ~130 queries hors périmètre.
Deux chantiers de difficulté très différentes :
API AD — simple. L'application est un champ du payload
([application, tenant, pageSize, offset]). Vérifié : ["CustomApp", tenant, 5, 0] sur /Workflow/GetByApplication renvoie bien les workflows CST_. Il
suffit d'un paramètre application sur les outils AD et workflow, avec une clé
de cache incluant l'application (sinon un cache pollué mélange les
applications).
QueryExecute — tranché : le champ Application ne partitionne rien.
Context.AgvTasks (entité de l'application AGV) répond aussi bien avec
Application: "AGV" qu'avec Application: "EasyWMS". Le contexte de lecture est
commun au tenant : toutes les applications y déversent leurs entités.
Conséquence — traitée : la table de résolution (D21) agrège le Metadata de
toutes les applications déployées, et non le seul EasyWMS. Inutile en
revanche d'ajouter un paramètre application à QueryExecute : il ne changerait
rien.
Les entités CustomApp ne sont interrogeables dans aucun contexte. Les 11
entités CST_ ont été testées sous les quatre QueryType, au singulier et au
pluriel : échec partout, et Metadata/Entities comme Metadata/EntitiesAll
renvoient 0 entité pour CustomApp. Aucune n'est marquée
isDataWarehouse. Ce sont des définitions EasyBuilder (FromMetadata: false)
sans projection dans un contexte requêtable.
L'API AD reste donc le seul accès au spécifique client — ce qui rend le
paramètre application sur les outils AD et workflow d'autant plus utile.
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 sérieuse pour L3.1 (sorties volumineuses) |
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).
É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 de10.255.255.2répond400 {"error":"invalid_request","error_description":"Tenant not found"}pour le tenantAD. L'hôte et le STS fonctionnent (LIMAGRAIN, même hôte, passe 4/4) : c'est la valeurAD_TENANTdu.envqui 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. Le message opaque du smoke test est traité à part (L3.2). select_expression: les projections via le paramètreSelectprovoquent 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).