Microprogettazione — testata, allineata al codice. Storage e operazioni implementati in runtime/mnestoma.py, esercitati da 20 test module + 6 cluster + integrazione end-to-end con agent_runtime. Schema del cap. 4 e soglie del cap. 6 verbatim, ager di base implementato come funzione invocabile. L'ager notturno (apply_executor_ager, introvertiva_propose, introvertiva_apply) e' gated dal segnale di interazione utente: un Metnos in vacanza non deprezza executor per inattività calendariale. L'introvertiva ha filtri qualità deterministici: vocab validator sui proposed_name, skip di flow args (entries, from_step, results) e di valori template {{stepN.field}}, soglia min_uses a 10. Volume proposte a 6 con qualità attesa alta.
Stato nella sequenza: under approvalapprovedtestedimplemented. Delta POC rispetto al doc: (a) events.mnest_id con ON DELETE CASCADE per supportare il purge dei proto-mnest senza orfani; (b) DB path default workspace/.mnestoma/mnest.sqlite, override via env MNESTOMA_DB_PATH per test isolati; (c) le query interne (top_k, by_tag, walk) vanno dirette sulla tabella mnests filtrando per stato; la vista v_mnestoma resta come da microdesign per consultazione esterna. Snapshot mensile e archiviazione decaying ancora non automatizzati (richiedono lo scheduler builtin).
← Indice documentazione Microprogettazione › mnestoma

Metnos

mnestoma — il grafo emergente di tutti i mnest
Microprogettazione —
Allineata con Architettura (cap. 9, Figura 6) e Dialogo sugli executor.
Nuovo concetto introdotto dalla (non sostituisce nulla di esistente).

Pubblico: chi implementerà lo schema dati, l'ager, gli snapshot.
Lettura: 16 minuti.

Indice

  1. Scopo e confini
  2. Cos'è il mnestoma
  3. Cosa il mnestoma NON è
  4. Il brodo del mnestoma — una metafora utile
  5. Schema dati
  6. Operazioni: insert, query, update
  7. L'ager: come opera il decadimento
  8. Pruning, snapshot, archiviazione
  9. Variante linguistica: mnestoma vs mnestome
  10. Bootstrap: il primo mnestoma
  11. Osservabilità e debug
  12. Domande aperte

1. Scopo e confini

Questo documento definisce il mnestoma: la struttura dati che raccoglie l'insieme di tutti i mnest attivi e ne governa il ciclo di vita. Tecnicamente è un grafo orientato pesato persistito in SQLite; ontologicamente è la memoria relazionale di Metnos — ciò che ricorda di aver fatto insieme.

Confini

Il documento copre:

Non copre, e demanda altrove:

2. Cos'è il mnestoma

Il mnestoma è un grafo orientato pesato in cui:

Il mnestoma emerge. Nessuno lo disegna a priori: nasce vuoto al primo avvio e si forma turno dopo turno, mentre il gateway osserva quali executor passano output a quali altri. Le forme che prende riflettono come il sistema viene usato: un mnestoma di un utente «archivio fatture» ha cluster diversi da quello di un utente «rassegna stampa quotidiana», anche se il seed degli executor è lo stesso.

Perché un grafo, non una lista. La forma «grafo» cattura una proprietà che la lista non catturerebbe: la vicinanza operativa. Due executor che compaiono spesso uno dopo l'altro nello stesso turno sono più vicini di due che non si incontrano mai. Il grafo lo rende esplicito; la lista lo nasconde. Quasi tutte le decisioni di ager e synt sono già formulate in termini di grafo (test verdi al 27/4); il Vaglio rule-based non legge ancora il mnestoma (giudizio locale per ora), il giudice LLM lo userà come contesto.

3. Cosa il mnestoma NON è

La parola «memoria» in un agente AI ha troppi significati. Vale la pena dire chiaramente cosa il mnestoma non è:

Cosa il mnestoma NON èDov'è quel concetto, allora
La memoria conversazionale dell'LLM (turni recenti, contesto in token).Nel working memory dell'execution trace.
La memoria episodica delle conversazioni passate (cosa Roberto disse ieri).Nella episodic memory, indicizzata per sender.
La memoria semantica dei fatti su Roberto e il suo mondo («il cane si chiama Fido»).Nella semantic memory, estratta via reflection e approvata dall'utente.
L'audit log delle azioni svolte.In workspace/.audit/, append-only, JSONL.
Il workspace dei file dell'utente (note, fatture, foto).In workspace/, gestito separatamente.
La definizione delle capacità (i singoli executor).In workspace/executors/, file per file.

Il mnestoma è la relazione osservata fra executor: chi ha lavorato con chi, quanto spesso, quanto recentemente. Niente di più.

3-bis. Il brodo del mnestoma — una metafora utile

Per capire cosa fa davvero un mnestoma, conviene smettere per un istante di pensarlo come una tabella SQLite e cominciare a pensarlo come un ambiente vivo: un brodo in cui piccole particelle fluttuano, si incontrano, si attraggono, si combinano. Da quella dinamica emergono strutture più complesse, secondo un processo di aggregazione progressiva che, di tanto in tanto, ricorda ciò che si osserva in altri sistemi naturali fatti di tanti elementi che interagiscono fra loro.

Quel che segue è una metafora, non un'identità. La uso con moderazione: serve a far vedere tre cose che il mnestoma fa davvero — aggregare ciò che si somiglia, riconoscere ciò che manca, far nascere nuove strutture quando il riconoscimento incontra il materiale giusto — senza dover rivendicare un parallelo letterale che non c'è.

Le particelle del brodo

All'inizio, il brodo è vuoto. Poi cominciano a comparire le particelle: piccole tracce di vita che il sistema raccoglie mentre l'utente lo usa. Sono di poche specie diverse, ognuna con la sua forma e il suo ruolo:

mnest (passaggio fra executor) executor fast-path proto-mnest Le particelle fluttuano (animazione: passa il cursore sull'illustrazione).
Fig. 1 — Il brodo del mnestoma a riposo. Quattro specie di particelle: i mnest (passaggi osservati), gli executor (nodi del grafo), i fast-path (scorciatoie introspettive) e i proto-mnest (desideri non ancora soddisfatti).

Ogni particella ha una storia: un mnest è il ricordo che «A è servito a B», un executor è un piccolo programma che sa fare una cosa precisa, un fast-path è una scorciatoia che il sistema ha appreso (la richiesta canonica «X si risolve così»), un proto-mnest è un mnest a metà: src reale, dst desiderato ma non ancora esistente. Si vede subito nel disegno che il proto-mnest ha una forma diversa, una specie di recettore aperto: c'è uno slot vuoto che aspetta di essere riempito.

Dalla ripetizione al fastpath

Nel brodo, niente è davvero a caso. Le particelle si attraggono fra loro in base alla somiglianza semantica, misurata con il modello multilingua BGE-M3. Quando l'utente fa ripetutamente la stessa cosa — tre richieste «scarica questa pagina» che diventano sempre get_urls seguito da describe_entries — i mnest osservati nei tre turn riferiscono alla stessa coppia di executor. Quei mnest formano un cluster cross-turn: un'evidenza che «questa pipeline funziona».

A questo punto succede qualcosa di interessante: il cluster non resta una nuvola sfocata, cristallizza. Diventa un fastpath, un percorso preformato che descrive la sequenza in modo compatto e immediatamente eseguibile. Da quel momento il PLANNER non ha più bisogno di chiamare il modello linguistico per ripensare la pipeline da capo: legge il fastpath e lo usa direttamente. La figura sotto mostra le quattro fasi — osservazione, cluster, cristallizzazione, riuso — in sequenza.

scarica X get_urls describe_entries output scarica Y get_urls describe_entries output scarica Z get_urls describe_entries output turn 1 turn 2 turn 3 cluster di mnest FASTPATH: get_urls → describe_entries il cluster diventa un fastpath nuovo input PLANNER LLM (non chiamato) output tre turn ripetuti producono mnest osservati i mnest convergono in un cluster cross-turn il cluster cristallizza in un percorso preformato il PLANNER usa il fastpath direttamente, senza chiamare l’LLM fase 1 fase 2 fase 3 fase 4
Fig. 2 — La nascita di un fastpath. Tre turn ripetuti producono mnest che convergono in un cluster, il cluster cristallizza in un percorso preformato, e il PLANNER lo usa direttamente saltando il modello linguistico.

Il fastpath che ne emerge non è un'astrazione: è proprio quella sequenza concreta, memorizzata, pronta all'uso. Il risparmio è tangibile — la chiamata al pianificatore LLM (circa dodici secondi) viene saltata interamente, e l'utente riceve la risposta in meno di un secondo. Il cluster che l'ha generato resta nel mnestoma come traccia di come si è arrivati al fastpath; il fastpath stesso vive nel suo registro separato (vedi fast_path.html).

I recettori: il proto-mnest e il desiderio

A volte, mentre il sistema lavora, accade qualcosa di più particolare: il pianificatore vorrebbe chiamare un executor che non esiste. Magari l'utente ha chiesto qualcosa di nuovo, e nella catena ideale il passo finale dovrebbe essere un compose_report che non è mai stato scritto. Quello che si registra, in quel momento, è un proto-mnest: una traccia con il src conosciuto e il dst appena un nome, non ancora un programma.

Possiamo vederlo come un recettore: una forma con una lacuna vuota in cui il dst dovrebbe entrare. La lacuna non è un dettaglio grafico, è la firma desiderata — dichiara cosa servirebbe per chiudere la forma. Il recettore aspetta: rimane stabile finché nessuno lo riempie, e diventa più visibile man mano che si presenta nello stesso modo, turno dopo turno.

read_url (esiste) src executor mnest osservato (turno utente) lacuna proto-mnest dst desiderato: «compose_report» non esiste ancora Il proto-mnest aspetta. La lacuna tratteggiata e' il dst mancante.
Fig. 3 — Il proto-mnest come recettore. A sinistra l'executor src esiste; a destra il proto-mnest mostra in chiaro la lacuna aperta che attende un dst.

Le funzioni introspettive: chi riconosce i recettori

Da qualche parte, nel brodo, lavorano le funzioni introspettive: i mestieri silenziosi di synt in modo introvertivo e del modulo introvertiva. Non hanno una funzione finale propria, servono a far accadere altre cose. La loro caratteristica è saper riconoscere i recettori: leggere la lacuna aperta e capire quale dst la chiuderebbe.

Quando una funzione introspettiva incontra un proto-mnest che si è visto più volte (la soglia è tre osservazioni ricorrenti, ), si avvicina, lo analizza, ne legge la signature desiderata, e poi propone: emette un candidato di sintesi. La proposta dice: «questo recettore esiste, ricorre, ed ecco un possibile dst che lo chiuderebbe».

Sintesi di un executor: dalla lacuna aperta al recettore chiuso synt al lavoro... Recettore (proto-mnest) attende una capacita' compose_report synt synt si avvicina synt al lavoro nel recettore executor creato, synt esce proto-mnest chiuso, capacita' nuova nel pool 0s 3.5s 7s 10.5s 14s
Fig. 4 — La danza della sintesi. Synt entra nella lacuna del recettore, lavora alla creazione di un nuovo executor, lo lascia al suo posto e se ne va. Il proto-mnest diventa un mnest attivo: la capacita' nuova entra nel pool degli executor.

Aggregazione: fast-path che si compongono

C'è un altro fenomeno interessante che accade nel brodo: due fast-path che vivono adiacenti, e si presentano spesso nello stesso turno, finiscono per agganciarsi a formare un fast-path più lungo.

Pensiamo a un turno tipo: «scaricami questa pagina» attiva un fast-path L1 single-tool; subito dopo, «dimmi cosa dice» attiva un altro fast-path L1. Il sistema osserva la successione, registra la sequenza, e quando si ripete tre volte la promuove a fast-path L2 multi-step. Da quel momento la coppia «scarica + descrivi» è una sola sequenza riconosciuta.

L1 «scarica» L1 «descrivi» L2 = scarica + descrivi describe_url executor sintetizzato soglia: 50 ripetizioni 3 ripetizioni promozione L2→L3
Fig. 5 — Aggregazione dei fast-path. Due fast-path L1 si combinano in un L2 dopo tre passaggi; dopo cinquanta, la sequenza è abbastanza stabile per essere unificata in un executor unico.

La sequenza non si ferma a due. Tre fast-path adiacenti possono formare un trimero, e così via. Il sistema conserva tutta la catena, valuta quanto spesso si ripete e, oltre una soglia (50 utilizzi per default), un job notturno chiamato multi_tool_promote presenta la pipeline a synt come proto-mnest: «ecco una sequenza che vale la pena unificare in un solo executor».

Dalla pipeline alla sintesi: due vie verso lo stesso esito

A questo punto conviene fermarsi e osservare che synt riceve proto-mnest da due strade diverse, indipendenti fra loro, che convergono nello stesso punto.

La via diretta: le funzioni introspettive osservano il mnestoma e individuano i recettori che ricorrono — quei proto-mnest che si presentano nello stesso modo turno dopo turno, soglia tre osservazioni ricorrenti. Quando ne trovano uno sufficientemente stabile, propongono direttamente un executor che chiuderebbe la lacuna. Non serve passare da un fast-path: l'analisi del singolo recettore basta. È il caso classico, e storicamente il primo che synt ha imparato a gestire.

La via indiretta: una pipeline di fast-path L2 che ha accumulato abbastanza utilizzi (cinquanta, per default) viene promossa dal job notturno multi_tool_promote a proto-mnest. Questa volta il proto-mnest non nasce da una richiesta fallita ma da una sequenza che ha funzionato tante volte: la signature desiderata descrive un executor unificato che incorpora tutta la catena di chiamate.

Le due strade conducono allo stesso ingresso. Synt riceve il proto-mnest, legge la signature, e la traduce in una struttura completa: esegue le sue cinque fasi (naming, signature, tests, description, code), produce un nuovo executor, lo firma con ed25519, lo iscrive al catalog. Il recettore non è più aperto: il dst esiste, il proto-mnest viene promosso a mnest attivo. La nuova capacità è unica, riusabile, e — che venga dall'analisi diretta di un recettore o dall'aggregazione di una pipeline — entra nel pool degli executor come tutti gli altri.

L'executor ha sempre la priorità sul fast-path (regola bidirezionale). La regola vale in entrambe le direzioni del tempo. Da sintesi a fast-path: una volta che la sintesi ha prodotto l'executor describe_urls, la pipeline aggregata [get_urls, describe_entries] che l'aveva originata viene immediatamente demoted: la sua forma si dissolve nel brodo, e ogni nuova richiesta passa direttamente attraverso l'executor monolitico. Da fast-path candidato a non-creazione: simmetricamente, se mentre il sistema sta per registrare un nuovo fast-path scopre che l'executor che farebbe la stessa cosa esiste già nel catalog, il fast-path non viene creato: non c'è nulla da memoizzare se la capacità unificata è già disponibile. Il runtime applica la regola al volo nel matcher (auto-demote) e nel recording (skip silenzioso); il PLANNER la conosce dal suo prompt e non emette mai la sequenza doppia se l'executor unificato è nel pool. La forma ha la priorità sulla scorciatoia, in ingresso e in uscita.

Tutto insieme: un sistema in equilibrio

Quel che emerge, guardandolo da lontano, è un sistema in equilibrio dinamico: chiuso ma vivo, dove ogni componente partecipa a un ciclo. Le particelle nascono dall'osservazione del turno, si attraggono per somiglianza, formano cluster, alcuni cluster diventano fast-path, alcuni fast-path si aggregano in pipeline, le pipeline mature diventano proto-mnest che chiedono sintesi, la sintesi produce nuovi executor, i nuovi executor generano altri mnest e tutto ricomincia.

Allo stesso tempo c'è un ciclo dell'oblio: l'ager notturno (vedi capitolo 6) fa decadere le particelle inutilizzate, riduce il loro peso, le sposta in stato decaying, alla fine le archivia. Le cose che non si usano più spariscono. Il brodo si pulisce da solo.

Tutto questo accade dentro un singolo file SQLite di pochi MB. La metafora del brodo non è un trucco didattico: descrive abbastanza fedelmente cosa fa il codice. Capire questo livello rende ovvi i capitoli che seguono — lo schema dati, le operazioni, l'ager — che si leggono come la spiegazione tecnica di un processo che hai già visto in moto.

4. Schema dati

Il mnestoma vive in workspace/.mnestoma/mnest.sqlite, un singolo file SQLite. La scelta di SQLite è deliberata: zero servizi da avviare, zero dipendenze esterne, backup banale (copia del file), affidabilità provata.

Tabella executors

Replica leggera del manifest, in lettura-veloce per le query del gateway. Il manifest canonico resta sempre workspace/executors/<nome>/manifest.toml; questa tabella è un indice.

CREATE TABLE executors (
 name TEXT NOT NULL,
 version TEXT NOT NULL,
 state TEXT NOT NULL, -- seed | active | quarantine | archived
 loaded_at TEXT NOT NULL, -- ISO 8601
 manifest_hash TEXT NOT NULL, -- blake3
 PRIMARY KEY (name, version)
);
CREATE INDEX idx_executors_state ON executors(state);

Tabella mnests

CREATE TABLE mnests (
 id TEXT PRIMARY KEY, -- ULID
 src_executor TEXT NOT NULL,
 src_version TEXT NOT NULL,
 dst_executor TEXT NOT NULL, -- nome canonico O nome desiderato (proto)
 dst_version TEXT, -- NULL per proto
 weight REAL NOT NULL CHECK (weight BETWEEN 0 AND 1),
 uses INTEGER NOT NULL CHECK (uses >= 1),
 ts_first TEXT NOT NULL,
 ts_last TEXT NOT NULL,
 decay_lambda REAL NOT NULL DEFAULT 0.018,
 state TEXT NOT NULL, -- proto | active | decaying | superseded
 tags TEXT, -- JSON array
 desired_sig TEXT, -- JSON, solo per proto
 CHECK (ts_last >= ts_first),
 UNIQUE (src_executor, src_version, dst_executor, dst_version, state)
);
CREATE INDEX idx_mnests_dst ON mnests(dst_executor);
CREATE INDEX idx_mnests_src ON mnests(src_executor);
CREATE INDEX idx_mnests_weight ON mnests(weight DESC);
CREATE INDEX idx_mnests_state ON mnests(state);

Tabella events

Append-only, registra ogni rinforzo o decadimento applicato. Permette di ricostruire la traiettoria del peso di un mnest e di ricalcolare posteriormente in caso di cambio della formula.

CREATE TABLE events (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 mnest_id TEXT NOT NULL,
 ts TEXT NOT NULL,
 kind TEXT NOT NULL, -- reinforce | decay | state_change
 delta REAL, -- variazione del peso (NULL per state_change)
 new_state TEXT, -- solo per state_change
 reason TEXT, -- es. "ager nightly", "synt approved"
 FOREIGN KEY (mnest_id) REFERENCES mnests(id)
);
CREATE INDEX idx_events_mnest ON events(mnest_id);
CREATE INDEX idx_events_ts ON events(ts);

Tabella canonical_query_log

Tabella di registrazione delle richieste utente in forma lemma, usata dal fast-path introvertivo (L1 single-tool, ). Ogni volta che il pianificatore decide il primo executor di un turno, una riga viene inserita o rinforzata qui: canonical query (forma minuscola condensata), tool scelto, valori osservati degli argomenti. Dopo tre passaggi consolidati, il canonical_matcher usa BGE-M3 cosine per matchare nuove richieste contro questo log e saltare il pianificatore.

CREATE TABLE canonical_query_log (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 canonical_query TEXT NOT NULL,
 tool_name TEXT NOT NULL,
 args_shape TEXT NOT NULL, -- template placeholder (back-compat)
 args_observed TEXT, -- VALORI args reali (Fase 14 v5)
 uses INTEGER NOT NULL DEFAULT 1,
 ok_count INTEGER NOT NULL DEFAULT 0,
 fail_count INTEGER NOT NULL DEFAULT 0,
 ts_first TEXT NOT NULL,
 ts_last TEXT NOT NULL,
 state TEXT NOT NULL DEFAULT 'candidate',
 UNIQUE(canonical_query, tool_name, args_shape)
);

La colonna args_observed (aggiunta via migrazione idempotente) memorizza i valori concreti degli argomenti osservati al primo passaggio del pianificatore. Quando una nuova richiesta matcha la riga, l'estrattore di argomenti (args_extractor) li riusa direttamente, evitando di rifare l'estrazione regex o di chiamare un LLM. La sequenza multi-step analoga vive in un sqlite separato (multi_tool_paths.sqlite); vedi fast_path.html per il dettaglio completo.

Vista v_mnestoma

Il grafo «vivo» per le query di lettura. Esclude superseded e mostra active + proto:

CREATE VIEW v_mnestoma AS
SELECT id, src_executor, src_version, dst_executor, dst_version,
 weight, uses, ts_last, state, tags, desired_sig
FROM mnests
WHERE state IN ('active', 'proto');

5. Operazioni: insert, query, update

Insert / rinforzo: record_passing

La sola operazione di scrittura in fase di turno. Atomica per coppia. Pseudocodice:

def record_passing(src, dst, turn_ctx) -> mnest_id:
 with conn.transaction:
 if dst.exists:
 row = SELECT * FROM mnests
 WHERE src_executor = src.name AND src_version = src.version
 AND dst_executor = dst.name AND dst_version = dst.version
 AND state = 'active'
 if row:
 w = decay(row.weight, now - row.ts_last, row.decay_lambda) + REINFORCE_DELTA
 UPDATE mnests SET weight = clamp01(w), uses = uses + 1, ts_last = now
 INSERT INTO events (mnest_id, ts, kind, delta, reason)
 VALUES (row.id, now, 'reinforce', REINFORCE_DELTA, turn_ctx.id)
 return row.id
 else:
 id = ulid
 INSERT INTO mnests (id, src_*, dst_*, weight, uses, ts_first, ts_last, state, tags)
 VALUES (id,..., BOOTSTRAP_WEIGHT, 1, now, now, 'active', tags)
 INSERT INTO events (mnest_id, ts, kind, delta, reason)
 VALUES (id, now, 'reinforce', BOOTSTRAP_WEIGHT, turn_ctx.id)
 return id
 else:
 # proto-mnest
 id = ulid
 desired = build_desired_signature(turn_ctx)
 INSERT INTO mnests (..., dst_executor=dst.desired_name, dst_version=NULL,..., state='proto', desired_sig=desired)
 return id

Query principali

QueryUso
top_k_outgoing(executor, k)Dato un executor, restituisce i k mnest uscenti più pesanti.
top_k_incoming(executor, k)Dato un executor, restituisce i k mnest entranti più pesanti.
walk(start, max_depth)Visita BFS pesata dal nodo di partenza, fino a una profondità massima. Usato dal gateway per costruire il context d'esecuzione.
recurring_protos(min_uses, since)Lista dei proto-mnest che hanno superato una soglia di ricorrenza. Innesco del synt.
by_tag(tag)Tutti i mnest con un tag dato. Usato dall'osservabilità e dall'ager per cluster.
decayingMnest in stato decaying. Usato dall'ager per la propost à di archiviazione.

Update di stato

Le transizioni di stato sono fatte da componenti specifici (ager, synt, gateway in caso di quarantena di un executor). Tutte sono accompagnate da una riga events con kind = 'state_change' e una reason obbligatoria; questo è il principio di reversibilità (cap. 14 dell'Architettura): non si cambia stato senza traccia del perché.

6. L'ager: come opera il decadimento

L'ager è il processo che applica il decadimento e segnala le transizioni di stato che il puro tempo richiede. Gira una volta al giorno, in finestra notturna (default: 04:00 ora locale), in una transazione lunga ma a basso impatto:

  1. Decadimento: per ogni mnest active, calcola weight_new = weight_old · exp(-λ · Δt) dove Δt è il tempo trascorso dall'ultimo evento. Aggiorna il peso e scrive una riga events di tipo decay.
  2. Decay state: ogni mnest che scende sotto la soglia decay weight passa ad decaying; lo segnala nel canale di proposte al gateway.
  3. Archive proposal: ogni mnest decaying che è sotto archive weight e con ts_last > 90 giorni entra nella lista delle proposte di archiviazione mostrate a Roberto.
  4. Proto purge: ogni proto-mnest che scende sotto min proto weight è eliminato (anti-rumore).
  5. Recurring proto detection: cerca proto-mnest con uses >= SYNTH_TRIGGER_USES e weight >= SYNTH_TRIGGER_WEIGHT; li segnala al synt come candidati per la sintesi.
  6. Snapshot: il primo del mese, copia il file SQLite in workspace/.mnestoma/snapshots/YYYY-MM.sqlite.

L'ager è un esempio puro di componente che fa solo manutenzione: non modifica la struttura dei mnest, non crea executor, non parla con l'utente. Propone; chi decide è il synt + Roberto, oppure la policy di archiviazione che il gateway applica nel turno successivo.

7. Pruning, snapshot, archiviazione

Snapshot mensile

Il primo dell'mese (UTC), l'ager produce uno snapshot del file vivo:

workspace/.mnestoma/snapshots/2026-04.sqlite # snapshot del mese
workspace/.mnestoma/snapshots/2026-03.sqlite.zst # vecchio, compresso
workspace/.mnestoma/snapshots/2026-02.sqlite.zst...

Lo snapshot serve a tre cose: rollback in caso di danneggiamento del file vivo, analisi storica del grafo, traccia per chi vuole capire come Metnos «si è formato» nel tempo. Snapshot oltre 12 mesi vengono compressi in .zst ma mai eliminati: la storia è un dato di prim'ordine.

Pruning del file vivo

Il file vivo si manterrebbe in piedi anche tutto pieno, ma per prestazioni e per pulizia conviene una potatura periodica:

Archiviazione di un executor

Quando un executor passa a archived, i suoi mnest passano a superseded con reason = 'executor archived'; restano leggibili, sono esclusi dalla vista v_mnestoma, e dopo 90 giorni vanno alla tabella di archivio.

8. Variante linguistica: mnestoma vs mnestome

Il termine ha due forme normative:

La doppia forma è intenzionale e va mantenuta. Tradurre mnestoma con mnestome in EN dà al lettore inglese il riflesso giusto (il suffisso biologico evoca un grafo emergente, come il microbiome). Tradurre mnestome con mnestoma in IT segue la regola fonetica italiana che evita suffissi sentiti come incongrui (mnestome in italiano sembrerebbe un imperativo verbale, «tu memorizzati!»).

9. Bootstrap: il primo mnestoma

Al primo avvio, il mnestoma è vuoto. La domanda «da dove si parte, allora?» ha tre risposte concrete:

  1. Si parte dal vuoto. Per la maggior parte delle istanze, il mnestoma è vuoto al primo avvio e si forma in un mese di uso. È lento ma corretto: la specificità dell'utente entra subito nella forma del grafo.
  2. Seed minimo (consigliato). Esiste un seed di 12-15 mnest noti, codificati nel repo, che cablano i passaggi più comuni fra gli executor seed (es. read_files → read_files_pdf, get_urls → render_texts). Hanno state = 'seed' per distinguerli e peso BOOTSTRAP_WEIGHT (vedi mnest.html cap. 6).
  3. Import da snapshot. Per migrazioni o per condivisione (futuro), si può importare uno snapshot pulito. L'import passa per una validazione: gli executor citati devono esistere e essere firmati.

10. Osservabilità e debug

L'utente può ispezionare il mnestoma da CLI (tramite il comando Metnos mnestoma):

Metnos mnestoma list # tutti i mnest attivi
Metnos mnestoma list --tag fattura # filtrati per tag
Metnos mnestoma top 20 # i 20 più pesanti
Metnos mnestoma graph executor read_files # vicinato di un executor
Metnos mnestoma proto # i proto-mnest correnti
Metnos mnestoma history mnest_01HW... # storia eventi di un mnest
Metnos mnestoma snapshot --month 2026-03 # apre lo snapshot mensile

La dashboard web (vedi observability.html, da riscrivere) ha una vista grafica dello stesso contenuto, con filtri e drill-down. La regola di trasparenza: l'utente può sempre sapere cosa Metnos pensa di sapere.

11. Domande aperte

  1. Concorrenza in scrittura. Il gateway è un singolo processo, quindi le scritture sono naturalmente seriali. Quando in futuro arriveranno gli executor remoti (cap. 4 dell'Architettura), il gateway resta unico ma le chiamate possono arrivare da più turni in parallelo. SQLite WAL basta? Aperta.
  2. Schema migration. Il file SQLite vive a lungo. Come gestiamo le migrazioni dello schema fra versioni di Metnos? Migrazioni dichiarative numerate, tipo Alembic? Aperta.
  3. Privacy degli snapshot. Gli snapshot mensili contengono nomi di executor e tag, ma non contenuti. La superficie di privacy è bassa, ma se si voglia condividere uno snapshot per debug servirebbe una funzione di redazione dei tag «personali». Da progettare se serve.
  4. Integrazione con la episodic memory. Il mnestoma e la memoria episodica delle conversazioni sono separati per scelta (cap. 3). Può aver senso un cross-reference esplicito (un mnest che cita il turn_id che lo ha generato)? L'inverso (un turno che cita i mnest che ha rinforzato) è già presente nell'audit. Aperta.

primo della triade
executor
Il nodo del mnestoma.
secondo della triade
mnest
L'arco del mnestoma.
livello 1
Architettura, cap. 9
Il quadro d'insieme.
indice
Microprogettazione
Tutti i doc.

Metnos — mnestoma microprogettazione
Doc canonico nuovo (concetto introdotto dalla ).