# Analisi tecnica: visualizzazione interattiva del grafo docs-node

**Repository:** `sophiadeveloper/mcp-servers`  
**Area:** `docs-node` / `docs_mindmap`  
**Tipo documento:** analisi tecnica / milestone implementata  
**Stato:** `IMPLEMENTED`  
**Data:** 2026-08-05

---

## 1. Decisione di prodotto

La visualizzazione non deve separare artificialmente la mappa mentale dal
concept graph. Sono due layer dello stesso grafo:

- **layer documentale:** nodi `document` e `document_links` diretti;
- **layer concettuale:** nodi `concept` e link diretti `document -> concept`;
- **metadata codebase:** restano nel pannello di dettaglio e nelle note
  derivate, non diventano nodi di grafo in questa milestone.

La vista principale deve quindi essere un canvas unico, con filtri/layer
attivabili. Le viste separate sono filtri dello stesso modello, non due export
o due prodotti distinti. Questo conserva la traccia documento -> concetto ->
documento che gia' usa `map_path` e impedisce di attribuire ai concept un
grado di autorevolezza maggiore degli edge che li hanno generati.

Un grafo completamente espanso non e' un default utile per shelf grandi:
concetti generici e molti link `mentions` riducono leggibilita' e prestazioni.
Il default deve essere un sottografo bounded (path o neighborhood). Una futura
overview puo' esistere solo come vista collassata/clusterizzata e deve
dichiarare esplicitamente troncamento e criteri di aggregazione.

## 2. Stato gia' disponibile

Non e' necessario introdurre un nuovo formato per visualizzare subito un
percorso o un vicinato in chat. `docs_mindmap.map_path` e
`docs_mindmap.map_neighborhood` supportano gia' `output_format: "mermaid"` o
`"both"`; il JSON resta il contratto strutturato di riferimento. Il traversal
e' bidirezionale su `document_links` e `concept_links`, ma l'output conserva
direzione, relazione, provenance, certainty e confidence originali.

Limiti correnti da rispettare anche nella futura UI:

- `max_depth`: default 4, massimo 8;
- `max_nodes`: default 50, massimo 200;
- edge `ambiguous` esclusi per default e inclusi solo con opt-in;
- ranking deterministico: distanza, certainty, confidence, poi chiavi stabili.

Mermaid e' quindi la risposta immediata per un frammento leggibile in chat;
non sostituisce un browser quando servono ispezione, filtro e navigazione.

## 3. Proposta: Milestone 18 — export HTML interattivo locale

**Stato decisionale:** `IMPLEMENTED`. M18 e' indipendente da M15
(adapter AST) e M16 (adapter simboli multi-linguaggio): non aggiunge parser,
migrazioni, entita' grafo, change-log o sincronizzazione.

### Obiettivo

`docs_mindmap` include l'azione locale
`export_mindmap_html`, che genera un singolo file HTML navigabile e derivato
per uno shelf locale scrivibile. SQLite resta sempre la fonte canonica.

L'export deve produrre un artefatto che l'agente possa salvare in una directory
locale scelta dall'utente e consegnare come link apribile nel browser. Il tool
non deve avviare il browser, inviare rete, creare repliche, aggiornare cursor o
scrivere nello storage docs-node.

### Contratto MCP proposto

L'azione riusa `docs_mindmap`; non introduce un tool separato:

```json
{
  "action": "export_mindmap_html",
  "shelf": "nome-o-uuid",
  "save_path": "C:/percorso-assoluto/grafo.html",
  "view": "path | neighborhood | overview",
  "source": { "type": "document | concept", "uuid": "..." },
  "target": { "type": "document | concept", "uuid": "..." },
  "center": { "type": "document | concept", "uuid": "..." },
  "max_depth": 4,
  "max_nodes": 50,
  "include_ambiguous": false,
  "include_evidence": false,
  "force": false
}
```

Regole runtime:

- `path` richiede `source` e `target`;
- `neighborhood` richiede `center`;
- `overview` non espande il grafo integrale: applica il limite nodi e restituisce
  cluster/contatori per il contenuto non materializzato;
- tutti gli array nello schema MCP dichiarano `items`; limiti e enum sono
  coerenti con `map_path`/`map_neighborhood`;
- `save_path` e' assoluto, normalizzato e senza traversal; repliche read-only e
  remote-server rifiutano l'operazione;
- risposta: percorso finale, checksum dell'artefatto, nodi/edge esportati,
  troncamento, warning e `generated_by: "docs-node"`.

L'azione e' `local_only` ma non richiede inizializzazione: il registry
`feature_status` la classifica come on-demand, analogamente a pathfinding e
all'export Obsidian, con coverage dello schema e della smoke obbligatoria.

## 4. Architettura di rendering

1. Riutilizzare l'adattatore read-only gia' usato da pathfinding e neighborhood
   per materializzare nodi ed edge uniformi. Non ricostruire query SQL o logica
   di certainty nel renderer.
2. Selezionare prima il sottografo JSON; Mermaid e HTML derivano dalla stessa
   selezione, così un link visualizzato conserva esattamente l'identita'
   restituita agli agenti.
3. Incorporare dati, CSS e JavaScript nel singolo file. Nessuna CDN, fetch
   esterna, dipendenza runtime o analytics.
4. Usare SVG nativo per una prima versione: zoom/pan, adattamento viewport,
   layout deterministico, hit testing e testo accessibile sono piu' semplici da
   verificare di un canvas opaco. Un canvas/WebGL richiede una decisione
   separata se l'overview clusterizzata ne dimostra il bisogno.
5. Mostrare un pannello di ispezione per nodo/edge con tipo, UUID, shelf,
   relazione, direzione, certainty, confidence e provenance disponibile.

Controlli minimi della pagina:

- ricerca per titolo/label/UUID;
- filtri per layer, tipo di nodo, relazione e certainty;
- legenda certainty e indicatore esplicito di edge ambiguous inclusi;
- selezione diretta di nodo/edge con inspector aggiornato; i cluster espongono
  un'azione separata per il drill-down, così la selezione non cambia vista;
- indicatore di `truncated`, profondita' e limiti applicati;
- label SVG multilinea con tooltip completo, griglia senza sovrapposizioni e
  pan limitato allo sfondo;
- per i documenti locali da scan source, inspector con nome/percorso
  selezionabile e copiabile, piu' link `file:` apribile; nessun body e nessun
  contenuto code e' incluso;
- Mermaid aggiunge `click … href` per tali documenti e restituisce anche
  `document_targets` additivo (`uuid`, `title`, `shelf`, `file_path`, `href`),
  perché alcuni renderer chat sanitizzano i link Mermaid. Snapshot remoti non
  ricevono URI `file:` né path locali.

La vista globale zoomabile e la navigazione per progressive disclosure sono
fuori dal perimetro M18 implementato: requisiti, limiti e validazione sono
definiti nella proposta separata **Milestone 19** alla fine di questo documento.

## 5. Sicurezza, privacy e scritture

- L'HTML contiene solo il sottografo richiesto e metadata gia' esposti dalla
  lettura MCP. Evidence e metadata raw sono esclusi per default; il relativo
  opt-in deve applicare escaping e redazione coerente con gli output esistenti.
- Non includere mai contenuto di file, snippet, body dei simboli o credenziali.
  I riferimenti codebase, se presenti nell'inspector, contengono solo path
  relativo, hash e metadata gia' ammessi dall'export Obsidian.
- Serializzare JSON in modo sicuro per un tag `script` (incluso escape di
  `</script>` e caratteri di controllo); inserire etichette via DOM/text node,
  non via `innerHTML`.
- La rigenerazione replica le garanzie dell'export wiki: destinazione vuota per
  default, `force:true` solo su file marcato `generated_by: docs-node`, staging
  nella stessa directory e publish atomico soltanto dopo successo completo.
- Nessuna modifica a DB, versioni, hash, change-log, cursor, replica o
  conflitti. Il file esportato e' una vista rigenerabile e non viene
  reimportato implicitamente.

## 6. Scenario remoto

M18 non aggiunge alcuna action a `docs_remote`: lo snapshot remoto
resta consultabile con `map_remote_path` e `map_remote_neighborhood`, che
possono gia' generare Mermaid nel payload. Questo evita che una richiesta di
consultazione remota comporti una scrittura locale di file senza una decisione
esplicita.

Un'estensione successiva, da approvare separatamente, potrebbe aggiungere
`docs_remote.export_remote_mindmap_html`. Dovrebbe scaricare e validare lo
snapshot V3 nella singola richiesta, generare **solo** il file locale scelto e
non creare replica, non muovere cursor, non pubblicare e non risolvere
conflitti. La risposta deve riportare `remote`, `base_url`, identita'/tempo
dello snapshot e `concept_sync_mode: "snapshot_only"`; non puo' dichiarare
copertura cross-shelf oltre gli edge presenti nel manifest.

## 7. Piano test proposto

Nuova smoke, con un unico owner in `test:docs`:

```text
tests/smoke/docs-node-mindmap-html-export.smoke.mjs
```

Copertura minima:

- schema MCP stretto, default e rifiuti per riferimenti/view incoerenti;
- path documento -> concetto -> documento e neighborhood con traversal inverso;
- esclusione default di ambiguous, inclusione esplicita e legenda certainty;
- HTML standalone con marker, dati escaped, SVG, controlli e dati di
  provenance solo con opt-in;
- massimo depth/nodes, troncamento esplicito e ordine deterministico;
- path relativo/traversal e destinazione non vuota rifiutati;
- `force:true` solo su artefatto marcato; errore di generazione non sostituisce
  il precedente file valido;
- per la futura vista globale zoomabile: tooltip mouse/focus anche al minimo
  zoom, click che fissa l'inspector, hit-area dei nodi piccoli, recenter della
  ricerca e test delle soglie di performance;
- assenza di contenuto/sorgente codice e assenza di scritture su DB, versioni,
  hash, change-log, cursor e replica;
- rifiuto su shelf replica/read-only e remote-server; assenza dell'azione dal
  tool list remote-server.

La smoke non deve aprire un browser. Se e quando saranno introdotti controlli
interattivi complessi, aggiungere un test browser dedicato per zoom, ricerca e
filtro, mantenendo la smoke deterministica e cross-platform. Il gate conclusivo
resta:

```bash
npm run test:affected -- --strict --include test:docs
```

## 8. Documentazione e discoverability alla realizzazione

M18 aggiorna nello stesso change:

- `docs-node/README.md`, distinguendo Mermaid gia' disponibile dall'export
  HTML locale e dal futuro remoto non implementato;
- `docs/server-capability-matrix.md`, solo per la capability effettivamente
  pubblicata;
- `skills/mcp-docs-navigator/SKILL.md` e una reference dedicata
  `references/graph-visualization.md`, con workflow: scegliere path o
  neighborhood -> verificare i limiti -> esportare -> consegnare il link;
- registry `feature_status`, test di classificazione action e smoke `test:docs`.

M15 resta fuori scope fino a una nuova decisione e non e' una dipendenza della
visualizzazione.

## 9. Criteri di decisione

Procedere soltanto se il prototipo dimostra che il sottografo HTML migliora
esplorazione e review rispetto a Mermaid/JSON senza introdurre dipendenze,
scritture nascoste o grafi integrali illeggibili. La prima release deve
preferire path e neighborhood; l'overview completa richiede evidenza di layout
comprensibile e prestazioni accettabili sullo shelf reale.

## 10. Milestone 19 proposta — vista globale zoomabile e progressive disclosure

**Stato decisionale:** `PROPOSED / NOT APPROVED`. M19 estende soltanto
l'artefatto HTML locale di M18: non introduce migrazioni, tool MCP, change-log,
sync, azioni `docs_remote` o scritture sul database. Il grafo completo resta
quello gia' incorporato nel file derivato e SQLite resta la fonte canonica.

### 10.1 Obiettivo e modello di navigazione

Offrire una modalita' esplicita **Vista completa** per orientarsi nel grafo
globale senza rendere tutte le label contemporaneamente. Il percorso primario
diventa:

```text
overview clusterizzata -> Vista completa -> hover/focus tooltip -> click inspector
-> zoom/pan o ricerca/recenter -> dettaglio locale -> espandi/comprimi cluster
```

La vista clusterizzata di M18 resta il default conservativo. La vista completa
non significa card e testo completo per ogni nodo: a basso zoom visualizza nodi
ed edge a basso dettaglio, mantenendo la possibilita' di interrogare ogni nodo.

### 10.2 Tooltip e accessibilita' al minimo zoom

Anche al minimo zoom, il passaggio del mouse su un nodo piccolo deve mostrare
un tooltip con almeno `title`/`label`, tipo (`document` o `concept`) e UUID
breve. Il focus da tastiera offre lo stesso contenuto, senza dipendere dal solo
hover; il click o Enter/Space fissa il dettaglio completo nell'inspector.

I nodi piccoli devono avere una hit-area minima indipendente dal diametro
visivo. Tooltip e inspector non possono mostrare body documentali, snippet o
contenuto codice; per documenti locali possono riusare soltanto i metadati e le
azioni gia' consentite da M18 (percorso copiabile e link `file:`).

### 10.3 Espansione e collasso nello stesso canvas

Un controllo **Espandi mappa** abilita l'apertura progressiva dei cluster nella
stessa superficie, senza navigazione a pagine. Ogni cluster espanso deve
disporre di un'azione **Comprimi** equivalente; `Vista completa` ripristina il
livello globale. Ricerca e selezione devono fare recenter/zoom sul nodo
identificato e attenuare il contesto non pertinente, preservando il percorso
verso il nodo selezionato.

L'azione "espandi tutto" puo' riferirsi solo ai cluster materializzati nella
vista corrente e deve rispettare un limite dichiarato di nodi/edge. Non deve
forzare il rendering di tutte le label o promettere leggibilita' integrale su
shelf grandi.

### 10.4 Strategia di rendering e limiti

Per il volume attuale dello shelf reale, la fattibilita' SVG deve essere
misurata nel browser con zoom, pan, tooltip e ricerca. Il renderer applica
progressive disclosure:

| Scala | Rendering richiesto |
| --- | --- |
| minima | nodi/edge a basso dettaglio, cluster o hub prioritari, tooltip e hit-area |
| intermedia | label dei nodi rilevanti, edge selezionati e contesto attenuato |
| dettaglio | card multilinea, inspector completo, provenance/evidence secondo opt-in |

Se le soglie concordate di frame time, memoria o risposta input non sono
rispettate, Canvas/WebGL e virtualizzazione sono una decisione tecnica
successiva: non sono implicati automaticamente da M19.

### 10.5 Test, documentazione e confini

- La smoke deterministica verifica presenza di controlli, stati e nessuna
  scrittura persistente; resta sotto l'unico owner `test:docs`.
- Un test browser separato verifica tooltip hover/focus al minimo zoom,
  hit-area, click/keyboard, espansione/collasso, recenter e layout stretto.
- `docs-node/README.md`, capability matrix e reference
  `mcp-docs-navigator/references/graph-visualization.md` distinguono M18
  implementata da M19 proposta e local-only.
- Nessun supporto remoto, snapshot HTML remoto, push, merge o conflitto e'
  introdotto da M19.
