Microprogettazione — allineata al codice. La componente observability e' stata realizzata e testata a livello di modulo (cluster observability 6/6 verde) il, poi estesa il dalla dashboard /admin dell'http_api (htmx + Jinja2 + uPlot, ): /admin/proposals, /admin/executors, /admin/executors/stats, /admin/runs, /admin/safety, /admin/turns, /admin/users. Telemetria fine StepLog: cinque sotto-componenti (intent_ms, prefilter_ms, vaglio_ms, exec_ms, rerank_ms) leggibili da bench_latency_breakdown.py. Il generatore HTML statico originale resta come fallback offline. Riferimento di implementazione: /opt/metnos/runtime/observability.py, /opt/metnos/runtime/http_routes_admin.py.
Stato nella sequenza dei microdesign: under approvalapprovedtestedimplemented.
← Indice documentazione Microprogettazione › observability

Metnos

observability — rendere visibile il sistema senza passare dai log
Microprogettazione
Pubblico: chi vuole capire cosa Metnos sta facendo senza aprire un terminale.

Lettura: 9 minuti.

Indice

  1. Cosa fa: dashboard statica
  2. Le sei sorgenti dati
  3. Generazione: render_dashboard
  4. Sezioni del file prodotto
  5. Privacy e HTML-escape
  6. Distribuzione e ciclo di vita
  7. CLI
  8. Limiti e rinvii a +

1. Cosa fa: dashboard statica

Un sistema che si comporta come Metnos — pianificatore ReAct, synt che genera executor, mnestoma che cresce, vaglio che giudica, pairing che riconosce sender — produce parecchio stato. La dashboard di osservabilita' e' il modo per vedere quello stato senza aprire terminali, senza ispezionare SQLite a mano, senza grep sui log JSONL. Un singolo file HTML, una pagina che riassume tutto cio' che serve a un proprietario per capire dove e' arrivato il sistema.

sorgenti dati mnestoma, turni, vaglio... aggregatore sola lettura dashboard HTML statica, no JS
Figura 1 — La dashboard di osservabilità: aggrega in sola lettura le sorgenti dati e genera HTML statico su richiesta, senza server vivo.

La scelta architetturale e' deliberatamente non-live: niente server, niente WebSocket, niente JavaScript. Il file e' generato on demand da uno script Python che legge le stesse sorgenti dati autoritative del runtime, le trascrive in HTML, e si ferma. Aprire con browser locale.

2. Le sei sorgenti dati

SorgenteCosa forniscePath
Mnestoma Stats globali (totale mnest, active, proto, decaying, eventi), top-N attivi per peso, top-N proto-mnest in attesa di sintesi, ultimi 20 event cronologici. ${METNOS_INSTALL_ROOT}/workspace/.mnestoma/mnest.sqlite (override MNESTOMA_DB_PATH)
Pairings Pairing attivi (channel, sender_id, livello, paired_at, paired_by, last_seen) e numero di pairing revocati nello storico. ~/.local/state/metnos/pairings.db
Turns Ultimi 15 turni eseguiti dal pianificatore (timestamp, query utente, esito, numero step, prima riga della risposta). ~/.local/share/metnos/turns/YYYY-MM-DD.jsonl
Vaglio Ultime 20 decisioni del Vaglio (executor, score, blocked_by, motivazione abbreviata, ts). ~/.local/share/metnos/vaglio/YYYY-MM.jsonl
Scheduler Task builtin del runtime (apply_ager, synt_suggest, …), schedule, ultima esecuzione, esito. ~/.local/share/metnos/scheduler/state.sqlite
Test framework Numero moduli, numero test case, distribuzione last_status, top moduli per case count. /opt/metnos/runtime/testing/tests.db

Niente di queste sorgenti e' stato creato per la dashboard: tutte preesistevano come fonte di verita' di un componente del runtime. La dashboard e' un consumatore in piu', non scrive nulla.

3. Generazione: render_dashboard

La funzione esposta e' observability.render_dashboard(out_path). Per ciascuna sorgente c'e' un piccolo helper privato (_collect_mnestoma, _collect_pairings, _collect_recent_turns, …) che apre la sorgente in sola lettura, raccoglie un dict serializzabile, e lo restituisce. Se una sorgente e' assente o solleva (es. SQLite non esiste perche' non hai mai avviato lo scheduler), l'helper ritorna un dict vuoto o un dizionario con la chiave error: la dashboard renderizza una nota informativa ma non si interrompe.

La render e' un singolo passo: nessun template engine, nessuna dipendenza esterna. Solo helper Python che concatenano stringhe HTML. Stesso CSS in linea dei doc canonici (per coerenza visiva con metnos.com), tabelle e card statiche, niente JavaScript.

4. Sezioni del file prodotto

Il file HTML prodotto contiene, in ordine:

  1. Test framework: card metriche (moduli, cases, status) + top moduli per cardinalita'. Risponde alla domanda «la rete dei test e' verde?».
  2. Mnestoma: card metriche (totale, active, proto, decaying, eventi) + tabella top mnest attivi (con barra di peso visiva) + tabella proto-mnest in attesa di sintesi + tabella eventi recenti. Risponde alla domanda «cosa Metnos pensa di sapere fare?».
  3. Pairings: tabella pairing attivi con livello, channel, sender_id, paired_at, last_seen. Risponde alla domanda «chi puo' parlare a Metnos in questo momento?».
  4. Turni recenti: ultimi 15 turni con esito (answer / error / cap_steps / cap_same_executor) e prima riga della risposta. Risponde alla domanda «cosa Metnos ha fatto di recente?».
  5. Decisioni del Vaglio: ultime 20 decisioni con score e motivazione. Pillola verde per approve, rossa per block:guard o block:judge. Risponde alla domanda «la guardia sta tenendo? Sto bloccando troppo o troppo poco?».
  6. Scheduler: tabella task builtin con schedule, ultima esecuzione, esito. Risponde alla domanda «la manutenzione notturna sta girando?».

5. Privacy e HTML-escape

Tutto cio' che esce da una sorgente passa per html.escape prima di essere inserito nel DOM. Il caso garantito dal test render_html_escape_sicuro: anche se un sender_id contiene <script>, il file prodotto mostra &lt;script&gt; — mai un tag attivo. Una dashboard di osservabilita' non e' superficie di attacco, ma e' disciplina mantenerla tale.

Cosa NON appare nella dashboard. I valori sensibili che le sorgenti gia' filtrano restano filtrati: il vaglio logga solo args_keys (non i valori), il pairing non logga il payload del codice ma solo il suo code_id, gli allegati delle mail non vengono mai materializzati nel turn log. La dashboard eredita queste scelte: se non e' nella sorgente, non e' nel file prodotto.

6. Distribuzione e ciclo di vita

Il file di default e' workspace/dashboard/index.html, che vive sotto il METNOS_INSTALL_ROOT e non e' deployato su metnos.com (e' uno strumento operativo locale). Per consultarlo: file:///opt/metnos/workspace/dashboard/index.html nel browser, oppure scp dal server alla macchina di Roberto se si vuole guardarlo da remoto.

Il file e' di solo-output. Si rigenera ogni volta che si lancia python3 -m observability render: 100 ms tipici. La prossima evoluzione (vedi cap. 8) sara' un task dello scheduler builtin che lo rigenera ogni N minuti.

7. CLI

python3 -m observability render # default: workspace/dashboard/index.html
python3 -m observability render --out path.html # path custom

Niente sotto-comandi diversi da render in. Il generatore non offre dump o export JSON: chi vuole i dati grezzi va direttamente alle sorgenti (SQLite + JSONL).

8. Limiti e rinvii a +