Commit Graph

12 Commits

Author SHA1 Message Date
Arthur Ria 54a6849563 L5.2 : plafonne la taille de reponse des trois outils de requete
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>
2026-08-25 15:13:51 +02:00
Arthur Ria 6f54d765c4 L5.1 : fenetre verbatim sur le blob data de get_workflow_details
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>
2026-08-25 15:08:13 +02:00
Arthur Ria 92de85cf53 L4.2 : paramètre application sur les outils AD et workflow (D26)
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>
2026-08-25 11:24:12 +02:00
Arthur Ria 706e628715 L4.1 : expose query_type sur les outils de requête (D25)
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>
2026-08-25 11:17:10 +02:00
Arthur Ria d0a6cc1a0b L3.1b : plafonne la taille de réponse de search_logs (MAX_LOG_SEARCH_CHARS)
max_results (50) borne le nombre de résultats mais pas le volume : les
context_lines multiplient la taille, et la réponse aux seuls défauts
atteignait 52-56 000 caractères — rejetée par le client MCP. Le tool
écarte désormais des résultats ENTIERS (jamais coupés au milieu de leur
contexte) jusqu'à passer sous le plafond, et le signale : truncated,
returned/omitted, hint actionnable (affiner keyword, réduire
context_lines, baisser max_results).

Plafond : MAX_LOG_SEARCH_CHARS, variable d'environnement avec défaut
25 000 — même style de lecture que MAX_QUERY_ROWS/QUERY_TIMEOUT
(parseInt(process.env.X) || défaut), documentée dans CLAUDE.md
(réglages partagés). 25 000 correspond à l'ordre de grandeur cible du
lot (~20-25 000 chars) et se mesure sur content[0].text, la taille qui
fait foi côté protocole. Les défauts max_results=50 et context_lines=2
sont inchangés : le correctif est le bornage signalé, pas un changement
de comportement par défaut.

Mesures via le protocole (LIMAGRAIN, content[0].text) :
- {"keyword":"Error"} : avant 52 162 chars / 50 résultats ; après
  24 164 chars, returned 16, omitted 34, truncated true, hint présent.
- {"keyword":"Error","max_results":3} : 4 855 chars, 3/3, pas de
  troncature signalée.
- mot-clé sans occurrence : 112 chars, 0 résultat, pas de truncated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 10:35:49 +02:00
Arthur Ria cb625a7918 L2.1 : résout entity_type via l'API Metadata (D21)
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>
2026-08-24 17:28:27 +02:00
Arthur Ria 03f561fdf7 Supervision : rôle durable de vérification et de passation
Ajoute docs/supervision.md, référencé depuis CLAUDE.md et docs/README.md.

Décrit le rôle de superviseur du projet, distinct des sessions qui codent :
vérifier l'état réel du MCP contre le WMS, réviser leurs livraisons sans les
croire sur parole, et rédiger la passation suivante.

Contient la baseline chiffrée à préserver (23 outils, 6 resources, npm test
4/4) et les mesures de référence du tenant, la boîte à outils de vérification
(handshake MCP, appel d'outil via le protocole, sonde directe de l'API), une
grille de revue en sept points, les six règles de rédaction d'une passation, et
les garde-fous (lecture seule, pas de push, pas de réécriture d'historique).

Consigne les quatre modes d'échec déjà observés sur ce dépôt : taxonomie
inventée, casse de champ supposée, collision de préfixe de routage, hypothèse
présentée comme solution. Ils sont récurrents et se repèrent vite quand on
sait quoi chercher.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:51:08 +02:00
Arthur Ria e0bdc1707d L1.2 : route les outils par table explicite nom -> module (D22)
Le routage par préfixe de nom laissait deux outils listés dans
tools/list mais injoignables : get_entity_metadata (capté par
startsWith('get_entity_') avant sa propre branche) et list_log_files
(aucune branche : le nom contient _log_files, pas _logs).

Une table nom d'outil -> module est construite au démarrage depuis les
listTools() des 8 modules de src/tools/. tools/list est servi depuis
cette même table et le dispatch devient un lookup : un outil listé est
un outil routé, par construction. Deux modules déclarant le même nom
font échouer le serveur au démarrage avec un message nommant les deux
modules. Le wrapper d'erreur du handler tools/call est inchangé, les
23 outils gardent leurs noms.

Vérifié contre le WMS réel : get_entity_metadata renvoie 232 entités,
list_log_files renvoie 19 fichiers, tools/list expose toujours 23
outils et chaque nom listé est traité par le executeTool() de son
module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:43:40 +02:00
Arthur Ria 86923542fa Roadmap et décisions : exploitation de la référence API du service
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>
2026-08-24 15:58:28 +02:00
Arthur Ria 1a1b9ebe03 Roadmap : lots de correction issus du diagnostic du 24/08
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>
2026-08-24 15:39:08 +02:00
Arthur Ria 0ff44f7b78 Documentation : structure README / CLAUDE / DECISIONS / MONITORING
Nouveaux documents :
- README.md : porte d'entrée humaine, absente jusqu'ici. Objet du projet,
  installation, npm test, branchement Claude Desktop, ajout d'un profil WMS,
  compilation de l'exécutable.
- DECISIONS.md : 20 décisions et pièges vérifiés sur un WMS réel (D1..D20),
  chacun avec son pourquoi. Extrait ce qui était noyé dans CLAUDE.md :
  100 % API, tenant_code OAuth, réponses {entities}, casse des propriétés,
  dotenv sur stderr, dates relatives LINQ non traduisibles, absence de
  CommandParameterData, etc.
- MONITORING.md : supervision du serveur MCP. Préfixes de logs, séquence
  d'un démarrage sain, cycle de vie du token OAuth et ses trois filets,
  état des caches, table symptôme -> cause. Une section dit explicitement
  ce qui n'est pas instrumenté (ni healthcheck, ni métriques, ni alerte).
- docs/logs.md : accès aux logs du WMS. Chemins, placeholder {host},
  blocage volontaire sur les profils SaaS, les trois outils, format des
  lignes, limites connues.

Mises à jour :
- CLAUDE.md réécrit et aligné sur le code. Correction de l'écart le plus
  gênant : le code utilise QueryType 0 (Reading), la doc annonçait 1, soit
  l'inverse de ce qui fonctionne pour les comparaisons de statut par
  chaîne. Corrigés également : 6 resources et non 7 (workflows://categories
  n'existe pas), section .env mono-profil obsolète, références à des
  fichiers de test absents, README annoncé mais inexistant. Le suivi de
  projet et les checklists de phases sont retirés.
- docs/README.md : index réel du dossier. L'ancien promettait une resource
  docs:// qui n'a jamais existé.
- docs/getting_started.md : avertissement en tête, c'est une capture
  partielle du portail Mecalux dont les liens internes ne résolvent pas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:15:31 +02:00
Arthur Ria b59cbb3546 version mise à jour par claude , à tester 2026-05-20 09:38:07 +02:00