# Analisi tecnica implementativa — Chrome Built-in AI nel GUI Installer MCP

## Metadati analisi

| Campo | Valore |
| --- | --- |
| Skill caricata | `mcp-technical-analyst` |
| File `.md` caricati | `skills/mcp-technical-analyst/SKILL.md`; `references/analysis-workflow.md`; `references/ticket-first-light.md`; `references/source-matrix.md`; `references/deliverable-templates.md`; `references/interactive-escalation.md`; `references/functional-exploration.md` |
| Repository target | `sophiadeveloper/mcp-servers` |
| Branch target | `master` |
| Commit/ref | Non fornito dall'utente; analisi su branch `master` disponibile via GitHub connector |
| Fonte funzionale primaria | Richiesta utente: valutare e preparare sviluppo di un caso d'uso Chrome Built-in AI nella GUI installer |
| Fonti non accessibili | Verifica live del contenuto attuale di `https://developer.chrome.com/docs/ai/built-in?hl=it` non eseguita in questa sessione; prima dello sviluppo va ricontrollato lo stato aggiornato delle API Chrome Built-in AI |

## Sintesi

È tecnicamente sensato introdurre Chrome Built-in AI nella GUI installer como funzionalità **assistiva, locale e opzionale**, non come componente decisionale del flusso di installazione.

Il caso d'uso consigliato è:

> Aggiungere nel GUI installer un assistente locale che spiega all'utente il piano di installazione/allineamento, riassume il changelog granulare e chiarisce rischi/impatti delle selezioni correnti, usando le Built-in AI API di Chrome quando disponibili e un fallback deterministico quando non disponibili.

La feature deve essere progettata come enhancement progressivo:

1. nessun blocco del caricamento UI;
2. nessuna modifica automatica alle selezioni;
3. nessuna chiamata server o backend LLM;
4. feature detection obbligatoria;
5. fallback testuale deterministico sempre disponibile;
6. nessun inserimento nel path critico di installazione.

## Scope e fonti consultate

### Fonti repository

- `scripts/gui-server.js`
- `scripts/gui/app.js`
- `scripts/gui/index.html`

### Evidenze repository

Il server locale della GUI espone `/api/state`, che restituisce già i dati necessari per costruire una spiegazione dell'installazione:

- `homePath`
- `installedCommit`
- `currentCommit`
- `installedAt`
- `diff`
- `dependencies`
- `menuItems`
- `prevSelections`

Riferimento osservato: `scripts/gui-server.js`, endpoint `GET /api/state`, costruzione di `stateResponse`.

Il frontend carica lo stato via `fetchState()`, valorizza `stateData`, ricostruisce `currentSelections`, aggiorna stato repository/ultima installazione, renderizza alberi e dipendenze.

Riferimento osservato: `scripts/gui/app.js`, funzione `fetchState()`.

Il frontend contiene già un modal di changelog granulare, popolato da `stateData.diff.added`, `stateData.diff.modified`, `stateData.diff.removed`.

Riferimento osservato: `scripts/gui/app.js`, funzione `showChangelogModal()`.

La pagina HTML contiene già:

- pulsante `Visualizza Modifiche Granulari`;
- modal `modal-changelog`;
- area `changelog-content`;
- tab Codex, Copilot, Antigravity, Installazione, Analytics;
- sezione Dipendenze di Sistema.

Riferimento osservato: `scripts/gui/index.html`.

Il flusso di installazione è già separato e deterministico:

- `POST /api/install` salva le selezioni e lancia `scripts/install-user-runtime.js`;
- `POST /api/install-dependency` installa una dipendenza specifica;
- i log sono pubblicati via SSE su `/api/logs`.

Riferimento osservato: `scripts/gui-server.js`.

## Evidenze osservate

### Evidenza 1 — La GUI dispone già del modello dati adatto

`/api/state` produce uno snapshot sufficiente per generare una spiegazione utente senza interrogare il filesystem dal browser e senza aggiungere nuove API backend.

Dati rilevanti:

```js
{
  homePath,
  defaultHomePath,
  installedCommit,
  currentCommit,
  installedAt,
  diff,
  dependencies,
  menuItems,
  prevSelections
}
```

### Evidenza 2 — Il changelog granulare è già calcolato

`showChangelogModal()` non calcola diff: lo presenta. Questo rende semplice aggiungere un riepilogo AI sopra o sotto l'elenco esistente, usando lo stesso `stateData.diff`.

### Evidenza 3 — Il frontend è vanilla JavaScript

La GUI non richiede framework frontend. L'integrazione deve quindi essere implementata come modulo JS semplice, preferibilmente in un nuovo file o in una sezione isolata di `app.js`.

### Evidenza 4 — Il flusso installativo non deve dipendere dall'AI

Le azioni con effetto sono server-side e già protette da token GUI:

- installazione runtime;
- installazione dipendenze;
- scan analytics;
- delete analytics.

L'AI deve restare read-only lato UI.

### Evidenza 5 — La GUI è localhost

Il server ascolta su `127.0.0.1:3000` e consente origin solo localhost/host previsto. Questo è coerente con una feature locale, ma non elimina la necessità di minimizzare i dati inviati al modello browser-side.

## Inferenze tecniche

### Inferenza 1 — Il caso d'uso più robusto è “spiegazione del piano”

La feature più utile e meno rischiosa è un assistente che converte dati strutturati già disponibili in testo operativo:

- cosa verrà installato;
- cosa è nuovo;
- cosa è modificato;
- cosa risulta rimosso;
- quali dipendenze mancano;
- cosa cambia con `Solo nuovi o modificati`;
- quali runtime sono coinvolti.

### Inferenza 2 — Prompt API e Summarizer API vanno trattate come opzionali

Le Chrome Built-in AI API possono avere vincoli di browser, piattaforma, lingua, disponibilità del modello e stato sperimentale. L'implementazione deve quindi:

- usare feature detection;
- verificare disponibilità a runtime;
- mostrare uno stato “AI locale non disponibile” non bloccante;
- usare fallback deterministico.

### Inferenza 3 — Non serve un nuovo endpoint backend per l'MVP

Per il primo rilascio il browser può usare `stateData` già caricato. Un endpoint dedicato diventerebbe utile solo se si volesse normalizzare il payload server-side o aggiungere dati non esposti oggi.

### Inferenza 4 — La feature può migliorare anche troubleshooting e analytics, ma in step successivi

Dopo il primo MVP, le stesse primitive possono essere riusate per:

- spiegare errori di installazione dai log SSE;
- riassumere analytics locali;
- spiegare l'impatto delle dipendenze mancanti.

Questi casi sono secondari perché più vicini a diagnosi/interpretazione e quindi più sensibili ad allucinazioni.

## Requisiti funzionali

### RF-01 — Stato AI locale

La GUI deve mostrare se l'assistente AI locale è:

- disponibile;
- in download/preparazione modello;
- non disponibile;
- disabilitato per incompatibilità browser/API.

### RF-02 — Riepilogo changelog assistito

Nel modal `Changelog Modifiche Granulari` deve essere aggiunto un pulsante:

> Riassumi con AI locale

Quando premuto, il sistema deve generare una sintesi leggibile basata su:

- `stateData.diff.added`;
- `stateData.diff.modified`;
- `stateData.diff.removed`;
- `stateData.dependencies`;
- `currentSelections`;
- `onlyChangedCheckbox.checked`;
- `installedCommit`;
- `currentCommit`.

### RF-03 — Fallback deterministico

Se le API Chrome Built-in AI non sono disponibili, il pulsante deve produrre comunque un riepilogo deterministico, ad esempio:

```text
Sono presenti 3 elementi nuovi, 5 modificati e 0 rimossi.
Dipendenze mancanti: pandoc, vtracer.
Modalità "solo nuovi o modificati": attiva.
Runtime coinvolti: Codex, Copilot.
```

### RF-04 — Nessuna azione automatica

L'assistente non deve:

- cambiare `currentSelections`;
- lanciare installazioni;
- installare dipendenze;
- salvare stato;
- inviare richieste agli endpoint `POST`.

### RF-05 — Payload minimizzato

Il payload passato all'AI deve contenere solo dati tecnici non sensibili e già visibili in UI. Non deve includere:

- path home completo se non necessario;
- token GUI;
- variabili ambiente;
- log completi;
- dati analytics grezzi;
- contenuti di file locali.

### RF-06 — Output marcato come assistivo

La UI deve indicare che il testo AI è un supporto interpretativo e che il piano effettivo resta quello determinato dalle selezioni visibili.

## Requisiti non funzionali

### RNF-01 — Privacy-first

La feature deve essere locale/browser-side. Non devono essere introdotte chiamate a servizi LLM remoti.

### RNF-02 — Progressività

La GUI deve funzionare invariata su browser non compatibili.

### RNF-03 — Determinismo del core

Il comportamento installativo deve restare identico con AI abilitata o disabilitata.

### RNF-04 — Manutenibilità

Isolare la logica AI in funzioni dedicate:

- `detectBuiltInAiCapabilities()`
- `buildInstallerAiContext()`
- `generateAiSummary()`
- `generateDeterministicSummary()`
- `renderAiSummary()`

### RNF-05 — Sicurezza

Non interpolare output AI con `innerHTML`. Usare `innerText`/`textContent` o sanitizzazione esplicita.

## Proposta implementativa

### Fase 1 — Preparazione UI

File: `scripts/gui/index.html`

Aggiungere nel modal `modal-changelog`, preferibilmente tra header e `changelog-content`, una sezione dedicata:

```html
<div class="ai-assist-panel" id="ai-assist-panel">
  <div class="ai-assist-header">
    <span class="ai-assist-title">Assistente locale</span>
    <span class="ai-assist-status" id="ai-assist-status">Verifica disponibilità...</span>
  </div>
  <div class="ai-assist-actions">
    <button id="btn-ai-summarize-changelog" class="btn btn-secondary">
      Riassumi con AI locale
    </button>
  </div>
  <div class="ai-assist-output" id="ai-assist-output" hidden></div>
</div>
```

Note:

- il pulsante deve essere visibile anche se l'AI non è disponibile;
- in assenza di AI userà il fallback deterministico;
- lo stato deve chiarire se il risultato è AI o fallback.

### Fase 2 — Stile

File: `scripts/gui/app.css`

Aggiungere classi isolate:

```css
.ai-assist-panel {}
.ai-assist-header {}
.ai-assist-title {}
.ai-assist-status {}
.ai-assist-actions {}
.ai-assist-output {}
.ai-assist-output.is-error {}
.ai-assist-output.is-fallback {}
```

Non usare stili inline nuovi salvo coerenza con pattern già presenti.

### Fase 3 — Feature detection

File: `scripts/gui/app.js`

Aggiungere stato globale:

```js
let builtInAiStatus = {
  checked: false,
  available: false,
  api: null,
  reason: null
};
```

Funzione proposta:

```js
async function detectBuiltInAiCapabilities() {
  const status = {
    checked: true,
    available: false,
    api: null,
    reason: null
  };

  try {
    if ('Summarizer' in window) {
      status.available = true;
      status.api = 'Summarizer';
      return status;
    }

    if ('LanguageModel' in window) {
      status.available = true;
      status.api = 'LanguageModel';
      return status;
    }

    status.reason = 'Chrome Built-in AI API non disponibile in questo browser.';
    return status;
  } catch (err) {
    status.reason = err.message;
    return status;
  }
}
```

Nota implementativa: i nomi e i metodi effettivi delle API Chrome Built-in AI devono essere ricontrollati sulla documentazione ufficiale al momento dello sviluppo. La logica sopra è volutamente un adapter, non una specifica definitiva.

### Fase 4 — Costruzione contesto

File: `scripts/gui/app.js`

Aggiungere:

```js
function buildInstallerAiContext() {
  const diff = stateData?.diff || { added: [], modified: [], removed: [] };
  const dependencies = stateData?.dependencies || {};

  const missingDependencies = Object.entries(dependencies)
    .filter(([, value]) => !value.available)
    .map(([key, value]) => ({
      key,
      name: value.name
    }));

  const selectedItems = (stateData?.menuItems || [])
    .filter(item => currentSelections[item.key] === 'checked')
    .map(item => ({
      key: item.key,
      name: item.name,
      status: item.status || null,
      level: item.level || 0,
      parent: item.parent || null
    }));

  return {
    installedCommit: stateData?.installedCommit || null,
    currentCommit: stateData?.currentCommit || null,
    onlyChanged: onlyChangedCheckbox.checked,
    diffCounts: {
      added: diff.added.length,
      modified: diff.modified.length,
      removed: diff.removed.length
    },
    diffSample: {
      added: diff.added.slice(0, 30),
      modified: diff.modified.slice(0, 30),
      removed: diff.removed.slice(0, 30)
    },
    missingDependencies,
    selectedItems: selectedItems.slice(0, 80)
  };
}
```

Vincoli:

- usare limiti (`slice`) per evitare prompt troppo lunghi;
- non includere token o path locali completi;
- evitare log e analytics raw.

### Fase 5 — Fallback deterministico

File: `scripts/gui/app.js`

Aggiungere:

```js
function generateDeterministicSummary(context) {
  const parts = [];

  parts.push(`Elementi nuovi: ${context.diffCounts.added}.`);
  parts.push(`Elementi modificati: ${context.diffCounts.modified}.`);
  parts.push(`Elementi rimossi: ${context.diffCounts.removed}.`);
  parts.push(`Modalità solo nuovi/modificati: ${context.onlyChanged ? 'attiva' : 'non attiva'}.`);

  if (context.missingDependencies.length > 0) {
    parts.push(`Dipendenze mancanti: ${context.missingDependencies.map(d => d.name || d.key).join(', ')}.`);
  } else {
    parts.push('Nessuna dipendenza mancante rilevata.');
  }

  if (context.installedCommit && context.currentCommit && context.installedCommit !== context.currentCommit) {
    parts.push(`Repository non allineato: ${String(context.installedCommit).slice(0, 10)} -> ${String(context.currentCommit).slice(0, 10)}.`);
  }

  return parts.join('\n');
}
```

### Fase 6 — Generazione AI

File: `scripts/gui/app.js`

Proposta adapter:

```js
async function generateAiSummary(context) {
  const fallback = generateDeterministicSummary(context);

  if (!builtInAiStatus.available) {
    return {
      source: 'fallback',
      text: fallback
    };
  }

  const prompt = [
    'Sei un assistente tecnico locale per un installer MCP.',
    'Spiega in italiano, in modo sintetico e operativo, il piano di installazione/allineamento.',
    'Non proporre azioni automatiche. Non inventare elementi non presenti nel JSON.',
    'Distingui: modifiche, dipendenze mancanti, rischi e prossimi controlli.',
    '',
    JSON.stringify(context, null, 2)
  ].join('\n');

  try {
    if (builtInAiStatus.api === 'LanguageModel' && window.LanguageModel) {
      const session = await window.LanguageModel.create();
      const text = await session.prompt(prompt);
      if (session.destroy) session.destroy();

      return {
        source: 'ai',
        text
      };
    }

    if (builtInAiStatus.api === 'Summarizer' && window.Summarizer) {
      const summarizer = await window.Summarizer.create({
        type: 'key-points',
        format: 'markdown',
        length: 'medium'
      });
      const text = await summarizer.summarize(prompt);
      if (summarizer.destroy) summarizer.destroy();

      return {
        source: 'ai',
        text
      };
    }

    return {
      source: 'fallback',
      text: fallback
    };
  } catch (err) {
    return {
      source: 'fallback',
      text: `${fallback}\n\nNota: AI locale non utilizzabile: ${err.message}`
    };
  }
}
```

Nota: verificare firma effettiva delle API Chrome Built-in AI prima del merge. I nomi `LanguageModel`, `Summarizer`, `create`, `prompt`, `summarize`, `destroy` sono da trattare come adapter da allineare alla documentazione corrente.

### Fase 7 — Rendering sicuro

File: `scripts/gui/app.js`

Aggiungere riferimenti DOM:

```js
const aiAssistStatus = document.getElementById('ai-assist-status');
const aiSummarizeChangelogBtn = document.getElementById('btn-ai-summarize-changelog');
const aiAssistOutput = document.getElementById('ai-assist-output');
```

Aggiungere renderer:

```js
function renderAiSummary(result) {
  aiAssistOutput.hidden = false;
  aiAssistOutput.classList.toggle('is-fallback', result.source === 'fallback');
  aiAssistOutput.textContent = result.text;

  aiAssistStatus.innerText = result.source === 'ai'
    ? 'Sintesi generata con AI locale'
    : 'Sintesi fallback deterministica';
}
```

Hook evento:

```js
aiSummarizeChangelogBtn.addEventListener('click', async () => {
  aiSummarizeChangelogBtn.setAttribute('disabled', 'true');
  aiAssistStatus.innerText = 'Generazione sintesi in corso...';

  try {
    const context = buildInstallerAiContext();
    const result = await generateAiSummary(context);
    renderAiSummary(result);
  } finally {
    aiSummarizeChangelogBtn.removeAttribute('disabled');
  }
});
```

Durante `DOMContentLoaded`:

```js
builtInAiStatus = await detectBuiltInAiCapabilities();
aiAssistStatus.innerText = builtInAiStatus.available
  ? `AI locale disponibile (${builtInAiStatus.api})`
  : 'AI locale non disponibile: verrà usato il fallback';
```

## Piano file-by-file

### `scripts/gui/index.html`

Modifiche:

- aggiungere pannello assistente nel modal changelog;
- aggiungere bottone `btn-ai-summarize-changelog`;
- aggiungere contenitore output `ai-assist-output`.

Rischio: basso.

### `scripts/gui/app.css`

Modifiche:

- aggiungere styling pannello AI;
- distinguere output fallback e output AI;
- garantire leggibilità nel tema esistente.

Rischio: basso.

### `scripts/gui/app.js`

Modifiche:

- aggiungere feature detection;
- aggiungere build context;
- aggiungere fallback deterministic summary;
- aggiungere adapter Chrome Built-in AI;
- aggiungere event listener;
- usare `textContent`, non `innerHTML`, per output AI.

Rischio: medio-basso per compatibilità browser; basso per installazione se la feature resta isolata.

### `scripts/gui-server.js`

Modifiche per MVP: nessuna.

Possibile evoluzione futura:

- endpoint read-only `/api/ai/context` per generare un contesto già normalizzato;
- utile se si vuole evitare logica di riduzione dati nel frontend.

Per ora non consigliato: aumenta superficie API senza necessità.

## Validazioni consigliate

### Test manuali funzionali

1. Aprire GUI installer su browser non compatibile.
2. Aprire `Visualizza Modifiche Granulari`.
3. Premere `Riassumi con AI locale`.
4. Verificare che venga generato fallback deterministico.
5. Verificare che nessuna selezione venga modificata.
6. Verificare che `Avvia Installazione / Allineamento` funzioni come prima.

### Test su Chrome compatibile

1. Abilitare le condizioni richieste dalle Built-in AI API secondo documentazione Chrome corrente.
2. Aprire GUI installer.
3. Verificare stato `AI locale disponibile`.
4. Generare sintesi.
5. Verificare che il testo non inventi elementi fuori da `diff`, `dependencies`, `menuItems`.

### Test regressione UI

1. Changelog senza differenze.
2. Changelog con solo aggiunti.
3. Changelog con modificati e rimossi.
4. Dipendenze tutte disponibili.
5. Dipendenze mancanti.
6. Opzione `Solo nuovi o modificati` attiva/disattiva.

### Test sicurezza

1. Verificare che output AI venga renderizzato con `textContent`.
2. Verificare assenza di token GUI nel payload AI.
3. Verificare assenza di path home completi se non necessari.
4. Verificare che non vengano chiamati endpoint `POST` dalla feature AI.
5. Verificare che i log completi non vengano passati al modello.

## Rischi

### Rischio 1 — API Chrome non disponibile o instabile

Mitigazione:

- feature detection;
- fallback deterministico;
- nessun blocco del flusso UI.

### Rischio 2 — Output AI non deterministico

Mitigazione:

- testo marcato come assistivo;
- prompt vincolato al JSON;
- nessuna azione automatica;
- output breve;
- preferire riepilogo a raccomandazioni operative vincolanti.

### Rischio 3 — Supporto lingua italiana non uniforme

Mitigazione:

- fallback italiano deterministico;
- prompt in italiano;
- test esplicito su Chrome compatibile;
- se necessario, usare output strutturato/fallback anziché affidarsi a generazione libera.

### Rischio 4 — Privacy e dati locali

Mitigazione:

- payload minimizzato;
- no log raw;
- no analytics raw;
- no path completi;
- no token;
- solo dati già presenti nella UI.

## Punti aperti

1. Verificare sul sito Chrome Developers lo stato corrente delle API disponibili e i nomi definitivi degli oggetti globali.
2. Decidere se la feature deve essere nascosta dietro flag, per esempio `?ai=1`, nella prima iterazione.
3. Definire se includere anche tab Analytics in una fase successiva.
4. Stabilire se documentare la feature nel `README.md` o in una guida specifica della GUI installer.
5. Verificare se la GUI installer viene usata principalmente su Chrome/Edge o anche su browser non Chromium.

## Roadmap proposta

### Milestone 1 — AI summary del changelog

Obiettivo:

- pannello assistente nel modal changelog;
- fallback deterministico;
- feature detection;
- adapter AI locale.

Deliverable:

- modifica `index.html`;
- modifica `app.css`;
- modifica `app.js`;
- test manuale base.

### Milestone 2 — Assistente piano installazione

Obiettivo:

- sintesi non solo del changelog ma anche delle selezioni attive;
- riepilogo runtime coinvolti;
- warning su dipendenze mancanti.

Deliverable:

- funzione `buildInstallerAiContext()` estese;
- sezione AI anche nella sidebar o nella tab Installazione.

### Milestone 3 — Troubleshooting assistito dei log

Obiettivo:

- riassumere errori installazione dopo `[ERROR]`;
- spiegare possibili cause;
- nessuna azione automatica.

Vincolo:

- non passare log completi;
- estrarre solo ultime righe significative e redigere path/sensibili.

## Criteri di accettazione MVP

La feature è accettabile se:

- la GUI si apre correttamente anche senza Chrome Built-in AI;
- il pulsante produce un riepilogo fallback quando AI non disponibile;
- su browser compatibile produce una sintesi AI;
- nessuna selezione cambia dopo la sintesi;
- nessun endpoint `POST` viene chiamato dalla sintesi;
- nessun output AI viene inserito con `innerHTML`;
- il flusso installativo resta invariato;
- il codice è isolato e leggibile;
- la documentazione segnala che la feature è opzionale.

## Prossimi passi per sviluppo

1. Ricontrollare la documentazione ufficiale Chrome Built-in AI e aggiornare l'adapter JS ai nomi API correnti.
2. Implementare la Milestone 1 in branch dedicato.
3. Testare prima fallback non compatibile, poi Chrome compatibile.
4. Aprire PR con screenshot del modal changelog in entrambi gli stati: fallback e AI disponibile.
5. Valutare dopo review se estendere alla tab Installazione.

## Decisione consigliata

Procedere con un MVP limitato al modal `Changelog Modifiche Granulari`.

Motivazione:

- sfrutta dati già disponibili;
- non richiede modifiche server;
- è utile per l'utente;
- non introduce dipendenze runtime obbligatorie;
- non altera il comportamento installativo;
- consente validazione rapida della compatibilità Chrome Built-in AI.

## Evidenze a Runtime e Deviazioni Implementative

Durante lo sviluppo effettivo della funzionalità e la sua successiva validazione sul campo, sono emersi dettagli cruciali sul comportamento delle API Chrome Built-in AI a livello di runtime. Di seguito vengono documentate le soluzioni tecniche adottate per mitigare questi comportamenti e le deviazioni rispetto alla proposta implementativa iniziale.

### 1. Gestione della Lingua e Prevenzione dei Blocchi di Chrome (Summarizer API)
- **Comportamento a runtime:** L'inizializzazione del `Summarizer` di Chrome (sia standard moderno che legacy) specificando una lingua non supportata (es. `'it'`), oppure delegando la risoluzione automatica in assenza di modelli locali multilingua configurati, solleva un errore di *Abort* nativo (es. `NotSupportedError`). Questo errore blocca permanentemente il thread del modello locale di Chrome, lasciando tutte le successive Promise (inclusi i tentativi di fallback) nello stato `pending` all'infinito.
- **Soluzione adottata:** È stato impostato esplicitamente l'inglese (`'en'` sia per `expectedInputLanguages` che per `outputLanguage`) per le API di summarization. Se la creazione con opzioni inglesi fallisce, viene eseguito un ripiego su opzioni di creazione vuote. La Prompt API (`LanguageModel`/Gemini Nano) non presenta questa limitazione e continua a rispondere direttamente in lingua italiana.

### 2. Erogazione dello Stream: Streaming Incrementale vs Cumulativo
- **Comportamento a runtime:** A seconda della build di Chrome o della versione della funzionalità sperimentale abilitata, lo stream restituito da `summarizeStreaming` o `promptStreaming` può essere cumulativo (ogni chunk contiene l'intero testo generato fino a quel momento) o incrementale/frammentato (ogni chunk contiene solo la nuova parola o il nuovo carattere).
- **Soluzione adottata:** È stata introdotta una funzione di accumulo intelligente `handleChunk(chunk)` all'interno del flusso di streaming:
  ```js
  let accumulatedText = "";
  function handleChunk(chunk) {
    if (accumulatedText && chunk.startsWith(accumulatedText)) {
      // Stream cumulativo
      accumulatedText = chunk;
    } else {
      // Stream incrementale
      accumulatedText += chunk;
    }
    onChunk({ source: 'ai', text: accumulatedText });
  }
  ```
  Questo previene sfarfallii visivi ed evita che la casella di output visualizzi un solo carattere per volta o spezzi i capoversi.

### 3. Rendering HTML Sicuro del Markdown e Feedback Visivo
- **Sanitizzazione e XSS:** L'output generato dall'AI locale viene formattato come Markdown. Per prevenire attacchi di iniezione di codice (XSS), la funzione `renderMarkdownSafely(text)` esegue innanzitutto una sanitizzazione completa dei tag HTML (`&`, `<`, `>`, `"`, `'`). Successivamente traduce i grassetti (`**testo**` -> `<strong>testo</strong>`) e converte le liste in tag `<ul>` e `<li>` con una classe CSS dedicata (`ai-md-list`).
- **Feedback visivo (.is-loading):** Tra l'attivazione del pulsante e la generazione del primo chunk passa un lasso di tempo significativo per l'inizializzazione del modello locale. Durante questa fase di caricamento, l'interfaccia mostra il messaggio *"Inizializzazione del modello AI locale in corso..."* animato con una pulsazione di opacità (`pulseLoading`) per guidare l'utente.
- **Autoscroll:** Durante la generazione in streaming, viene eseguito l'autoscroll automatico (`scrollTop = scrollHeight`) per garantire che l'ultimo testo generato sia sempre visibile all'utente.

### 4. Ottimizzazione della UI in Caso di Changelog Vuoto
- **Comportamento iniziale:** Quando non venivano riscontrate differenze con il commit installato, il pannello AI rimaneva visibile, rischiando di confondere l'utente o di forzare il modello locale a generare un riepilogo su dati inesistenti.
- **Soluzione adottata:** In assenza di modifiche nel changelog (`diff` vuoto), il pannello assistente locale `#ai-assist-panel` viene nascosto dinamicamente a runtime impostando `display = 'none'`, disattivando la visualizzazione del pulsante AI e prevenendo stati incoerenti.

## Estensioni Implementative: Punti di Integrazione AI (Senza Fallback)

In linea con la policy di abilitare le funzionalità AI on-device esclusivamente come miglioramento progressivo e solo in presenza di un supporto reale e attivo del browser (senza inquinare l'interfaccia con avvisi di fallback o pulsanti disabilitati in caso di assenza), vengono identificati e descritti due punti di estensione strategici all'interno della GUI dell'installer.

### 1. Risoluzione e Spiegazione Errori nel Terminale (`#modal-logs`)
- **Utilità:** Durante l'installazione del runtime o di una dipendenza di sistema, eventuali errori sollevati nel flusso SSE (es. righe contenenti `[ERROR]`, problemi di permessi di rete o di versioni di Node/Git) possono essere criptici per l'utente. L'AI locale può analizzare il log ed estrarre una spiegazione chiara e azioni correttive consigliate.
- **Logica di visibilità (Senza Fallback):**
  * Il pannello e il pulsante *"🤖 Analizza Errore con AI"* rimangono **completamente nascosti** per impostazione predefinita.
  * Vengono visualizzati **soltanto se** si verificano contemporaneamente due condizioni:
    1. `builtInAiStatus.available === true` (l'API locale di Chrome è attiva).
    2. Lo stato dell'installazione termina con un errore (rilevamento di una riga `[ERROR]` o fallimento dell'endpoint `/api/install`).
  * In caso di installazione completata con successo o in assenza di API AI nel browser, l'utente non vedrà alcuna opzione o messaggio relativo all'AI nel modal del terminale.
- **Dati inviati al modello:**
  * Ultime 10-15 righe del log del terminale (filtrate da dati sensibili o path assoluti personali dell'utente).
  * Tipo di operazione eseguita (Installazione pacchetti o dipendenza specifica).
- **Prompt suggerito:**
  ```text
  Sei un esperto di sistemi e assistente di installazione locale.
  Analizza le ultime righe di questo log di errore di installazione e spiega in italiano semplice:
  1. Qual è la causa probabile del fallimento (es. permessi mancanti, file bloccato, dipendenza assente).
  2. Quali passaggi precisi l'utente può eseguire per risolvere manualmente il problema.
  Mantieni la risposta breve, amichevole e focalizzata sulla risoluzione.
  
  [Log terminale]:
  ...
  ```

### 2. AI-Powered Insights nel Dashboard Analytics (`#tab-analytics`)
- **Utilità:** La scheda *Analytics* raccoglie metriche d'uso locali delle sessioni (numero di messaggi, eventi di runtime, strumenti chiamati e modelli più utilizzati). Un riepilogo AI può correlare questi dati per generare consigli sull'efficienza d'uso (es. identificare modelli con un volume sproporzionato di chiamate, consigliare la distribuzione ottimale dei carichi di lavoro tra modelli pesanti e leggeri, evidenziare i tool MCP invocati più frequentemente).
- **Logica di visibilità (Senza Fallback):**
  * All'interno della scheda Analytics, viene predisposta un'area denominata `#analytics-ai-insights`.
  * Questo contenitore e il relativo pulsante *"🤖 Genera Insights AI"* sono **completamente nascosti** (tramite `display: none` o `hidden`) se `builtInAiStatus.available === false`.
  * Non viene mostrato alcun messaggio di errore o di avviso di indisponibilità: la sezione semplicemente non esiste nell'interfaccia dell'utente se il browser non supporta le API.
- **Dati inviati al modello:**
  * Totale sessioni, messaggi inviati ed eventi di runtime registrati.
  * Elenco dei modelli utilizzati con relativi conteggi d'uso (volumi di messaggi e stima di attività).
  * Elenco dei tool/strumenti MCP più invocati.
  * Filtri temporali e di sorgente correntemente attivi.
- **Prompt suggerito:**
  ```text
  Analizza le seguenti statistiche di utilizzo dei modelli e degli strumenti MCP raccolte dall'applicazione:
  [Dati Analytics]:
  ...
  Genera in italiano un report sintetico di 3 punti chiave focalizzato su:
  - Distribuzione dell'uso dei modelli (identificando se i modelli più pesanti/costosi sono usati in modo sproporzionato per task semplici).
  - Trend di consumo e frequenza di invocazione dei tool MCP (quali strumenti sono critici e più utilizzati).
  - Suggerimenti su come ottimizzare le chiamate e migliorare l'efficienza dei workflow d'uso.
  Fornisci indicazioni sintetiche e prettamente analitiche.
  ```

---
**Nota di Chiusura:** Il documento è stato promosso dalla cartella `TODO/` a `docs/analisi-tecniche/` in quanto la milestone implementativa è stata completata, testata e validata con successo.

