Convention 3 impose { success: false, error, tool }, mais le champ tool n'etait
ajoute que par le wrapper de src/index.js. Les enveloppes construites
localement dans src/tools/ ne le portaient pas : call_query_api avec
query_type: 7 repondait { success: false, error: "query_type invalide : ..." },
sans tool. Le contrat etait donc respecte ou non selon le chemin d'erreur --
alors qu'il est lu par Claude, pas par un humain.
Balayage des 8 modules : 15 enveloppes success:false au total, 11 y ont gagne
le champ tool (ad-tools, config-tools, wms-query-tools et workflow-tools
l'avaient deja via le catch de leur executeTool). Les champs additionnels sont
conserves et passent apres tool : warning de resolution d'api-tools,
availableCount + hint de get_entity_metadata, listes de profils de
profile-tools.
Grep de controle -- 15 enveloppes, 0 sans tool :
src/tools/ad-tools.js:140 tool: name
src/tools/api-tools.js:170 tool: 'call_query_api'
src/tools/api-tools.js:217 tool: 'execute_command'
src/tools/config-tools.js:179 tool: 'get_system_parameters'
src/tools/log-tools.js:116 tool: 'list_log_files'
src/tools/log-tools.js:157 tool: 'read_recent_logs'
src/tools/log-tools.js:227 tool: 'search_logs'
src/tools/metadata-tools.js:110 tool: 'get_entity_metadata'
src/tools/metadata-tools.js:154 tool: 'get_entity_metadata'
src/tools/metadata-tools.js:197 tool: 'generic_search'
src/tools/profile-tools.js:111 tool: 'get_current_wms_profile'
src/tools/profile-tools.js:129 tool: 'switch_wms_profile'
src/tools/profile-tools.js:159 tool: 'switch_wms_profile'
src/tools/wms-query-tools.js:169 tool: name
src/tools/workflow-tools.js:117 tool: name
Verifie en execution (protocole, LIMAGRAIN sauf mention) -- 11 enveloppes
declenchees, toutes avec tool :
call_query_api query_type: 7 -> tool: call_query_api
get_entity_metadata entite inconnue -> tool + availableCount + hint
query_wms_entities entite inconnue -> tool: query_wms_entities
get_workflow_details id inconnu -> tool: get_workflow_details
get_ad_elements type inconnu -> tool: get_ad_elements
switch_wms_profile profil inconnu -> tool + profiles
read_recent_logs fichier inexistant -> tool: read_recent_logs
list_log_files / search_logs /
read_recent_logs sur EUROTRAFIC -> tool, garde SaaS D9 (sans reseau)
Trois catch restent couverts statiquement, faute de declencheur : celui
d'execute_command (interdit d'appel, il ecrit dans le WMS), celui de
generic_search (l'API tolere categorie inexistante comme limit negative :
elle repond success), et celui de get_current_wms_profile (inatteignable tant
qu'un profil par defaut se charge au demarrage).
Baseline preservee : 23 outils, 6 resources.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Aucune borne de VOLUME n'existait sur query_wms_entities, call_query_api et
search_wms_data -- seulement une borne de LIGNES (MAX_QUERY_ROWS). Le modele
Writing serialise l'agregat complet (navigations, $id) : une seule ligne
Products y pese 95 288 caracteres, la ou la meme ligne Reading en fait ~4 500.
Toutes ces reponses depassaient le seuil de rejet du client MCP (D24), qui
renvoie un echec opaque plutot qu'un resultat partiel.
Plafond commun MAX_QUERY_RESPONSE_CHARS (defaut 25 000, meme ordre de grandeur
que MAX_LOG_SEARCH_CHARS), applique par src/services/response-limit.js : on
ecarte des LIGNES ENTIERES, jamais coupees au milieu, et on signale avec le
vocabulaire D24 (truncated / returned / omitted / hint). Le helper est partage
parce que les trois outils partagent le meme mecanisme -- ce que les mecanismes
de get_system_parameters et search_logs, eux, ne font pas. La recherche
dichotomique evite 200 reconstructions d'une charge utile de ~1 Mo.
Mesures avant/apres (protocole, LIMAGRAIN, longueur de content[0].text) :
query_wms_entities Products limit 200 957 234 -> 24 432
count 200, returned 5, omitted 195, truncated
search_wms_data "PAL" 847 543 -> 22 992
totalFound 150, returned 4, omitted 146 ; reparti en tourniquet :
Products 2, Containers 1, Tasks 1 -- sans quoi Products, en tete,
consommerait tout le budget et les deux autres reviendraient a zero
resultat sans que rien ne le dise
call_query_api Products query_type 1 95 288 -> 738
cas limite : returned 0, omitted 1, truncated, hint expliquant le
volume Writing et renvoyant vers Reading
Sous le plafond, rien ne change -- verifie identique OCTET POUR OCTET contre
la version precedente :
query_wms_entities Container limit 1 4 476 -> 4 476
call_query_api Products limit 2 9 671 -> 9 671
get_entity_schema Container 11 172 -> 11 172
search_wms_data sous plafond 11 767 -> 11 767
count_wms_entities Products 120 -> 120 (non concerne)
MAX_QUERY_ROWS et les limites par defaut des outils sont inchanges : le
correctif est le bornage signale, pas une reduction silencieuse. L'avertissement
de volume rejoint la description du parametre query_type (D25) de
query_wms_entities et call_query_api, pas celle de count_wms_entities dont la
reponse est un scalaire.
Baseline preservee : 23 outils, 6 resources.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
La reponse embarquait la definition EasyBuilder complete, au-dela du seuil de
rejet du client MCP (~70 000 caracteres, D24). Deux parametres de fenetre au
schema (D23) : max_data_chars (defaut 20 000) et data_offset (defaut 0). Les
metadonnees du workflow restent completes dans chaque tranche ; seul `data`
est fenetre, et dataTotalChars est porte par toute reponse.
La tranche est verbatim -- decoupe de chaine, rien d'autre. Ne jamais resumer
ni parser ce blob : la concatenation des tranches doit reconstituer la
definition a l'octet pres. Verifie : 20 000 + 20 000 + 20 000 + 11 512 =
71 512, concatenation identique au blob d'origine (premiers et derniers
caracteres compris).
Mesures avant/apres (protocole, LIMAGRAIN, longueur de content[0].text) :
StackerCrane_LocationIsAccessibleByExtractor_PR 79 092 -> 23 117
(blob data : 71 512, desormais annonce par dataTotalChars)
CST_SendRejectContainersToPK (CustomApp) 101 816 -> 23 023
(blob data : 92 362)
StackerCrane_LoadMovementForOutboundTask_PR 10 587 -> 10 652
(blob de 9 013 : sous le defaut, objet workflow identique a l'octet pres,
ni truncated ni hint -- les +65 caracteres sont les trois champs de
fenetre, contrat "total toujours porte" de D24)
Gardes de valeur dans le code de l'outil, pas dans le wrapper (D23 ne valide
que les noms) : data_offset: -5 et max_data_chars: 1.5 echouent avant tout
appel reseau avec un message nommant l'attendu.
Baseline preservee : 23 outils, 6 resources.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cas réel du 25/08/2026 : une session Cowork cherchant des workflows CST_
sans passer application=CustomApp a conclu à tort à leur absence de l'AD.
Vérifié en révision : CST_PickingTasksSequencing_PR et
CST_ChooseDestinationFromPS existent bien dans CustomApp sur LIMAGRAI2512.
Le correctif (rappel de l'application interrogée + hint sur résultat
maigre, depuis la liste Application/GetAll déjà en cache) rejoint le
lot 5, pas encore lancé.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deux mesures nouvelles du 25/08/2026 aggravent le dossier : une requête
Reading ordinaire query_wms_entities(Products, limit 200) pèse 957 234
caractères et search_wms_data(PAL) 847 543 — le dépassement du seuil de
rejet client (~70 000, D24) ne se limite donc pas au Writing ni aux
workflows. Les points ouverts correspondants deviennent un lot 5 planifié
dans la ROADMAP (L5.1 fenêtre verbatim sur le blob data, L5.2 garde de
taille commune aux trois outils de requête avec le cas limite d'une
ligne seule au-dessus du plafond, L5.3 balayage du champ tool).
Pas de nouveau numéro de décision : le lot étend D24. D27 réservable si
besoin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Les vérifications attendues des trois blocs rejouées via le protocole
passent : api://catalog assaini (plus de QueryType 1, d'Aliases ni de
suffixe d'assembly), query_type opérationnel (Writing 1 ligne, Metrics en
erreur parlante, 7 rejeté localement sans aucun trafic réseau, warning de
résolution conservé jusque dans l'échec WMS), caches par application
étanches (4012/153, retour en cache hit, invalidation complète à la
bascule). Baseline 23/6, npm test 4/4 exit 0, diffs propres.
Deux découvertes consignées en points ouverts : une ligne Products en
Writing pèse 95 288 caractères (famille D24), et les catch locaux
d'api-tools omettent le champ tool du contrat (antérieur au lot).
Leçon de révision : mon appel search_workflows(search_term=...) des lots
précédents était silencieusement ignoré pré-D23 — le paramètre s'appelle
query. La validation D23 a transformé mon erreur en signal.
handoff-lot4.md supprimé (livré et révisé).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
L'application venait de WMS_APPLICATION (partagée par tous les profils) : le
MCP n'interrogeait que EasyWMS, alors que CustomApp porte le spécifique
client (153 workflows CST_ sur ce tenant) et que 9 applications sont
déclarées par Application/GetAll.
Paramètre application (défaut : l'application du profil, comportement
inchangé sans lui) sur get_ad_elements, search_ad_elements,
get_ad_element_details, search_workflows, get_workflow_details,
list_workflow_categories. Clés de cache : ad-service passe par
(application, type), workflow-service par application — sans quoi un appel
CustomApp polluerait le cache EasyWMS. L'invalidation reste l'abonnement
onSwitch (D8), le chargement reste paresseux (aucun préchargement des 9
applications, D10). list_workflow_categories s'adosse à Application/GetAll
(liste allégée en cache : le blob data de chaque application pèse ~100 Ko) ;
get_application_summary regroupe par application et ne détaille que les
entrées en cache (D24), workflows compris. Acté en D26 ; CLAUDE.md mis à
jour (Caches, AD), L4.2 retiré de la ROADMAP.
Vérifications rejouées via le protocole (LIMAGRAIN / LIMAGRAI2512),
requêtes séquentielles :
- search_workflows(CST_, application:CustomApp) -> 5 objets peuplés dont
CST_SendRejectContainersToPK ([Workflow] Successfully cached 153 workflows
for "CustomApp").
- get_ad_elements(Workflow, application:CustomApp) -> count 153, éléments
CST_* ([AD] Successfully cached 153 CustomApp::Workflow).
- Séquence EasyWMS -> CustomApp -> EasyWMS sur search_workflows : 4012 vs
153, retour en cache hit ([Workflow] Using cached data for "EasyWMS"),
aucune pollution ; get_application_summary montre les deux caches
(workflowCachesByApplication EasyWMS 4012 / CustomApp 153).
- Sans paramètre application -> comportement inchangé (W1 = W3).
- switch_wms_profile EUROTRAFIC puis retour -> [Workflow] Cache cleared,
[AD] All caches invalidated, [EntityResolver] Cache cleared ; summary vide.
- list_workflow_categories -> 9 applications, comptes réels des applications
chargées.
Baseline : tools/list 23 (les 23 noms répondent), resources 6, rejet D23
d'un paramètre inconnu OK (search_workflows/applikation), npm test 4/4
exit 0.
Anomalie hors périmètre consignée dans ROADMAP.md : get_workflow_details
peut dépasser le seuil de rejet client (~101 800 caractères mesurés sur
CST_SendRejectContainersToPK), comportement antérieur au lot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
QueryType était figé à 0 en dur dans executeQuery/executeScalarQuery : le
modèle Writing, opérationnel et mesuré, était inatteignable. Paramètre
query_type (défaut 0) sur call_query_api, query_wms_entities,
count_wms_entities — get_entity_schema et search_wms_data restent des
raccourcis Reading.
D3 reste la règle par défaut : la bascule est un opt-in, avertie dans les
descriptions d'outils (statuts en énumérations en Writing). Garde de valeur
assertValidQueryType dans le code (le wrapper D23 ne valide pas les valeurs),
avant tout réseau. En query_type != 0, un nom inconnu du Metadata Reading
passe tel quel avec warning (allowUnknown du resolver) — conservé aussi dans
la réponse d'erreur si le WMS échoue ensuite. Acté en D25 ; CLAUDE.md nuancé,
L4.1 retiré de la ROADMAP (reliquat : exploration Metrics, rapport à part).
Vérifications rejouées via le protocole (LIMAGRAIN / LIMAGRAI2512) :
- call_query_api(Products, query_type:1, limit:1) -> success, 1 ligne,
queryType:1 dans la réponse.
- call_query_api(Products, query_type:3) -> erreur structurée contenant
'ApplicationMetricDataContext' ne contient pas de définition pour 'Products'.
- call_query_api(Products, query_type:7) -> erreur locale nommant les 4
contextes, aucun [API] POST/GET dans stderr.
- query_wms_entities(Container, limit:1) sans query_type -> comportement
inchangé (resolvedTableName Containers, Reading, pas de champ queryType).
- call_query_api(FooBar123, query_type:1) -> transmis tel quel (payload
QueryType:1 Expression Context.FooBar123...), erreur WMS
ApplicationWritingRepository + warning de résolution dans la réponse.
- count_wms_entities(Product, query_type:1) -> count 51145 (~51160).
Baseline : tools/list 23, resources 6, rejet D23 d'un paramètre inconnu OK.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mesures rafraîchies du 25/08/2026 : Writing (QueryType 1) répond 1 ligne
sur Context.Products, Metrics (3) existe sans Products, CustomApp
renvoie ses workflows CST_ sous la clé entities de GetByApplication.
Découverte consignée en L4.0 : la resource api://catalog documente un
exemple QueryType: 1 (le piège D3), un Select dans l'expression et
l'entité fantôme Aliases.
D25 (rapport D3/query_type) et D26 (clés de cache par application)
réservées. L4.3-L4.5 et l'exploration Metrics explicitement hors
périmètre. Le point délicat resolver/Writing est cadré : nom inconnu du
Reading transmis tel quel avec warning quand query_type != 0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Les deux bornages (L3.1a pagination, L3.1b plafond de volume) partagent
le même vocabulaire de signal — truncated présent uniquement quand la
réponse est coupée, hint actionnable, returned vs total avant coupe —
mais gardent des implémentations locales : paginer et plafonner un
volume sont deux mécanismes distincts, un helper commun forcerait une
abstraction qu'ils n'ont pas. D24 consigne ce contrat, les garde-fous
de cadrage (défauts inchangés, mesure protocolaire qui fait foi) et le
changement de sens de totalParameters.
ROADMAP : L3.1 livré, le lot 3 devenait vide — section retirée ; la
référence à L3.1 dans L4.5 (QueryExecuteStream) renvoie désormais à
D24. read_recent_logs est laissé tel quel : sans helper partagé, rien
de gratuit à lui apporter (L3.1c).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Les vérifications attendues des quatre correctifs ont été rejouées via le
protocole et passent toutes : résolution Container/Alias/Item (échec avant
tout POST, 6 GET seulement), rejet des paramètres inconnus et requis
manquants, garde-fous get_workflow_details/search_logs, corps STS dans
les erreurs d'auth sans fuite de credential. Contrôle latéral séquentiel :
la bascule EUROTRAFIC reconstruit bien la table par tenant (280 entités,
7 applications, contre 288/5 sur LIMAGRAIN).
Trivialité corrigée : tableNames.size (undefined sur un tableau) ->
.length dans le log de chargement du resolver.
Découverte de révision consignée en point ouvert : le serveur traite les
tools/call en concurrence, une bascule de profil pendant des appels en
vol les fait partir sur le nouveau profil.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
authenticate() ré-enveloppait l'erreur axios en "Authentication failed:
Request failed with status code 400" et jetait le corps de la réponse du
STS, qui contenait le diagnostic exact ({"error":"invalid_request",
"error_description":"Tenant not found"} sur le profil AD).
Réutilise _enrichHttpError (L1.1) dans authenticate() et
refreshOAuthToken(), avec payload volontairement omis : il contient les
credentials (password grant) ou le refresh_token ; l'helper n'inclut
jamais les headers. Le chemin "token trop vieux -> password grant" de
refreshOAuthToken() sort du try : un échec d'authenticate() y était
rattrapé pour... rappeler authenticate() à l'identique ; il propage
désormais son erreur enrichie directement.
Mesure (via le protocole) : switch_wms_profile("AD") puis
count_wms_entities("Products") ->
Count failed for Products: Authentication failed: POST
https://10.255.255.2/EasySTS/OAuth/Token failed (HTTP 400): Request
failed with status code 400
Response body: {"error":"invalid_request","error_description":"Tenant
not found"}
Aucun credential ni header dans la réponse (vérifié : pas de
password/Basic/Bearer/payload).
ROADMAP : L3.2 retirée, point ouvert "profil AD" mis à jour.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
Mesure V1 (24/08/2026) : le SDK MCP ignore additionalProperties: false —
read_recent_logs({lines: 5}) avec la clause sur le schéma répondait
success: true, returnedLines: 100 (retombée silencieuse sur le défaut).
La validation vit donc dans le wrapper tools/call de src/index.js,
pilotée par les schémas de la table de routage (D22) : paramètre inconnu
ou requis manquant -> erreur structurée nommant le fautif et les
paramètres valides, avant tout dispatch.
Les 23 schémas portent additionalProperties: false — inerte côté SDK,
mais c'est le contrat que lisent les clients. Pas de renommage de
paramètres (écarté, cf. ROADMAP).
Mesures (via le protocole) :
- read_recent_logs({"lines": 5}) -> "Paramètre(s) inconnu(s) pour
read_recent_logs : lines. Paramètres valides : count, log_file."
- read_recent_logs({"count": 5}) -> succès, returnedLines: 5
- boucle sur 22 outils avec {} (execute_command vérifié statiquement) :
22/22 répondent, aucun Unknown tool, les 11 outils à paramètres requis
échouent avec le message actionnable
- handshake : 23 outils, 6 resources
Docs : D23 dans DECISIONS.md, L2.2 retirée de la ROADMAP.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Context.{entity_type} attend le TableName du Metadata, pas le nom
d'entité de l'AD (Container -> Containers, mais Alias -> Alias) : un nom
faux partait en HTTP 500 de compilation LINQ. Nouveau service
entity-resolver.js : table Name|TableName (insensible à la casse) ->
TableName, agrégée sur les applications déployées (via
GET /configuration/applications — les applications sans contexte
requêtable n'y figurent pas et n'apportent 0 entité Metadata), cache TTL
partagé, invalidation par onSwitch (D8). Branché dans wms-query-service
(query/count/schema/search) et call_query_api.
Nom inconnu -> échec avant tout appel réseau de requête, suggestions
proches + renvoi vers get_entity_metadata. Metadata injoignable -> le
nom passe tel quel avec un warning dans la réponse.
Mesures (LIMAGRAIN, via le protocole) :
- query_wms_entities("Container", limit 1) -> succès, 1 ligne, résolu
Containers
- query_wms_entities("Alias") -> succès, invariant (pas de pluriel)
- query_wms_entities("Item") -> "Item" n'existe pas dans le modèle
Reading. Proches : RFMenuItems, Sites. 288 entités disponibles —
aucune ligne [API] POST dans stderr
- count_wms_entities("Product") -> 51160
- get_entity_schema("Container") et call_query_api("Container") : mêmes
résolutions
- 288 TableName distincts sur 5 applications, aucun conflit
Name -> TableName (mesuré le 24/08/2026)
Docs : D21 dans DECISIONS.md ; CLAUDE.md (piège retiré des points
ouverts, liste d'entités corrigée Aliases -> Alias, entity-resolver dans
la structure) ; exemple singulier/pluriel dans wms://query-examples ;
ROADMAP allégée (cause racine + L2.1 + L3.3 livrés).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lot 1 révisé selon la grille : vérifications L1.1/L1.2/L1.3 rejouées en
protocole (22 outils routés + execute_command en statique), diffs lus,
baseline 23/6 et npm test 4/4 confirmés. Deux anomalies préexistantes
découvertes en bouclant sur les outils avec arguments vides :
get_workflow_details({}) renvoie le premier workflow du cache (clés
mortes Id/Code/Name dans la comparaison), search_logs({}) échoue en
TypeError non actionnable — consignées en L2.3.
handoff-lot1.md supprimé (livré), handoff-lot2.md rédigé : D21 et D23
réservés, profil AD signalé cassé (ne pas réinvestiguer), vérifications
attendues par correctif.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Le lot 1 (erreurs HTTP détaillées, routage par table, projections des
workflows) est livré et vérifié contre le WMS réel — il sort de la
roadmap. D22 étant écrite, L3.2 est ajusté en conséquence.
L4.3 est corrigé d'après mesure : le champ ClientModule de QueryExecute
est accepté mais sans effet observable dans les logs du WMS — une
requête en échec envoyée avec ClientModule: "MCP-WMS" reste tracée
« Execute error. Client: GNA », et la chaîne n'apparaît dans aucun log.
Le champ n'a donc pas été renseigné.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Source : la page d'aide générée https://<host>/ApplicationService/Help, qui
documente des champs et des endpoints que le MCP n'utilise pas. Toutes les
affirmations ci-dessous ont été testées contre LIMAGRAI2512.
D3 corrigé — QueryContextType a quatre valeurs, pas deux :
Reading 0 (ApplicationReadingContext), Writing 1 (ApplicationWritingRepository),
DataWarehouse 2 (non configuré sur ce tenant : IDataWarehouse non résolu),
Metrics 3 (ApplicationMetricDataContext, présent, modèle non exploré). Le
message d'erreur nomme le contexte, ce qui donne un moyen rapide de savoir quel
QueryType a servi.
L4.1 étendu aux quatre contextes.
L4.2 tranché sur son point dur : le champ Application ne partitionne pas le
contexte de lecture. Context.AgvTasks répond aussi bien avec Application AGV
qu'avec EasyWMS — le contexte est commun au tenant. La table de résolution du
lot 2 devra donc agréger le Metadata de toutes les applications, mais un
paramètre application sur QueryExecute serait inutile. Les entités CustomApp
restent inatteignables sous les quatre QueryType, au singulier comme au
pluriel, et Metadata renvoie 0 entité pour cette application : ce sont des
définitions EasyBuilder sans projection requêtable. L'API AD est le seul accès
au spécifique client.
Trois chantiers ajoutés :
- L4.3 ClientModule, non renseigné, d'où des requêtes du MCP journalisées sous
« Client: GNA » et indistinguables du vrai client GNA.
- L4.4 API WorkflowLog (GetInstances, GetLogs, Validate), joignable et
fonctionnelle, susceptible de remettre en cause D16.
- L4.5 champs inexploités de QueryExecute : Parameters (requêtes paramétrées,
piste pour D13), CommandTimeout, QueryId + QueryCancel, QueryExecuteStream
(piste pour L3.1), plus les endpoints event sourcing et les sondes
healthcheck/ready.
CLAUDE.md pointe désormais vers la page d'aide comme source de vérité.
MONITORING.md documente healthcheck/ready comme sonde légère.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deux angles morts mesurés sur le tenant LIMAGRAI2512.
L4.1 — QueryType est figé à 0 (Reading) en dur dans api-service.js : le modèle
Writing est inatteignable. Ce n'est pas une limite de l'API, QueryType 1
répond correctement sur Context.Products — il manque le paramètre. D3 reste
vrai en revanche : en Writing les statuts sont des énumérations, donc le
défaut doit rester 0.
L4.2 — Application vient de WMS_APPLICATION, partagé par tous les profils,
sans surcharge possible. Le MCP n'interroge que EasyWMS alors que
/AD/api/Application/GetAll en déclare 9. CustomApp porte le spécifique client
(153 workflows, 54 queries, 11 entités préfixés CST_) et est entièrement
invisible ; avec AGV, Notifications, GalileoFaults et Common, ce sont 260
workflows hors périmètre.
Côté API AD le correctif est simple, l'application n'étant qu'un champ du
payload — vérifié, ["CustomApp", tenant, 5, 0] renvoie bien les workflows CST_.
Il faudra en revanche indexer les caches par application.
Côté QueryExecute c'est non résolu : passer Application "CustomApp" ne change
pas le contexte de lecture, les entités CST_ ne répondent ni au singulier ni au
pluriel et aucune n'apparaît dans les 232 entités du Metadata EasyWMS. Elles
sont définies dans EasyBuilder (FromMetadata: false). Consigné comme question
ouverte, sans solution promise.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ajoute ROADMAP.md et le relie depuis README.md et CLAUDE.md.
Origine : un rapport d'usage d'une session Cowork sur le profil LIMAGRAIN a
signalé 8 anomalies. Vérification faite contre le WMS réel, 4 bugs sont
confirmés et reproduits, dont un non signalé par le rapport.
Cause racine commune : entity_type est interpolé dans Context.{entity_type}
sans aucune validation, alors que le nom attendu est le TableName de l'API
Metadata et non le nom d'entité de l'AD. Container -> Containers, mais
Alias -> Alias : c'est un mapping, pas une règle de pluralisation. L'API
Metadata connaît 232 entités là où le MCP en expose 12 en dur, et la liste
documentée était fausse (Aliases n'existe pas).
Lot 1 (déblocage) : corps des erreurs HTTP remonté, routage des outils par
table explicite, projections de champs des workflows.
Lot 2 (fond) : résolution des entités via l'API Metadata, rejet des
paramètres inconnus.
Lot 3 : bornage des sorties volumineuses, documentation.
Trois propositions du rapport sont explicitement écartées, avec leur raison :
uniformisation des noms de paramètres, indexStatus sur generic_search, outil
dédié d'aide à la syntaxe.
CLAUDE.md : la section « Points ouverts » renvoie désormais vers la roadmap et
avertit des deux pièges non encore corrigés.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>