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
+1
View File
@@ -275,6 +275,7 @@ function getAvailableTypes() {
}
module.exports = {
resolveApplication,
getElements,
searchElements,
getElementDetails,
+46
View File
@@ -133,6 +133,49 @@ async function fetchApplications() {
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.
* Real AD keys (lowercase, cf. D5): id, name, version, applicationName,
@@ -251,6 +294,9 @@ function getCacheStatus() {
module.exports = {
fetchAllWorkflows,
fetchApplications,
getCachedApplications,
buildOtherApplicationsHint,
resolveApplication,
searchWorkflows,
getWorkflowDetails,
getWorkflowStats,
+11 -1
View File
@@ -247,15 +247,25 @@ async function searchADElementsTool(args) {
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 {
content: [{
type: 'text',
text: JSON.stringify({
success: true,
elementType: element_type,
...(application ? { application } : {}),
application: effectiveApplication,
query,
count: mappedResults.length,
...(hint ? { hint } : {}),
elements: mappedResults
}, null, 2)
}]
+11 -1
View File
@@ -134,13 +134,23 @@ async function searchWorkflows(args) {
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 {
content: [{
type: 'text',
text: JSON.stringify({
success: true,
...(application ? { application } : {}),
application: effectiveApplication,
count: results.length,
...(hint ? { hint } : {}),
// Clés réelles de l'API AD (minuscules, cf. D5) : id, name, version,
// applicationName, commonInfo. Pas de code/category/description.
workflows: results.map(w => {