diff --git a/ROADMAP.md b/ROADMAP.md index 0ef98a2..97a5bf8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -12,31 +12,11 @@ contient que ce qui reste à faire. --- -## Lot 2 — Correctif de fond - -La cause racine commune du lot (résolution `Name` -> `TableName` via l'API -Metadata) est livrée — la règle et ses mesures vivent en **D21**. - -### L2.3 — Arguments manquants : deux garde-fous - -Découverts lors de la révision du lot 1 (24/08/2026), en bouclant sur les 23 -outils avec des arguments vides. Préexistants au lot 1 (vérifié sur le diff) : - -- `get_workflow_details` sans `workflow_id` renvoie `success: true` avec **le - premier workflow du cache**. Cause : `getWorkflowDetails()` - (`workflow-service.js`) compare `w.Code === workflowId` — or `Code`, `Id`, - `Name` n'existent pas sur les objets réels (clés minuscules, D5), donc - `undefined === undefined` matche. Supprimer les clés mortes de la - comparaison et rejeter un `workflow_id` absent avec un message actionnable. -- `search_logs` sans terme de recherche renvoie - `Search failed: Cannot read properties of undefined (reading 'toLowerCase')` - — le contrat d'erreur tient, mais le message viole la convention 4 - (actionnable). Garde d'entrée avec le nom du paramètre attendu. - ---- - ## 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` : ajouter `limit` / `offset`, aujourd'hui absents diff --git a/src/services/workflow-service.js b/src/services/workflow-service.js index df010f6..bfb3149 100644 --- a/src/services/workflow-service.js +++ b/src/services/workflow-service.js @@ -132,22 +132,24 @@ async function searchWorkflows(query, category = null, limit = 50) { * @param {string|number} workflowId - Workflow ID */ async function getWorkflowDetails(workflowId) { + // Garde d'entrée : sans elle, un workflow_id absent matchait le premier + // workflow du cache (undefined === undefined sur les clés mortes ci-dessous). + if (workflowId == null || workflowId === '') { + throw new Error('workflow_id est requis (id ou nom exact du workflow). Utilisez search_workflows pour le trouver.'); + } + const workflows = await fetchAllWorkflows(); - // Try to find by Id, id, Code, code, Name, or name + // Clés réelles de l'API AD (minuscules, D5) : id, name. Les variantes + // Id/Code/Name n'existent pas sur ces objets — les comparer faisait matcher + // undefined === undefined dès que workflow_id manquait. const workflow = workflows.find(w => w.id === workflowId || - w.Id === workflowId || - w.id === parseInt(workflowId) || - w.Id === parseInt(workflowId) || - w.Code === workflowId || - w.code === workflowId || - w.Name === workflowId || w.name === workflowId ); if (!workflow) { - throw new Error(`Workflow not found: ${workflowId}`); + throw new Error(`Workflow not found: ${workflowId}. Utilisez search_workflows pour trouver l'id ou le nom exact.`); } return workflow; diff --git a/src/tools/log-tools.js b/src/tools/log-tools.js index 30078f7..e265946 100644 --- a/src/tools/log-tools.js +++ b/src/tools/log-tools.js @@ -174,6 +174,12 @@ async function searchLogs(args) { const { keyword, max_results = 50, context_lines = 2 } = args; try { + // Garde d'entrée : sans elle, un keyword absent plantait en + // "Cannot read properties of undefined (reading 'toLowerCase')". + if (typeof keyword !== 'string' || keyword.trim() === '') { + throw new Error('Le paramètre "keyword" (mot-clé à rechercher) est requis. Exemple : search_logs({"keyword": "Execute error"}).'); + } + const result = await logService.searchLogs(keyword, max_results, context_lines); return {