L5.4 : rendre les autres applications visibles depuis les recherches

Cas reel du 25/08/2026 : une session Cowork cherchant des workflows CST_ sans
passer application="CustomApp" a conclu que l'AD n'en contenait aucun -- alors
que CustomApp en porte 153. Le parametre application existait bien (D26) et
etait documente ; ce qui manquait, c'est que RIEN dans la reponse ne disait
qu'on n'avait regarde qu'une application sur neuf. Un defaut silencieux se lit
comme une exhaustivite.

search_workflows et search_ad_elements rappellent desormais TOUJOURS
l'application effectivement interrogee (plus seulement quand le parametre a ete
passe), et ajoutent un hint quand la recherche revient vide.

Seuil a 0 resultat, pas "peu" : toute valeur non nulle produirait un hint
parasite sur une recherche legitimement etroite, et le mode d'echec observe est
bien le zero pris pour une absence.

Le hint nomme les autres applications depuis la liste allegee DEJA en cache ;
sans elle il reste generique et renvoie vers list_workflow_categories. Aucun
appel reseau n'est fait pour construire un hint -- ce serait exactement le
prechargement que D26 interdit.

Verifie en execution (protocole, LIMAGRAIN) :

  search_workflows {"query":"CST_"}                 404 chars
    application: "EasyWMS", count: 0, hint nommant CustomApp et renvoyant
    vers list_workflow_categories
  search_workflows {"query":"CST_"} apres
    list_workflow_categories                        461 chars
    meme hint, enrichi de la liste en cache : Common, Notifications, SmartUI,
    WarehouseWebDesigner, GalileoFaults, CustomApp, User, AGV
  search_workflows {"query":"CST_","application":"CustomApp"}
    count: 44, application: "CustomApp" -- dont CST_SendRejectContainersToPK
  search_workflows {"query":"stacker"}   14 192 -> 14 220 chars
    count: 50 inchange, application: "EasyWMS" presente, aucun hint parasite
  search_ad_elements Command "CST_"                 457 chars
    application: "EasyWMS", count: 0, meme hint

stderr : aucun fetch d'une application non demandee. Seules EasyWMS et
CustomApp sont chargees, chacune sur demande explicite.

Rebouclage complet apres modification des schemas : 23 outils, 6 resources,
les 23 noms de tools/list atteignent leur module (aucun "Unknown tool" ;
execute_command verifie statiquement, non appele car il ecrit dans le WMS),
D23 rejette toujours un parametre inconnu sur les quatre schemas modifies,
npm test 4/4 en code 0.

Lot 5 retire de la ROADMAP.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Arthur Ria
2026-08-25 15:19:59 +02:00
parent a1acb781b0
commit 660c62c32c
7 changed files with 96 additions and 34 deletions
+4 -1
View File
@@ -191,7 +191,10 @@ cache incluent l'application pour éviter toute pollution croisée (D26).
| `ad-service` | **un par (application, type)** (20 types) | `AD_ELEMENT_TYPES` : `View` 200, `Workflow` 5000, `Resource` 15000, autres 100000 | | `ad-service` | **un par (application, type)** (20 types) | `AD_ELEMENT_TYPES` : `View` 200, `Workflow` 5000, `Resource` 15000, autres 100000 |
**Ne préchargez jamais les 9 applications** : seule l'application demandée est **Ne préchargez jamais les 9 applications** : seule l'application demandée est
chargée (D26). chargée (D26). `search_workflows` et `search_ad_elements` rappellent toujours
l'application interrogée et, sur résultat **vide**, ajoutent un `hint` nommant
les autres — construit depuis la liste d'applications **déjà en cache**, jamais
par un appel réseau (D26).
Les tailles de page par type viennent de l'observation des timeouts serveur — Les tailles de page par type viennent de l'observation des timeouts serveur —
ne les augmentez pas à l'aveugle. ne les augmentez pas à l'aveugle.
+23
View File
@@ -622,3 +622,26 @@ Règles associées :
ne détaille que les entrées **effectivement en cache** : la sortie reste ne détaille que les entrées **effectivement en cache** : la sortie reste
bornée quel que soit le nombre d'applications interrogées (D24). Il expose bornée quel que soit le nombre d'applications interrogées (D24). Il expose
aussi les caches de workflows par application. aussi les caches de workflows par application.
**Le paramètre ne suffisait pas : il faut que la réponse le dise** (lot 5,
25/08/2026). Cas réel : une session Cowork cherchant des workflows `CST_*` sans
passer `application: "CustomApp"` a conclu que l'AD n'en contenait aucun — alors
que `CST_PickingTasksSequencing_PR` et `CST_ChooseDestinationFromPS` existent.
Le paramètre était disponible et documenté ; ce qui manquait, c'est que **rien
dans la réponse ne disait qu'on n'avait regardé qu'une application sur neuf**.
Un défaut silencieux se lit comme une exhaustivité.
`search_workflows` et `search_ad_elements` rappellent donc **toujours**
l'application effectivement interrogée (plus seulement quand le paramètre a été
passé), et ajoutent un `hint` quand la recherche revient **vide** :
- Seuil à **0 résultat**, pas « peu ». Toute valeur non nulle produirait un hint
parasite sur une recherche légitimement étroite, et le mode d'échec observé
est bien le zéro pris pour une absence.
- Le hint nomme les autres applications depuis la liste allégée **déjà en
cache** ; sans elle, il reste générique et renvoie vers
`list_workflow_categories`. **Jamais de fetch pour construire un hint**
ce serait précisément le préchargement que cette décision interdit.
- Il nomme `CustomApp` en clair, sauf quand c'est déjà l'application
interrogée : c'est une connaissance statique, déjà portée par les
descriptions d'outils, pas une donnée à aller chercher.
-31
View File
@@ -82,37 +82,6 @@ plus riche que `/AD/api/Application/GetAll`), `GET /healthcheck?tenantCode=` et
--- ---
---
## 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.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é ## Écarté
| Proposition | Raison | | Proposition | Raison |
+1
View File
@@ -275,6 +275,7 @@ function getAvailableTypes() {
} }
module.exports = { module.exports = {
resolveApplication,
getElements, getElements,
searchElements, searchElements,
getElementDetails, getElementDetails,
+46
View File
@@ -133,6 +133,49 @@ async function fetchApplications() {
return applicationsCache; return applicationsCache;
} }
/**
* Liste des applications déjà en cache, ou null si le cache est vide/expiré.
* Ne déclenche AUCUN appel réseau c'est ce qui permet d'enrichir une réponse
* de recherche sans jamais précharger une application non demandée (D26).
* @returns {Array<{name: string, id: string, version: number}>|null}
*/
function getCachedApplications() {
if (applicationsCache && applicationsTimestamp &&
Date.now() - applicationsTimestamp < CACHE_TTL) {
return applicationsCache;
}
return null;
}
/**
* Hint de découvrabilité (L5.4). Une recherche n'interroge qu'UNE application
* sur les neuf déclarées, et rien dans la réponse ne le disait : une session
* cherchant des workflows `CST_*` sans `application: "CustomApp"` a conclu à
* tort qu'il n'y en avait aucun (25/08/2026).
*
* Les autres applications sont nommées depuis la liste allégée **déjà en
* cache** ; sans elle, le hint reste générique et renvoie vers
* `list_workflow_categories` jamais de fetch pour construire un hint.
*
* @param {string} application - application effectivement interrogée
* @param {string} sujet - ce qui a été cherché ('workflow', 'élément Command')
*/
function buildOtherApplicationsHint(application, sujet) {
const cached = getCachedApplications();
const others = (cached || []).map(a => a.name).filter(n => n !== application);
const liste = others.length
? `Autres applications déclarées sur ce tenant : ${others.join(', ')}.`
: `Appelez list_workflow_categories pour lister les autres applications déclarées.`;
const custom = application.toLowerCase() === 'customapp'
? ''
: ` Le spécifique client (préfixe CST_) vit dans "CustomApp" : relancez avec application: "CustomApp".`;
return `Aucun ${sujet} trouvé dans l'application "${application}" — c'est la SEULE interrogée, ` +
`les autres ne le sont jamais implicitement.${custom} ${liste}`;
}
/** /**
* Search workflows by query string. * Search workflows by query string.
* Real AD keys (lowercase, cf. D5): id, name, version, applicationName, * Real AD keys (lowercase, cf. D5): id, name, version, applicationName,
@@ -251,6 +294,9 @@ function getCacheStatus() {
module.exports = { module.exports = {
fetchAllWorkflows, fetchAllWorkflows,
fetchApplications, fetchApplications,
getCachedApplications,
buildOtherApplicationsHint,
resolveApplication,
searchWorkflows, searchWorkflows,
getWorkflowDetails, getWorkflowDetails,
getWorkflowStats, getWorkflowStats,
+11 -1
View File
@@ -247,15 +247,25 @@ async function searchADElementsTool(args) {
code: e.code || e.Code code: e.code || e.Code
})); }));
// L5.4 : même correctif que search_workflows — l'application interrogée est
// toujours rappelée, et un résultat vide signale que les huit autres n'ont
// pas été regardées. Le hint se construit depuis la liste d'applications
// DÉJÀ en cache : aucun appel réseau, aucun préchargement (D26).
const effectiveApplication = adService.resolveApplication(application);
const hint = mappedResults.length === 0
? workflowService.buildOtherApplicationsHint(effectiveApplication, `élément ${element_type}`)
: null;
return { return {
content: [{ content: [{
type: 'text', type: 'text',
text: JSON.stringify({ text: JSON.stringify({
success: true, success: true,
elementType: element_type, elementType: element_type,
...(application ? { application } : {}), application: effectiveApplication,
query, query,
count: mappedResults.length, count: mappedResults.length,
...(hint ? { hint } : {}),
elements: mappedResults elements: mappedResults
}, null, 2) }, null, 2)
}] }]
+11 -1
View File
@@ -134,13 +134,23 @@ async function searchWorkflows(args) {
const results = await workflowService.searchWorkflows(query, category, limit, application); const results = await workflowService.searchWorkflows(query, category, limit, application);
// L5.4 : l'application interrogée est TOUJOURS rappelée (pas seulement quand
// elle a été passée), et un résultat vide dit qu'une seule application sur
// neuf a été regardée — c'est ce silence qui avait fait conclure à tort à
// l'absence de workflows CST_.
const effectiveApplication = workflowService.resolveApplication(application);
const hint = results.length === 0
? workflowService.buildOtherApplicationsHint(effectiveApplication, 'workflow')
: null;
return { return {
content: [{ content: [{
type: 'text', type: 'text',
text: JSON.stringify({ text: JSON.stringify({
success: true, success: true,
...(application ? { application } : {}), application: effectiveApplication,
count: results.length, count: results.length,
...(hint ? { hint } : {}),
// Clés réelles de l'API AD (minuscules, cf. D5) : id, name, version, // Clés réelles de l'API AD (minuscules, cf. D5) : id, name, version,
// applicationName, commonInfo. Pas de code/category/description. // applicationName, commonInfo. Pas de code/category/description.
workflows: results.map(w => { workflows: results.map(w => {