- Aggiunta descrizione area corrente tra Missioni e Aree
- Mostra nome, descrizione e atmosfera dell'area
- Sezione visibile solo quando si e' in una area
- Dati arricchiti con description/atmosphere/features
- Selettore personaggio sopra la barra input
- Solo PG vivi, nome abbreviato
- Click seleziona/deseleziona
- Nome preposto all azione: 'Druso: esploro...'
- Label azione mostra il nome del PG
- deepseek-v4-flash su opencode/go come modello primario
- big-pickle su opencode/zen come fallback (gratuito)
- Fallback automatico su censura "User Safety" o errore HTTP
- Aggiornati .env, config.py, start.sh, docker-compose.yml
- Lock per-campagna in dm_cycle: serializza le richieste
per la stessa campagna, evitando che due DM cycle
leggano stato stale e si sovrascrivano
- begin_write()/end_write() in db.py per lock scritture
- _conn_lock finalmente usato (era definito ma mai acquisito)
- 72 test, tutti passano
- test_llm_parser.py: 18 test per parse_tool_call, repair, strip
- Fix: repair raddoppiava i due punti nelle chiavi
- Fix: aggiunto passaggio per valori con apici singoli
- Copertura: JSON valido, apici singoli, misti, codeblock,
virgole trailing, = invece di :, testo senza JSON
- 72 test totali, tutti passano
- test_tools.py: 4 test per update_quest (normale, status invalido,
quest non trovata, rinomina)
- test_adventure.py: integrità dati (9 aree, connessioni bidirezionali,
mostri con statblock, quest, items, features)
- Tutti 54 test passano in 0.69s
- Card personaggi morti: grigia, teschio, 0 PF, filtro grayscale
- Bottone Nuovo PG quando ci sono caduti
- replaceFunnelDead() chiama POST /api/campaign/{id}/character
- Stato aggiornato dopo rimpiazzo
- #app usa 100dvh su mobile (viewport dinamico)
- Input piu visibile anche se disabilitato (opacity 0.7)
- Touch target 44px per input e bottone
- flex-shrink:0 su btn-send
- safe-area padding aumentato
- Rimosso height:100dvh da #main (causava layout rotto)
- #main si affida a flex:1 per l'altezza
- hamburger ☰ sempre visibile nell'header su mobile
- Safe-area per notch iOS
- Hamburger button (☰) nell'header per aprire sidebar
- Sidebar come drawer overlay su mobile (<768px)
- Sidebar backdrop con chiusura al tap
- Swipe a sinistra per chiudere sidebar
- Safe-area per iPhone notch
- Font-size 16px su input (previene zoom iOS)
- dvh per altezza viewport mobile
- Auto-focus input solo su desktop
- Aggiunto current_area_id allo stato WS
- Mappa ordinata per ID area (1.1-1.9)
- Area corrente evidenziata con ✧ e bordo dorato
- Aree visitate con pallino pieno, non visitate vuoto
- Connessioni mostrate con nomi (non ID)
- CSS rinnovato per area-item
- Aggiunta istruzione: usa update_quest quando missione completata/fallita
- Esempio update_quest spostato in cima negli esempi
- Quest ID nel contesto per permettere al LLM di referenziarle
- update_quest: aggiorna stato/nome/descrizione missioni
- db: get_quest(), update_quest con nome+desc
- prompt: quest_id nel contesto, esempio nei tool examples
- Switch da deepseek-v4-flash (go) a big-pickle (zen) — gratuito
Fase 2 del remediation plan:
- set_puzzle_state / is_puzzle_solved per enigmi area
- update_inventory su character_items con add/remove/equip/list
- combat() legge HP da combat_state e persiste danno
- dm_cycle inietta campaign_id nei tool che ne hanno bisogno
- helpers db: dedup inventario, remove/equip per nome
Fase 4 del remediation plan:
- test integrazione dm_cycle con LLM mockato (5 test)
- test WebSocket handler con mock (4 test)
- CI minimo .gitea/workflows/test.yml
- Fase 0: env var allineate, SYSTEM_PROMPT deduplicato, .gitignore pulito
- Fase 1: GameContext isolato, ciclo DM unificato, provider thread-safe (contextvars)
- Fase 2: DB schema esteso (current_area_id, combat_state, character_items)
- Fase 3: thread-local connection pool + WAL + busy_timeout
- Fase 4: test suite (32 test, 100% pass)
- heuristic_fallback come parser di riserva (non secondo pilota)