[FIX] ARIA: mappa navigazione reale + contesto pagina (ticket #424)
ARIA citava voci di menu inesistenti (es. 'A4 - Analisi e Valutazione del Rischio' / 'Fase 4.1 - Inventario') non corrispondenti alla barra laterale, e non sapeva da quale pagina scrivesse l'utente. - AIService::askWithRag: iniettata la mappa REALE della sidebar (navigationMapBlock, sincronizzata con common-bi.js) con regole che vietano di inventare menu/fasi/codici; aggiunto contesto pagina utente. - AiController::ask: accetta e passa il campo 'page' dal frontend. - common.js (ARIA FAB): invia la pagina corrente in /api/ai/ask. - Cache-buster common.js 20260623->20260623h su tutte le pagine. NB: questo commit include anche il fix #419 gia' applicato e live in common.js (email bug-reporter recuperata via api.getMe quando assente nelle claims JWT), finora non committato — incluso come backup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d45bd472cd
commit
ea5966eaee
@@ -39,10 +39,14 @@ class AiController extends BaseController
|
||||
}
|
||||
|
||||
$user = $this->getCurrentUser() ?? [];
|
||||
// Pagina corrente (facoltativa) inviata dal frontend, per dare ad ARIA
|
||||
// contesto sulla schermata da cui l'utente sta scrivendo (ticket #424).
|
||||
$page = mb_substr(trim((string) $this->getParam('page', '')), 0, 120);
|
||||
$userContext = [
|
||||
'user_id' => $userId,
|
||||
'organization_id' => $this->getCurrentOrgId(), // può essere null
|
||||
'consulting_firm_id' => $user['consulting_firm_id'] ?? null,
|
||||
'page' => $page,
|
||||
];
|
||||
|
||||
try {
|
||||
|
||||
@@ -56,6 +56,30 @@ class AIService
|
||||
. "5. ENISA, NIST e ISO sono best practice di settore, NON fonti normative vincolanti: gli obblighi italiani derivano da Direttiva (UE) 2022/2555, D.Lgs. 138/2024 e Determinazioni ACN.\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Mappa REALE della barra laterale dell'applicazione, da iniettare nel
|
||||
* system prompt dell'assistente ARIA cosi' che le indicazioni di navigazione
|
||||
* usino i nomi ESATTI del menu e non vengano inventati moduli/fasi inesistenti.
|
||||
*
|
||||
* ⚠️ TENERE SINCRONIZZATA con la fonte di verita' della sidebar:
|
||||
* public/js/common-bi.js (array navItems). Se aggiungi/rinomini una voce
|
||||
* di menu li', aggiorna anche questo elenco.
|
||||
* (Ticket #424, 2026-06-23: ARIA citava voci di menu inesistenti.)
|
||||
*/
|
||||
private function navigationMapBlock(): string
|
||||
{
|
||||
return "\n## MAPPA DELLA NAVIGAZIONE (barra laterale REALE dell'app)\n"
|
||||
. "Sezione \"Principale\": Dashboard · Calendario · Compliance Journey · Gap Analysis · Misure e Requisiti · Modello SGSI (ISO 27001).\n"
|
||||
. "Sezione \"Gestione\": Organigramma · Competenze · Rischi · Incidenti · Policy · Supply Chain · Stakeholder · Attivita' stakeholder · Segnalazioni · Normative · AI Cross-Analysis · Knowledge Base.\n"
|
||||
. "Sezione \"Operativo\": Formazione · Inventario · Audit interni · Controlli periodici · Riesame di Direzione · Audit & Report.\n"
|
||||
. "Sezione \"Sistema\": Guida all'uso · Impostazioni · Architettura · Simulazione Demo · Integrazioni Esterne.\n"
|
||||
. "\nREGOLE DI NAVIGAZIONE (vincolanti):\n"
|
||||
. "1. Quando indichi DOVE cliccare o COME raggiungere una funzione, usa ESCLUSIVAMENTE i nomi delle voci qui sopra, esattamente come scritti, indicando la sezione (es. \"nella sezione Operativo, voce Inventario\").\n"
|
||||
. "2. NON inventare nomi di menu, \"fasi\", codici (es. \"A4\", \"Fase 4.1\") o moduli che NON compaiono in questo elenco.\n"
|
||||
. "3. L'inventario degli asset si trova in: sezione Operativo > Inventario. La valutazione del rischio in: sezione Gestione > Rischi. Misure e requisiti in: sezione Principale > Misure e Requisiti.\n"
|
||||
. "4. Se l'utente cerca una funzione che non corrisponde ad alcuna voce, dillo chiaramente e suggerisci la voce piu' vicina, senza inventarne una.\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Analizza risultati gap analysis e genera raccomandazioni
|
||||
*/
|
||||
@@ -702,9 +726,20 @@ PROMPT;
|
||||
error_log('[AIService::askWithRag] RAG failed, fallback diretto: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$systemPrompt = "Sei un esperto consulente di cybersecurity NIS2 (EU 2022/2555) e D.Lgs. 138/2024.\n"
|
||||
$systemPrompt = "Sei ARIA, l'assistente dell'applicazione NIS2 Agile, esperta di cybersecurity NIS2 (EU 2022/2555) e D.Lgs. 138/2024.\n"
|
||||
. "Rispondi in modo preciso e cita le fonti del contesto quando rilevanti.\n"
|
||||
. $this->authoritativeSourcesBlock();
|
||||
. $this->authoritativeSourcesBlock()
|
||||
. $this->navigationMapBlock();
|
||||
|
||||
// Pagina corrente dell'utente (se inviata dal frontend): aiuta ARIA a
|
||||
// dare indicazioni contestuali invece di rimandare a moduli a caso.
|
||||
$page = trim((string) ($userContext['page'] ?? ''));
|
||||
if ($page !== '') {
|
||||
$systemPrompt .= "\n## CONTESTO UTENTE\n"
|
||||
. "L'utente si trova attualmente nella pagina: \"" . $page . "\". "
|
||||
. "Tieni conto di dove si trova quando dai indicazioni di navigazione.\n";
|
||||
}
|
||||
|
||||
if (!empty($contextBlock)) {
|
||||
$systemPrompt .= "\n## Contesto documentale (knowledge base)\n" . $contextBlock
|
||||
. "\n\nQuando rispondi, cita esplicitamente i numeri tra parentesi quadre [1], [2], ... che corrispondono ai documenti del contesto.";
|
||||
|
||||
Reference in New Issue
Block a user