Documentazione: GUI Avalonia implementata e progetto rinominato agent-wiki-ui

MVP.md descrive ora la GUI Avalonia al posto di WinForms/WebView2 e il
protocollo pagina-C# sparisce. ADR-0001 passa ad Accettata con l'esito delle
verifiche (renderer markdown proprio, perché Markdown.Avalonia è per Avalonia
11). Il nome ha un'unica sorgente in docs/README.md, con la checklist di
rinomina e la migrazione della cartella dati. README e CLAUDE.md seguono la
nuova struttura Core/Gui e i due publish single-file.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-15 11:18:46 +02:00
1 parent c4c1ad4520
commit 9c6a679e6a
9 files changed
+80 -564

No files matched your search

+20 -14
View File
@@ -4,37 +4,43 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Progetto
LlmRun: eseguibile C# (.NET 10, Windows) che invoca Claude Code (`claude -p`) da terminale. Senza argomenti apre una GUI WinForms, con argomenti funziona da CLI. Non è un repo git.
agent-wiki-ui (già `LlmRun`; il nome ha un'unica sorgente, vedi [docs/README.md](docs/README.md#nome-del-progetto)): eseguibile C# (.NET 10, Windows e Linux) che invoca Claude Code (`claude -p`) da terminale. Senza argomenti apre una GUI di chat Avalonia, con argomenti funziona da CLI.
## Workflow doc-first (obbligatorio)
- Specifica e criteri di accettazione: [docs/MVP.md](docs/MVP.md). Fasi e stato: [docs/ROADMAP.md](docs/ROADMAP.md). Indice dei doc e regole (SSOT, ADR): [docs/README.md](docs/README.md); una decisione architetturale si scrive solo nel suo ADR, gli altri doc la richiamano con un link. Uso: [README.md](README.md).
- Ad ogni richiesta di modifica: aggiornare prima i doc interessati (MVP.md, ROADMAP.md con le spunte, README.md se cambia l'uso; un nuovo ADR in `docs/adr/` per ogni scelta architetturale), poi il codice, poi questo file se cambiano comandi, design o vincoli. Nessuna modifica deve lasciare i doc disallineati.
> In corso: migrazione a GUI Avalonia multipiattaforma ([ADR-0001](docs/adr/0001-gui-multipiattaforma-avalonia.md), ROADMAP Fase 5). Finché non è conclusa, le sezioni sotto descrivono lo stato attuale (WinForms + WebView2).
## Comandi
- Build: `dotnet build` (LlmRun.csproj, net10.0-windows, WinForms)
- Build: `dotnet build` (agent-wiki-ui.csproj, `net10.0`, Avalonia)
- GUI: `dotnet run`; CLI: `dotnet run -- "prompt"`
- Publish single-file: `dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true`
- Test: non esistono ancora.
- Publish single-file (uno per sistema): `dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true` e `-r linux-x64`
- Test: non esistono ancora. Per verificare la GUI senza schermo si può usare `Avalonia.Headless` con `CaptureRenderedFrame()` in un progetto di prova fuori dal repo.
## Architettura
- [Program.cs](Program.cs): top-level statements. Senza argomenti avvia `Gui`; con argomenti è la CLI (`claude -p <prompt>` con `ArgumentList`, stdout/stderr ereditati, exit code propagato, 127 se `claude` non è nel PATH).
- [Gui.cs](Gui.cs): host WinForms sottile. Un solo WebView2 che carica [ui.html](ui.html) (embedded resource; `{{MODELS}}` è sostituito con le opzioni dei modelli). Pagina e C# dialogano con `WebMessage` JSON (protocollo in `docs/MVP.md`). Per ogni `send` C# lancia `claude -p` con stdout/stderr rediretti, converte la risposta da markdown a HTML con Markdig (`DisableHtml`) e la rimanda alla pagina. Contesto: `--session-id <guid>` al primo messaggio, `--resume <guid>` poi. Cronologia: un JSON per chat in `%LOCALAPPDATA%\LlmRun\chats\<guid>.json` (il nome file è l'id di sessione, validato come Guid prima dell'uso), salvato appena l'utente invia e di nuovo alla risposta; all'avvio (primo `list` dalla pagina) viene riaperta la chat più recente. `--model`/`--effort` omessi se "Predefinito". Lista modelli hardcoded in `Gui.Models`, da aggiornare quando escono nuovi modelli.
- [ui.html](ui.html): tutta la UI (HTML+CSS+JS, nessuna libreria). Token di colore/tipografia come variabili CSS in cima; specifiche in `docs/MVP.md` → "Design (UI/UX)". Cambiando l'aspetto aggiornare quella sezione.
- Dipendenze NuGet (solo GUI): Markdig, Microsoft.Web.WebView2.
Decisioni e motivazioni negli ADR ([docs/adr/](docs/adr/)); qui solo la mappa del codice.
- [Program.cs](Program.cs): top-level statements. Con argomenti è la CLI (`Claude.RunInherited`); senza avvia Avalonia (`App`).
- [Core/Claude.cs](Core/Claude.cs): **unico punto di avvio di `claude`** (cartella dell'exe, stdin chiuso, `ArgumentList`, `--session-id`/`--resume`, `--model`/`--effort` omessi se vuoti). Contiene anche l'elenco modelli `Catalog.Models`, da aggiornare quando escono nuovi modelli.
- [Core/ChatStore.cs](Core/ChatStore.cs): cronologia, un JSON per chat in `<LocalApplicationData>/<nome-app>/chats/<guid>.json` (nome file = id di sessione, validato come Guid prima dell'uso).
- [Core/AppInfo.cs](Core/AppInfo.cs): nome dell'app, letto dall'`AssemblyName` del csproj (unica sorgente).
- [Gui/MainViewModel.cs](Gui/MainViewModel.cs): stato e logica della chat (invio, apertura/eliminazione, salvataggio subito all'invio e di nuovo alla risposta, riapertura dell'ultima chat all'avvio).
- [Gui/MainWindow.axaml](Gui/MainWindow.axaml) (+ `.cs`): layout XAML con binding compilati. [Gui/App.axaml](Gui/App.axaml): token di colore come risorse di tema chiaro/scuro e stili; specifiche in `docs/MVP.md` → "Design (UI/UX)". Cambiando l'aspetto aggiornare quella sezione.
- [Gui/MarkdownView.cs](Gui/MarkdownView.cs): renderer markdown proprio (albero Markdig → controlli Avalonia, `DisableHtml`).
- Dipendenze NuGet: Avalonia (+ Desktop, Themes.Fluent), Markdig.
## Vincoli non ovvi
- La working directory di `claude` deve essere la cartella dell'exe: usare `AppContext.BaseDirectory`, mai `Environment.CurrentDirectory` né `Assembly.Location` (vuoto in single-file).
- Lo stdin di `claude` va redirezionato e chiuso subito, altrimenti aspetta 3s.
- `claude` è un .exe nativo (`~/.local/bin`), avviabile direttamente. Se fosse `claude.cmd` serve `cmd.exe /c`.
- La logica di avvio processo è duplicata tra CLI (`Program.cs`) e GUI (`Gui.cs`): se cambia (cartella di lavoro, stdin, flag), modificarla in entrambi i punti.
- Nella GUI i link `http(s)` non devono navigare nella finestra: si aprono nel browser di sistema (`NavigationStarting`/`NewWindowRequested`).
- La GUI deve girare su un thread STA (creato a mano in `Program.cs`, perché i top-level statements non hanno `[STAThread]`): senza, WebView2 fallisce con `RPC_E_CHANGED_MODE`.
- `claude` è un eseguibile nativo (`~/.local/bin`), avviabile direttamente. Se fosse `claude.cmd` (Windows) serve `cmd.exe /c`.
- Il nome dell'app non va scritto a mano nel codice: usare `AppInfo.Name`. Cambiare nome cambia la cartella dati (vedi checklist in docs/README.md; `ChatStore` migra le cartelle dei nomi precedenti).
- Avalonia 12: la clipboard si usa con `using Avalonia.Input.Platform;` (`SetTextAsync` è un'estensione); `TextBox.Watermark` è obsoleto, usare `PlaceholderText`.
- Nel renderer markdown i colori si risolvono al momento del rendering (`TryFindResource` con `ActualThemeVariant`) e la vista si ricostruisce al cambio di tema.
- I link nel markdown si aprono con hit-test sul testo (`TextLayout.HitTestPoint`) solo se `http(s)` e se non c'è una selezione in corso.
- Il publish single-file richiede `IncludeNativeLibrariesForSelfExtract` (nel csproj): Skia e HarfBuzz sono librerie native.
## Skill del repo