~/progetti/formicaio/README.md
←~/progetti/formicaio/README.md

Formicaio

{ “data”: “2026-10-24”, “stato”: “live”, “moduli_stack”: 14 }

Un team di agenti specializzati per i tuoi obiettivi di ogni giorno — ricordano il contesto, citano le fonti e misurano i progressi

Formicaio nasce da una domanda che mi facevo ogni mattina: «cosa posso mangiare stamattina?». Per rispondere bene servono il piano di allenamento, il giorno della settimana, quello che c'è in dispensa e l'obiettivo — e con una chat AI generica andava rispiegato tutto da capo, ogni volta: un quarto d'ora per decidere un pasto, per poi ricevere un consiglio che non sapeva niente di me. Formicaio parte dall'assunto opposto: il contesto è un dato strutturato, non un testo da riscrivere. È un assistente personale fatto di agenti specializzati, raccolti in team — atletica, studio, qualunque altro ambito — che rispondono in pochi secondi con il tuo contesto, dicono da quale fonte viene ogni consiglio e tengono il conto di quello che fai davvero.

## Team, agenti e fonti

Un team è un ambito con il suo stato condiviso: obiettivi, metriche, impegni ricorrenti, tipi di osservazione. Dentro ci sono uno o più agenti, ognuno con le sue istruzioni, i suoi principi e i suoi documenti. Prima di ogni risposta, una lettura strutturata della domanda sceglie l'agente che deve rispondere e riconosce quello che va registrato; poi l'agente risponde citando i passaggi da cui prende il consiglio.

·Documenti per agente, divisi in passaggi e trovati con la ricerca full-text di PostgreSQL: ogni citazione rimanda al passaggio esatto
·Osservazioni lette dalla chat: un allenamento saltato, una pesata o un pasto diventano dati, validati dal nucleo, senza compilare moduli
·Impegni ricorrenti, come gli allenamenti della settimana, con le eccezioni dette in chat
·Ogni risposta è una raccomandazione per un giorno preciso: un tocco sotto la risposta dice com'è andata, ed è da lì che si misura l'aderenza

## Un nucleo che non sa niente di atletica

Il requisito più severo era l'agnosticità: un nuovo ambito deve aggiungersi con la sola configurazione, senza toccare il codice. Il nucleo non conosce né la pista né gli esami, e un controllo in CI fallisce se un termine del pilota compare nei suoi moduli. La configurazione di un team è descritta da uno schema JSON versionato e validata con Ajv; ogni salvataggio pubblica una nuova versione immutabile, e ogni turno registra quella che ha usato. Il secondo team, studio, è nato così: un file di configurazione, zero righe di codice. Oggi team, agenti, metriche e tipi di osservazione si creano e si modificano direttamente dall'app, partendo da dei template.

## Il turno, dalla domanda alla risposta

Ogni domanda è un turno con una traccia completa: la versione della configurazione, il contesto inviato al modello, i tentativi, i controlli delle regole, i token e il costo. Il contesto si assembla leggendo il nucleo nello stesso processo, perché dentro un turno il sistema deve leggere le proprie scritture: è il motivo principale per cui l'architettura è un monolite modulare e non un insieme di servizi.

·Monolite modulare a confini rigidi: un'interfaccia pubblica per modulo, uno schema PostgreSQL e un ruolo di database per modulo, dipendenze verificate in CI con dependency-cruiser
·Eventi accodati nella stessa transazione del turno e consegnati una volta sola da graphile-worker, con dead-letter dopo tre tentativi
·Un tetto di spesa giornaliero per utente, riservato sotto advisory lock prima di chiamare il modello
·Il testo di domande e risposte si cancella dopo 90 giorni: restano date, durate, costi e un'impronta

## La tua chiave, il tuo modello

Formicaio non ha una chiave sua. Ogni utente sceglie nelle impostazioni il fornitore — Anthropic, OpenAI o DeepSeek — e incolla la propria chiave, che viene sigillata con AES-256-GCM in uno schema a parte. C'è un modello per fornitore, dietro un adapter comune con il suo ciclo di retry dentro il budget di latenza del turno. Ogni risposta la paga chi la chiede, e prima della scelta l'app dice in chiaro come ciascun fornitore tratta i dati.

## Misurare, non indovinare

Il progetto ha un gate settimanale con due numeri: l'aderenza, cioè la quota di giorni d'impegno in cui il consiglio viene seguito davvero (l'obiettivo è almeno l'80%), e il tempo dalla domanda alla risposta mostrata (p95 sotto i due minuti, contro il quarto d'ora di partenza). La qualità delle risposte si valuta su un set di domande congelato, su una copia usa e getta del database, mai in produzione.

## Design e identità visiva

L'app è una PWA installabile, pensata per il telefono ma comoda anche da desktop, con un'estetica morbida e un solo blu come colore primario. Il marchio è un formicaio in sezione: il cumulo in alto, le camere dentro, le gallerie ritagliate fino all'ingresso, così su qualunque superficie si vede il fondo attraverso. Nel nome, la «AI» di FORMICAIO è nel colore d'accento.

·HeroUI v3 con i token di Formicaio, tema chiaro e tema scuro
·Plus Jakarta Sans servito dall'app stessa: nessuna richiesta a servizi di font esterni
·Accesso senza password, con l'email e un codice di sei cifre, costruito sulle API di Clerk con il markup dell'app
·Risposte in Markdown rese in modo sicuro, con le citazioni numerate; ogni pagina pubblica è verificata con axe-core nei test

## Stack tecnologico

Un monorepo TypeScript gestito con pnpm: il backend, la PWA e un client API generato dal contratto OpenAPI del backend, così front-end e back-end non possono divergere in silenzio.

·Backend: NestJS su Fastify, Kysely per l'accesso ai dati, PostgreSQL 18
·Code e scadenze: graphile-worker sullo stesso PostgreSQL
·Configurazione dei team: JSON Schema validato con Ajv
·Web: React, Vite, React Router, TanStack Query, HeroUI v3, Tailwind CSS v4, i18next
·Modelli: gli SDK di Anthropic e di OpenAI, che serve anche DeepSeek tramite la sua API compatibile
·Test a livelli con Vitest, dai confini tra moduli fino ai processi reali con il fornitore del modello simulato

## In produzione

Gira in container Docker su un server nell'Unione europea. Le immagini le costruisce la CI, taggate con lo SHA del commit, e ogni commit su main va in produzione da solo: dalla CI il server accetta una cosa sola, il deploy di un commit di main, sempre con un backup del database prima delle migrazioni. Il database sta su un volume cifrato con LUKS2, e le copie notturne lasciano il server già cifrate con age, verso Cloudflare R2.

Formicaio è un progetto personale, ideato, progettato e sviluppato da solo, e il suo primo utente sono io. I documenti di progetto — discovery, stima, modello di dominio, architettura, piano di implementazione e piano di test — li ha scritti donumAI e li ho approvati stage per stage. Il criterio con cui lo giudico è scritto nel gate: quattro settimane di uso quotidiano, con l'aderenza almeno all'80%. Il resto sono intenzioni.

// stack
[“nestjs”, “postgres”, “react”, “llm”, “fastify”, “kysely”, “graphile-worker”, “vite”, “heroui”, “tailwind”, “typescript”, “pwa”, “json-schema”, “docker”, ]