Files
nisse/nisse-ui
dongarandClaude Opus 5.5 a8e2023183
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 2m41s
CI / e2e (pull_request) Successful in 4m25s
The status page's walkthrough (M6.6b)
A new package, nisse-ui: a read-only page for studying how the agents
work. For each work item it shows the steps (what people and the
orchestrator said, and each run), each run's turns, and each turn's
request read against the log it was made from:
- each message beside the events it came from, tagged unchanged,
  labelled, narrated, shortened (by how much) or a compaction, with what
  fitting dropped;
- what is new since the turn before, and where the request first
  differs (where prompt reuse had to stop), next to the server's count;
- the reply with its reasoning, and the raw JSON.

Runs going in circles are flagged by nisse_core.loop.circles (repeated
near-identical replies, one correction given again and again, repeated
apologies), a pure function M7.8 can reuse in Driver.run.

In nisse-core:
- render.py: message_indexes(), from the same code render() uses, so
  the page's matching can't drift from what was sent.
- calls.py: the record notes when recording began; the reader gains
  calls_for(item) and call(id).
- state/readonly.py: opens an agent's SQLite file without creating its
  -wal/-shm files (mode=ro alone does, once the writer has closed).

The page reads only through read-only connections, escapes everything,
and sends a Content Security Policy that allows no script. It listens on
127.0.0.1; until M6.6d puts it behind Authelia, reach it over an SSH
tunnel. Jinja2 is its one new dependency, for autoescaping.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
2026-10-25 03:36:50 +00:00
..

nisse-ui

The status page (architecture X6): a read-only view of what the agents did and how, for studying context, compaction and memory in practice.

It reads each agent's state store and the call record beside it (L7), and never writes to either. It runs no model and holds no credentials.

uv run nisse-ui --source dev=/var/lib/nisse-dev/state.db \
                --source review=/var/lib/nisse-review/state.db \
                --runs /path/to/kept-runs
  • --source NAME=STATE_DB: an agent's state store. Its call record is <stem>.calls.db beside it.
  • --runs DIR: runs the benchmark kept (scripts/benchmark.py run --keep-runs DIR). Each folder holding a state.db is a source.

It listens on 127.0.0.1:8765, because it shows everything the models saw, including what other people wrote. Until it sits behind Caddy and Authelia (M6.6d), reach it through an SSH tunnel:

ssh -L 8765:localhost:8765 <this VM>

then open http://localhost:8765/.

What it shows: for each work item, its steps (what people and the orchestrator said, and each run), each run's turns, and for each turn:

  • the request exactly as sent, message by message, beside the log events each came from and what rendering did to them;
  • what changed since the turn before, and where prompt reuse had to stop, next to the server's own count;
  • the reply, with its reasoning;
  • the raw JSON.

Runs going in circles are flagged (nisse_core.loop.circles).

Safety: everything is escaped, and the page sends a Content Security Policy that runs no script at all. Files are opened through nisse_core.state.readonly, which never creates or locks anything.