TESTED Microdesign v1.1 — new, tested on April 27, 2026. The observability component has been built and tested at module level (cluster observability 6/6 green) on 27/4/2026. Implementation reference: /opt/myclaw/runtime/observability.py.
Status in the microdesign sequence: under approvalapprovedtestedimplemented. The v1.0 of this doc preceded the code; it is replaced by this v1.1 after the implementation of the static HTML generator that closes (together with operational mnestome) phase 4 of the roadmap.
← Documentation index Microdesign › observability

Metnos

observability — making the system visible without going through the logs
Microdesign v1.1 — status TESTED (April 27, 2026)
Audience: those who want to understand what Metnos is doing without opening a terminal.

Reading time: 9 minutes.

Contents

  1. What it does: static dashboard
  2. The six data sources
  3. Generation: render_dashboard
  4. Sections of the produced file
  5. Privacy and HTML-escape
  6. Distribution and lifecycle
  7. CLI
  8. Limits and what is deferred to v1.2+

1. What it does: static dashboard

A system that behaves like Metnos — ReAct planner, synt that generates executors, mnestome that grows, vaglio that judges, pairing that recognises senders — produces a great deal of state. The observability dashboard is the way to see that state without opening terminals, without inspecting SQLite by hand, without grepping the JSONL logs. A single HTML file, one page that summarises everything an owner needs to understand where the system has got to.

The architectural choice is deliberately non-live: no server, no WebSocket, no JavaScript. The file is generated on demand by a Python script that reads the same authoritative data sources of the runtime, transcribes them into HTML, and stops. Open it in a local browser.

2. The six data sources

SourceWhat it providesPath
Mnestome Global stats (total mnest, active, proto, decaying, events), top-N active by weight, top-N proto-mnest awaiting synthesis, last 20 chronological events. ~/.local/share/metnos/.mnestoma/mnest.sqlite (override MNESTOMA_DB_PATH)
Pairings Active pairings (channel, sender_id, level, paired_at, paired_by, last_seen) and number of revoked pairings in the history. ~/.local/state/metnos/pairings.db
Turns Last 15 turns executed by the planner (timestamp, user query, outcome, step count, first line of the answer). ~/.local/share/metnos/turns/YYYY-MM-DD.jsonl
Vaglio Last 20 decisions of the Vaglio (executor, score, blocked_by, abbreviated reasoning, ts). ~/.local/share/metnos/vaglio/YYYY-MM.jsonl
Scheduler Builtin runtime tasks (apply_ager, synt_suggest, …), schedule, last execution, outcome. ~/.local/share/metnos/scheduler/state.sqlite
Test framework Number of modules, number of test cases, last_status distribution, top modules by case count. /opt/myclaw/runtime/testing/tests.db

None of these sources was created for the dashboard: each one already existed as a source of truth for a runtime component. The dashboard is one more consumer; it writes nothing.

3. Generation: render_dashboard

The exposed function is observability.render_dashboard(out_path). For each source there is a small private helper (_collect_mnestoma, _collect_pairings, _collect_recent_turns, …) that opens the source in read-only mode, gathers a serialisable dict, and returns it. If a source is missing or raises (e.g. SQLite does not exist because the scheduler has never been started), the helper returns an empty dict or a dictionary with the error key: the dashboard renders an informative note but does not break.

The render is a single pass: no template engine, no external dependency. Just Python helpers concatenating HTML strings. Same inline CSS as the canonical docs (for visual consistency with metnos.com), static tables and cards, no JavaScript.

4. Sections of the produced file

The produced HTML file contains, in order:

  1. Test framework: metric cards (modules, cases, status) + top modules by cardinality. Answers the question «is the test net green?».
  2. Mnestome: metric cards (total, active, proto, decaying, events) + table of top active mnest (with a visual weight bar) + table of proto-mnest awaiting synthesis + table of recent events. Answers the question «what does Metnos think it knows how to do?».
  3. Pairings: table of active pairings with level, channel, sender_id, paired_at, last_seen. Answers the question «who can talk to Metnos right now?».
  4. Recent turns: last 15 turns with outcome (answer / error / cap_steps / cap_same_executor) and first line of the answer. Answers the question «what has Metnos done recently?».
  5. Vaglio decisions: last 20 decisions with score and reasoning. Green pill for approve, red for block:guard or block:judge. Answers the question «is the guard holding? Am I blocking too much or too little?».
  6. Scheduler: table of builtin tasks with schedule, last execution, outcome. Answers the question «is the nightly maintenance running?».

5. Privacy and HTML-escape

Everything that comes out of a source goes through html.escape before being inserted into the DOM. The case is guaranteed by the test render_html_escape_sicuro: even if a sender_id contains <script>, the produced file shows &lt;script&gt; — never an active tag. An observability dashboard is not an attack surface, but it takes discipline to keep it that way.

What does NOT appear in the dashboard. The sensitive values that the sources already filter out remain filtered: the vaglio logs only args_keys (not the values), the pairing does not log the payload of the code but only its code_id, mail attachments are never materialised in the turn log. The dashboard inherits these choices: if it is not in the source, it is not in the produced file.

6. Distribution and lifecycle

The default file is workspace/dashboard/index.html, which lives under METNOS_HOME and is not deployed on metnos.com (it is a local operational tool). To consult it: file:///opt/myclaw/workspace/dashboard/index.html in the browser, or scp from the server to Roberto's machine if one wants to look at it remotely.

The file is output-only. It is regenerated every time python3 -m observability render is launched: typically 100 ms. The next evolution (see ch. 8) will be a task of the builtin scheduler that regenerates it every N minutes.

7. CLI

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

No subcommands other than render in v1.1. The generator offers no JSON dump or export: those who want the raw data go straight to the sources (SQLite + JSONL).

8. Limits and what is deferred to v1.2+