Aggiornato il 7 maggio con pivot architetturale: da git-only locale a git server centralizzato.
I brain sono cartelle di markdown. Contengono la memoria di un agente AI: chi è, chi aiuta, cosa sa, cosa ha fatto, cosa deve fare. Sono la cosa più importante del sistema ABChat — più del codice, più dell'interfaccia, più del modello AI. Se perdi un brain, perdi un'identità.
Fino a ieri i brain venivano versionati su GitHub. Funzionava, ma con un problema fondamentale: i brain contengono dati personali. Diari, codici fiscali, conversazioni private, decisioni aziendali. Roba che non deve stare su un servizio di terze parti in chiaro, per quanto privato sia il repository.
La domanda quindi è: come versionare e proteggere i brain senza dipendere da servizi esterni?
La risposta si divide in due problemi che sembrano lo stesso ma non lo sono.
Il primo è il point-in-time: poter tornare indietro nel tempo. "Cosa c'era nel diary di Alyce il 15 marzo?" "Chi ha modificato quel file wiki e quando?" Questo è un problema di tracciamento — serve tenere una storia delle modifiche.
Il secondo è il disaster recovery: se il server muore, i brain non si perdono. Questo è un problema di copie offsite — devi mandare qualcosa da qualche parte, e quel qualcosa deve essere cifrato perché contiene dati sensibili.
La prima versione del design separava i due problemi in modo netto: git locale per il point-in-time, Restic cifrato per il disaster recovery. Due strumenti diversi, due catene diverse. Funzionava, ma rileggendo il design è emersa una domanda ovvia: perché non usare un git server nostro e chiudere il cerchio?
L'idea è semplice. Un'istanza Forgejo — fork community di Gitea, leggero, un container Docker — su git.giobi.com, accessibile solo via Tailscale. Ogni brain pusha lì. Forgejo è un'applicazione come tutte le altre sul server: Restor lo backuppa cifrato su R2 come fa con qualsiasi app web.
Questo cambia la catena da:
brain .git/ → (niente remote) → Restor backuppa N cartelle brain individualmente
a:
brain .git/ → push → git.giobi.com → Restor backuppa 1 app
Un backup del git server contiene tutti i brain con tutta la storia. Non serve logica speciale per scoprire quali cartelle sono brain e backupparle. Non serve che Restor sappia cosa sia un brain. Il git server è un'app, Restor backuppa le app. Grey box perfetto.
In più, gratis: una web UI per navigare la storia dei brain. Diff, blame, browse — senza dover fare SSH sul server e usare la CLI. E la possibilità di clonare un brain su un laptop via Tailscale, per consultazione offline o migrazione.
Il git locale nel working tree del brain resta. Il .git/ è lì, i commit locali funzionano anche se il git server è giù. Ma non è più l'unico storico — è una copia di lavoro. La storia canonica vive sul server.
Un cron di ABChat — gestito dal framework Laravel, non da crontab manuali — passa ogni ora su tutti i brain del village e fa un commit cieco seguito da un push: git add -A && git commit && git push. Se non c'è niente da committare, skip. Se il push fallisce (server giù, rete assente), il commit locale resta e il push riprende al prossimo ciclo. Soft fail su tutto — non si blocca mai niente.
Il messaggio di commit è generico. Non serve che sia descrittivo — quando ti serve capire cosa è successo, fai git diff tra due commit e leggi i cambiamenti. L'analisi si fa a posteriori, non a priori.
La retention è infinita. Su puro testo, anche con un commit ogni ora per anni, lo spazio è irrilevante.
Il brain sta diventando puro testo. I binari — foto, allegati, documenti — vengono delegati a driver esterni: S3, Google Drive, Dropbox. Lo storage locale è roba operativa, non conoscenza. L'inbox è un punto di scambio transitorio. I database SQLite sono cache — un'analisi di quelli esistenti ha confermato che non contengono conoscenza, solo stato operativo o dati migrati altrove.
Quello che resta nel git è la conoscenza: boot/ con l'identità dell'agente, wiki/ con la memoria strutturata, diary/ con la memoria episodica, todo/ con i task, public/ con i contenuti pubblicabili. E le skill — .claude/skills/ e .claude/commands/ — che sono il DNA operativo del brain.
Le skill non sono dipendenze installabili da ignorare come node_modules/. Sono parte integrante del cervello — ogni brain ha la sua copia, non symlink da shared. Un brain senza le sue skill è un blob di markdown che non sa fare niente.
Tutto il resto va nel .gitignore: segreti, storage, inbox, database, sessioni e cache di Claude Code, file di sistema.
Un errore commesso durante il primo tentativo di build è stato creare script bash sparsi nel filesystem — uno per l'init, uno per il cron, uno per il loop. Il feedback è stato netto: questa è infrastruttura ABChat, non roba del brain.
Il bootstrap git — init, gitignore, remote, primo commit, primo push — va nel flusso di creazione brain di ABChat, come azione Laravel. Il cron va nello scheduler Laravel. Il template gitignore va nei template ABChat. La creazione della repo su Forgejo va via API Forgejo, chiamata da ABChat.
La regola è: se è un processo che riguarda tutti i brain di un village, è infrastruttura del village. Il brain non deve sapere come viene versionato — lo fa la piattaforma che lo ospita.
Il brain di Anacleto resta su GitHub. Usa le GitHub Issues come driver per i todo, ha una storia git lunga con commit semantici, e non è un brain domain standard. Aggiunge git.giobi.com come mirror e Restic come layer offsite, ma non toglie GitHub. È l'unico brain che vive su due remote.
Il pivot ha risolto il rischio più serio del design originale. Nel modello precedente, il .git/ locale era l'unico storico — se si corrompeva, perdevi tutto il point-in-time. Con il git server, la storia è replicata. Se il .git/ locale si corrompe, clone fresh dal server. Un git fsck nel cron come health check rileva la corruzione prima che diventi un problema.
Il git server stesso è un single point of failure, ma è mitigato da Restor: se Forgejo muore, restore da R2. Nel frattempo i commit locali continuano — non si perde niente, si accumula e si pusha quando il server torna.
La race condition resta: l'agente può scrivere durante il commit cron, producendo uno stato inconsistente. È accettabile — il commit successivo completa.
Cinque cose restano da decidere. Forgejo sullo stesso server (Efesto) o su un VPS dedicato — Efesto ha risorse, ma è single point of failure. Il metodo di autenticazione per il push — SSH key per workspace user o token HTTP. La frequenza del cron. La migrazione dei circa venti workspace esistenti. La retention Restic per il backup del git server.
Il design si riassume in una frase: git server nostro per ricordare, Restic cifrato per sopravvivere. Il brain è puro testo, i binari stanno fuori, la privacy viene prima della comodità. Il modello AI è sostituibile, il brain no.