~/progetti/donumai/README.md
~/progetti/donumai/README.md

donumAI

{ data: “2026-08-08”, stato: “in sviluppo”, moduli_stack: 14 }

Motore a stage per lo sviluppo software — gli agenti scrivono, ma niente avanza finché non approvi tu

donumAI nasce da un fastidio molto preciso: gli strumenti che promettono di «scrivere i documenti di progetto con l'AI» producono testo plausibile e nessun modo per sapere se è ancora vero. Un documento di architettura generato a marzo resta lì, convincente come il primo giorno, mentre a maggio i requisiti sono cambiati e nessuno se ne accorge. donumAI parte dall'assunto opposto: la parte difficile non è generare, è tenere insieme sei documenti che si contraddicono a vicenda nel momento in cui il progetto si muove. Il prodotto è un motore che accompagna un progetto software attraverso sei stage — discovery, stima, domain design, architettura, piano di implementazione, piano di test — e a ogni passaggio mette una persona davanti a quello che gli agenti hanno scritto.

## I sei stage e il gate

Ogni stage produce un artefatto versionato, fatto di sezioni. Gli agenti lo scrivono, ma non lo chiudono: la revisione avviene sezione per sezione, e per ognuna si può approvare, commentare o chiedere modifiche. Uno stage sblocca il successivo solo quando il suo gate è approvato — non è una formalità, è un lucchetto vero. È la differenza fra un assistente che produce e un processo che avanza.

·Discovery: il brief iniziale, raccolto con un'intervista che procede a fasi
·Stima: i numeri e le assunzioni su cui poggiano
·Domain design: il modello del dominio applicativo
·Architettura: le decisioni lockate, insieme alle alternative scartate
·Piano di implementazione: epiche, sequenziamento, milestone, definition of done
·Piano di test: strategia e distribuzione dei test

## Quando qualcosa a monte cambia

La scommessa dietro donumAI è stretta e meccanica: versionare ogni documento, registrare da quale decisione viene ogni sua parte, e nel momento in cui un input cambia marcare come «stale» tutto quello che a valle ne dipendeva. Il drift non sparisce — smette di essere invisibile, e a conti fatti quella è la parte grossa del problema. I trace link non vengono inferiti da un modello: nascono per proiezione sui dati, perché un link inferito ha un tasso d'errore, e da lì in avanti se lo porta dietro tutta la catena.

## Regole deterministiche prima delle rubriche

Ogni artefatto passa da un layer di validazione prima di arrivare al gate. Il principio è che qualunque proprietà catturabile come campo tipizzato esce dal giudizio di un modello ed entra in una regola strutturale: presenza, cardinalità, tipo, appartenenza a un insieme chiuso. Le regole strutturali costano zero chiamate, non cambiano da un'esecuzione all'altra e non si lasciano convincere da una prosa scritta bene. Solo quello che resta — il giudizio semantico irriducibile — va alla rubrica.

·Per il solo stage di architettura: 154 regole deterministiche, estratte riga per riga dai documenti di metodo
·Tre severità che non si collassano mai in una: block ferma il gate, repair innesca un ciclo di correzione automatica, warn compare al gate senza bloccare
·Enum chiusi copiati verbatim dalle fonti, perché la conoscenza pregressa di un modello è spesso vecchia
·Verdetti obbligatori sulle proprietà che il giudizio lo richiedono davvero, ma su cui si può costringere il giudice a citare le evidenze

## Il markdown non è mai un input

È l'invariante che tiene in piedi tutto il resto, ed è anche la decisione tecnica a cui tengo di più. Il worker non produce testo: produce oggetti tipizzati, attraverso una tool call forzata. Le regole girano sugli oggetti. Il markdown è una proiezione, prodotta da un renderer puro, e nessun componente a valle lo legge mai. Se in questo progetto mi ritrovo a scrivere un parser o una regex su della prosa, vuol dire che sono andato nella direzione sbagliata. Un layer di estrazione è un'inferenza con un tasso d'errore, e tutte le regole a valle erediterebbero quell'errore smettendo di essere deterministiche. C'è perfino un test che verifica l'invariante sull'AST — per tipo di ritorno e non per nome della funzione — e che dimostra di non essere cieco riconoscendo i parser storici rimasti in un modulo più vecchio.

## Le guide di metodo

Dietro ogni stage ci sono dei documenti di metodo, e quei documenti sono leggibili dentro il prodotto stesso: una sezione di studio che spiega perché un artefatto è fatto così, cosa rende una decisione lockabile e con quali criteri verrà giudicata. Sono scritti in italiano mentre il resto dell'interfaccia è in inglese, il che ha reso la tipografia un problema concreto: la prosa lunga in italiano ha una misura di riga e un ritmo diversi da quelli di un'interfaccia densa.

## Design e identità visiva

L'interfaccia è pensata per persone tecniche che ci passano dentro delle ore: tabelle dense, documenti lunghi, decisioni di gate. Densità e leggibilità prima della decorazione. Il sistema si chiama «Slate & Ferrous» ed è quasi monocromatico, con un solo accento blu: il nero-inchiostro segna le azioni primarie, il blu segna lo stato — così una board piena di card resta leggibile senza che il colore faccia due mestieri insieme.

·Palette in OKLCH, tema chiaro e tema scuro entrambi progettati e non uno l'inverso dell'altro
·Tipografia: Bricolage Grotesque per i titoli, Public Sans per l'interfaccia, JetBrains Mono per identificatori, versioni e metriche — se è monospaziato, per definizione è un valore prodotto dalla macchina
·Font self-hosted: nessuna richiesta a terzi sulle pagine pubbliche, che è anche l'unico modo per scrivere una cookie policy senza banner e dire il vero
·Il marchio è un doppio esagono con un nodo pieno su ciascuno dei sei vertici dell'anello interno: uno per stage

## Stack tecnologico

Il progetto è un monorepo TypeScript in cui control plane ed execution plane sono tenuti separati di proposito: l'API riceve le richieste e possiede lo stato, mentre un worker a parte esegue i run, che possono durare minuti.

·Control plane e motore: NestJS con Prisma e PostgreSQL
·Execution plane: un worker separato su BullMQ e Redis
·Web: React 19, Vite, TanStack Router, HeroUI, Tailwind CSS v4
·Contratti condivisi: schemi Zod in un pacchetto a parte, usati sia dall'API che dal client
·Client LLM provider-agnostico, isolato in un suo pacchetto
·Monorepo gestito con pnpm

donumAI è un progetto personale, sviluppato da solo, e procede in un ordine che mi sono imposto: prima il cablaggio tipizzato, poi l'invocazione del giudice e la misura della sua varianza, poi tutto il resto. Le 154 regole scritte finora restano ipotesi finché non girano su artefatti generati davvero, e la tabella che mi interessa ha due colonne: le regole che non scattano mai e quelle che scattano sempre. Hanno diagnosi opposte e vanno lette insieme — una regola che scatta sempre non è un successo del layer di validazione, è il sintomo di qualcosa da correggere più a monte.

// stack
[nestjs”, prisma”, postgres”, redis”, bullmq”, react”, vite”, tanstack-router”, typescript”, tailwind”, zod”, llm”, monorepo”, sdlc”, ]