diff --git a/CLAUDE.md b/CLAUDE.md index f0cc0a6..ebeef81 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -42,6 +42,7 @@ Decisioni e motivazioni negli ADR ([docs/adr/](docs/adr/)); qui solo la mappa de - Codex (`CodexEngine`): l'id di sessione lo genera Codex e si legge da `thread.started` nell'output JSONL (`--json`); la risposta è l'ultimo `agent_message`; `exec resume` non accetta `-s`, la sola lettura si impone con `-c 'sandbox_mode="read-only"'`; serve `--skip-git-repo-check` (la cartella dell'exe non è un repository); `--` prima del prompt. Dettagli e prove in ADR-0002. Il modello predefinito è quello di `~/.codex/config.toml`: se richiede un Codex più recente l'errore compare nella chat (vedi docs/INSTALL.md). - Il controllo delle versioni contatta solo `downloads.claude.ai` (Claude Code) e `api.github.com` (Codex, serve lo User-Agent), al massimo ogni 5 minuti e in background; un errore di rete non è un errore dell'app (stato "sconosciuto"). - L'aggiornamento di un CLI è sempre un gesto esplicito dell'utente (pulsante Aggiorna): nessun aggiornamento automatico e nessun fallback che esegua npm/brew/winget al posto suo. +- Windows: l'eseguibile è `WinExe` (nessuna console al doppio clic); in modalità CLI `Core/ConsoleHost.cs` riaggancia il terminale padre con `AttachConsole` e collega stdout/stderr a `CONOUT$` solo se non sono già reindirizzati (ADR-0005). Il codice deve poter fallire in silenzio senza terminale. Conseguenza: su Windows l'exit code della CLI arriva solo se il chiamante attende il processo. - 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. diff --git a/README.md b/README.md index 1217d3d..9551056 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ dotnet publish -c Release -r linux-x64 --self-contained -p:PublishSingleFile=tru Senza `-o` il risultato è in `bin/Release/net10.0//publish/`. **Usarli** -- Windows: doppio clic su `agent-wiki-ui.exe` per la GUI, oppure da terminale `agent-wiki-ui.exe "prompt"` per la CLI. Il file non è firmato: Windows può mostrare un avviso di sicurezza al primo avvio. +- Windows: doppio clic su `agent-wiki-ui.exe` per la GUI (non si apre nessuna finestra di console), oppure da terminale `agent-wiki-ui.exe "prompt"` per la CLI. Da `cmd` o PowerShell il prompt torna subito e l'output compare dopo; per aspettare la fine e leggere l'exit code usa `start /wait agent-wiki-ui.exe "prompt"` (cmd) o `Start-Process -Wait -NoNewWindow agent-wiki-ui.exe "prompt"` (PowerShell); `& .\agent-wiki-ui.exe "prompt" | Out-Host` aspetta ma non dà l'exit code. Spiegazione in [ADR-0005](docs/adr/0005-windows-senza-console.md). Il file non è firmato: Windows può mostrare un avviso di sicurezza al primo avvio. - Linux: `chmod +x agent-wiki-ui` (se serve) e poi `./agent-wiki-ui`. La GUI richiede un desktop con X11 o XWayland. - Al primo avvio le librerie native (Skia, HarfBuzz) vengono estratte in una cartella temporanea: il primo avvio è un po' più lento. - I motori (`claude`, `codex`) devono essere installati e nel PATH dello stesso sistema: vedi [docs/INSTALL.md](docs/INSTALL.md). diff --git a/docs/MVP.md b/docs/MVP.md index c778072..f7ef0ca 100644 --- a/docs/MVP.md +++ b/docs/MVP.md @@ -13,7 +13,7 @@ Tutti gli argomenti sono uniti in un unico prompt. Con `--engine ` come prim 1. Se non ci sono argomenti: stampa l'uso ed esce con codice 2. 2. Avvia il motore scelto in modalità non interattiva (`claude -p ` o `codex exec … -- `) con `WorkingDirectory = AppContext.BaseDirectory`. 3. Ritrasmette stdout e stderr del processo figlio in tempo reale. -4. Esce con lo stesso exit code di `claude`. +4. Esce con lo stesso exit code del motore. **Su Windows** l'eseguibile non ha finestra di console ([ADR-0005](adr/0005-windows-senza-console.md)): `cmd` e PowerShell non aspettano la fine del programma, quindi l'exit code è disponibile solo se il chiamante attende il processo (`start /wait`, `Start-Process -Wait`, `| Out-Host`, script). 5. Se l'eseguibile del motore non è trovato: messaggio chiaro ed exit code 127. ## GUI (chat) @@ -60,7 +60,7 @@ Ogni criterio ha test automatici nella matrice di [TESTING.md](TESTING.md) (CL-0 - [ ] Eseguito da un'altra cartella, `claude` parte nella cartella dell'exe (verificabile chiedendo "pwd"). - [ ] L'output appare in streaming, non solo alla fine. -- [ ] L'exit code è propagato. +- [ ] L'exit code è propagato (su Windows, quando il chiamante attende il processo: vedi sopra). - [ ] Un prompt con virgolette e spazi arriva intatto. ## Domande aperte diff --git a/docs/README.md b/docs/README.md index a0c2484..ce6e8a7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -40,3 +40,4 @@ Se il nome cambia di nuovo, aggiornare solo questi punti: | [0002](adr/0002-motori-cli-claude-codex-antigravity.md) | Più motori CLI (Claude Code, Codex, Antigravity) su Windows e Linux | Accettata (Claude Code, Codex) | | [0003](adr/0003-strategia-di-test.md) | Strategia di test e regola "nuova funzione = nuovi test" | Proposta | | [0004](adr/0004-aggiornamento-dei-cli.md) | Aggiornamento dei CLI dalle Impostazioni | Proposta | +| [0005](adr/0005-windows-senza-console.md) | Windows: eseguibile senza finestra di console | Proposta | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 17e5f47..7d71c4f 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -56,6 +56,7 @@ Decisione e motivazioni: [ADR-0001](adr/0001-gui-multipiattaforma-avalonia.md). - [x] Rendering markdown in Avalonia (titoli, liste, tabelle, citazioni, codice), pulsante Copia, link nel browser di sistema - [x] Tema chiaro/scuro che segue il sistema, con i token di MVP.md → "Design (UI/UX)" (da provare su un desktop Linux reale) - [x] Eliminare `ui.html` e il protocollo `WebMessage` +- [x] Windows: eseguibile senza finestra di console, la CLI riaggancia il terminale padre ([ADR-0005](adr/0005-windows-senza-console.md)); da provare su Windows nativo - [ ] Publish single-file self-contained `win-x64` e `linux-x64`: compilano e partono (Linux: CLI e GUI su WSLg; Windows: solo CLI, via WSL); da provare la GUI su Windows nativo e su una distribuzione Linux pulita - [x] Aggiornare README.md e CLAUDE.md (comandi, architettura, vincoli) a migrazione conclusa diff --git a/docs/TESTING.md b/docs/TESTING.md index ad154cf..a0e3eee 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -192,6 +192,15 @@ Si provano con `FakeClaude`/`FakeCodex` che rispondono a `--version` e `update`; | UI-15 | Il nome dell'app compare nel titolo della finestra e nella barra laterale | G | `Nome_app_visibile` | [ ] | ### Eseguibile pubblicato +Righe WIN: console su Windows (ADR-0005). +| ID | Requisito | Liv. | Test | | +|---|---|---|---|---| +| WIN-01 | L'eseguibile `win-x64` pubblicato ha sottosistema "Windows GUI" (intestazione PE); quello `linux-x64` non è interessato | E | `Sottosistema_gui` | [ ] | +| WIN-02 | CLI con output reindirizzato su file o pipe: l'output arriva, handle ereditati non toccati | E | `Cli_con_output_reindirizzato` | [ ] | +| WIN-03 | CLI da un terminale: output visibile (`AttachConsole` + `CONOUT$`); senza terminale padre l'attacco fallisce in silenzio e l'app prosegue | E (manuale su Windows nativo) | `Cli_con_terminale_padre` | [ ] | +| WIN-04 | Exit code corretto quando il chiamante attende il processo (`start /wait`, `Start-Process -Wait`) | E (manuale su Windows nativo) | `ExitCode_con_attesa` | [ ] | +| WIN-05 | Il codice di `ConsoleHost` non fa nulla su Linux/macOS | U | `ConsoleHost_non_windows` | [ ] | + | ID | Requisito | Liv. | Test | | |---|---|---|---|---| | PUB-01 | Il publish single-file `linux-x64` si compila e la CLI risponde con `FakeClaude` | E | `Publish_linux_smoke` | [ ] | diff --git a/docs/adr/0005-windows-senza-console.md b/docs/adr/0005-windows-senza-console.md new file mode 100644 index 0000000..b8fdeca --- /dev/null +++ b/docs/adr/0005-windows-senza-console.md @@ -0,0 +1,45 @@ +# ADR-0005 — Windows: eseguibile senza finestra di console + +- **Stato**: Proposta +- **Data**: 2026-10-15 +- **Collegato a**: [ADR-0001](0001-gui-multipiattaforma-avalonia.md) (GUI e piattaforme) + +## Contesto +Su Windows l'eseguibile è di tipo "console" (`OutputType` `Exe`): con il doppio clic, oltre alla finestra della GUI si apre anche un terminale vuoto che resta aperto finché l'app gira. Il tipo console serve alla CLI (`agent-wiki-ui.exe "prompt"`), perché da terminale `cmd` e PowerShell aspettano la fine del programma, mostrano l'output e danno l'exit code. Un eseguibile "GUI" non ha console, ma allora la CLI perde queste proprietà. Su Linux il problema non esiste: nessuna finestra extra. + +## Criteri di decisione +1. Doppio clic: solo la finestra della GUI. +2. La CLI deve continuare a mostrare l'output nel terminale da cui parte, anche con reindirizzamenti (`> file`, `| altro`). +3. Un solo file da distribuire, come per Linux. +4. Nessun cambiamento per Linux. + +## Opzioni considerate +| Opzione | Esito | Motivo | +|---|---|---| +| Lasciare il tipo console e nascondere la finestra all'avvio (`FreeConsole`) | Scartata | La finestra compare comunque per un istante; con Windows Terminal come terminale predefinito può restare una scheda. | +| Due file: `agent-wiki-ui.exe` (senza console) e `agent-wiki-ui-cli.exe` (con console) | Alternativa valida | Nessuna perdita nella CLI (exit code corretto ovunque), ma due file da distribuire e da spiegare. Da riprendere se l'exit code della CLI diventa importante in Windows. | +| **Un solo `.exe` senza console; la CLI riaggancia il terminale padre** | **Scelta** | Un file, doppio clic pulito, output visibile nel terminale. | + +## Decisione +- Il progetto usa `OutputType` **`WinExe`** (sottosistema Windows). Su Linux non cambia nulla. +- Con **argomenti** (modalità CLI) su Windows, `Core/ConsoleHost.cs` chiama `AttachConsole(ATTACH_PARENT_PROCESS)`: se parte da `cmd`, PowerShell o Windows Terminal l'app usa quel terminale. Se l'output standard non è già valido (non è reindirizzato) lo collega alla console (`CONOUT$`); se è un file o una pipe ereditati li lascia stare, così `> file` e `|` funzionano. Il motore avviato dopo eredita gli stessi handle. +- Senza terminale padre (doppio clic, avvio da un altro programma) l'attacco fallisce in silenzio e l'app prosegue. +- Senza argomenti (GUI) non si tocca la console. + +## Conseguenze +**Positive**: il doppio clic mostra solo la finestra; un unico file; output e reindirizzamenti della CLI funzionano. +**Negative / costi — comportamento della CLI su Windows**: +- `cmd` e PowerShell **non aspettano** la fine di un programma a sottosistema Windows: il prompt torna subito e l'output compare dopo, mescolato al prompt. +- L'**exit code** non arriva a `%ERRORLEVEL%` né a `$LASTEXITCODE` in uso interattivo. Arriva se il chiamante aspetta il processo: `start /wait agent-wiki-ui.exe "prompt"` in `cmd`, `Start-Process -Wait -NoNewWindow` o `& .\agent-wiki-ui.exe "prompt" | Out-Host` in PowerShell, script e programmi che attendono il processo figlio. In pipeline (`| Out-Host`, `| more`) PowerShell attende. +- Su Linux e macOS il comportamento della CLI resta quello di sempre (exit code propagato, streaming). +- Il criterio di accettazione dell'MVP sull'exit code vale quindi, su Windows, solo se il chiamante attende il processo. + +## Da verificare +- [ ] Doppio clic su Windows nativo: nessuna finestra di console. +- [ ] Da `cmd`, PowerShell e Windows Terminal: output visibile, reindirizzamento su file e pipe, exit code con `start /wait` e con `Start-Process -Wait`. +- [ ] Output corretto quando il processo è avviato da un altro programma senza terminale. +- [ ] Il sottosistema dell'eseguibile pubblicato risulta "Windows GUI" (controllato sull'intestazione PE). + +## Riferimenti +- Passi: [ROADMAP.md](../ROADMAP.md), Fase 5. +- Righe di test: [TESTING.md](../TESTING.md), righe WIN.