diff --git a/docs/Architecture.md b/docs/Architecture.md index 148a81e..5c08091 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -21,6 +21,7 @@ overnight and expects to be treated well in return. | Dev Agent | `nisse-dev` | Designs and builds software projects (Part D) | | Review Agent | `nisse-review` | Reviews pull requests (Part R) | | Sysadmin Agent | `nisse-ops` | Operates infrastructure (Part O) | +| Status page | `nisse-ui` | Shows the operator what the agents are doing and how (X6); not an agent | More agents are planned (3D design work, video-file management), each another application over `nisse-core`. One string names all of an agent's artifacts @@ -278,7 +279,8 @@ executes nothing, so it runs on the agent host. **Matrix is the conversation channel:** a self-hosted homeserver, one identity and room per agent, behind a `Transport` interface so another chat system is one new -class. Existing Matrix clients are the UI. +class. Existing Matrix clients are the UI for conversation and commands; a +read-only page shows each agent's work, and how it went, in detail (X6). **A thread per work item.** Each item's conversation is a Matrix thread, and the thread is how the agent knows which item a message is about. @@ -332,7 +334,8 @@ logs the outage; interrupted outbound effects are covered by intents (L8). ### L6. Context and memory **1. The working context of one model call** is rendered from the log at call time -for one role, fitted to that model's window, and never stored. +for one role, fitted to that model's window, and never stored as state. A copy +goes into the call record (L7) for the operator to study; nothing reads it back. - **A long run is compacted:** well before the window fills, the model's own notes replace the middle of its run in one step (a `compaction` event, L7), keeping word for word what started the work and its last few turns. Rare, @@ -411,6 +414,25 @@ call time. delegation that produced it. - **The log is never edited;** corrections and compactions are new events. +**The call record** is a second store beside the log, for study only: `nisse-core` +writes it for every model call of every agent, into its own file on the agent's +volume. +- **What each call was:** the request exactly as sent (system prompt, tools, + messages, `tool_choice`, output limit; never headers, so no credential), the raw + response with its reasoning, the model asked and the one that answered, time, + tokens, the server's own count of prompt reuse, and what fitting cut. A failed + call is recorded with its error. +- **Where it came from:** its work item, role and run (a driver run, a consult, a + compaction, a classification), and for each message, the log events it was + rendered from and what rendering did to them (unchanged, labelled, narrated, + compacted, shortened and by how much), with what was dropped. So a request reads + against the log it was made from (L6). +- **Content is stored once,** by hash: a long, growing conversation costs about one + copy of itself. +- **It is never load-bearing:** nothing in the agent reads it, a failed write is + logged and the call goes ahead, and it is deleted when the agent starts. Its + layout never migrates; it carries its version for the page (X6). + ### L8. Durability and recovery **The state store** (SQLite) holds each work item's position, permissions, pending @@ -1078,8 +1100,9 @@ template with a trigger, rate limit and expiry, for a routine fix). **One agent host,** stable and long-lived. Each agent is a container on it with its own volume (state, transcripts), secrets (L12) and network; no agent can reach -another's. Its MCP servers run beside it (X3). The vault lives here (L10). **It never -runs a command a model chose** (L13), which is what makes sharing it safe. +another's, and only the status page reads their volumes, read-only (X6). Its MCP +servers run beside it (X3). The vault lives here (L10). **It never runs a command +a model chose** (L13), which is what makes sharing it safe. **Tool VMs** are where model-chosen commands run, reached only over SSH from the agent host, each built from a template plus recorded installs and disposable: @@ -1135,10 +1158,49 @@ Vaultwarden, Samba AD with Authelia, and SilverBullet for the operator's view of the vault. Each agent has its own account, token and room in each; nothing is shared between agents. +### X6. The status page + +**`nisse-ui`** is the operator's view of the agents: what each is doing, and how it +did it in full detail. It is for understanding the system (how context, compaction +and memory work in practice), more than for daily use. +- **What it shows:** per agent, the active item, what's queued, parked and blocked + and why, recent closed items, with links to issue, PR and thread; and per item, a + walkthrough: its steps (runs, and the orchestrator's facts and gates between + them), each run's turns, and each turn's request and response from the call + record (L7), readable: where each message came from and what was done to it, + what changed since the previous turn and where prompt reuse stopped, the + reasoning, and the raw JSON. Memory appears as the log records it: the index + when it was shown, each note read or written. Work from before the agent's last + start has its steps but no requests. +- **It reads, never writes:** each agent's state store and call record through a + read-only mount, opened read-only in short transactions, and the agent's memory + folder read-only, as SilverBullet does (L10). Each agent stays the only writer + of its state (L8), and agent code doesn't change for the page. It runs no + model, holds no credentials and reaches nothing but the mounts and Caddy. +- **Versions:** it is released with the agents, from the same tag. It reads the + state store's schema versions it knows and says so for any other, rather than + guessing; it reads item data tolerantly (defaults for missing fields, raw names + for unknown states), for the gap while one container updates before another. + CI tests it against stores written by the agents' own code, so a change that + would break it fails in the same PR. +- **Any recorded run opens,** not only a live agent's: bring-up, end-to-end and + benchmark runs leave the same two files. +- **Everything it shows is untrusted text** (L11): it is escaped, and the page + allows no script it didn't ship. +- **Access** is through Caddy behind Authelia, the operator's group only: it shows + everything the models saw. +- **Commands come later** (Part Q), never by writing an agent's files: as another + `Transport` (L5), so a button sends what Matrix would, with the same rules and + record. + --- ## Part Q — Open questions +- **Commands from the status page** (X6): how they reach each agent and show who + sent them (a per-agent inbox only the page writes, or signed requests). The + first are `stop`, priority ("do #N next"), and a **hold**: a task, or a whole + agent, does nothing until released. A hold is a new command, in Matrix too. - **The classifier's model,** and how its verdicts are calibrated against overrides. - **Recognising questions:** an explicit marker or classification; a misread asks. - **How far the local driver goes,** measured on real work (P7). diff --git a/docs/Development-Plan.md b/docs/Development-Plan.md index 5719cfe..e19611f 100644 --- a/docs/Development-Plan.md +++ b/docs/Development-Plan.md @@ -578,6 +578,22 @@ Samba AD principal (L12). **M6.5 The browser tool.** *Pre-approved.* On the internal test network (D7). +**M6.6 The status page.** *Pre-approved (design agreed 2026-10-24, #109).* +`nisse-ui` (X6), for studying how the agents work: context, compaction, memory. +Slices a–c are built on this box before the agent host is ready, against +bring-up, end-to-end and benchmark runs; only d waits for M6.1. +- **a. The call record** (L7) in `nisse-core`: written by the shared model client + and `Driver.run`, with each message's provenance from the per-role view and + fitting; wired in each agent's build; deleted at start. +- **b. The walkthrough:** an item's steps, each run's turns, and each request read + against the log it was made from. +- **c. The overview:** each agent's active, queued, parked and blocked items. +- **d. Deployment:** its image, the read-only mounts and a Caddy route behind + Authelia (with #166). + +Commands wait (Part Q). The shared database #109 first proposed is dropped: each +agent keeps its own store. + ### Phase 7 — `nisse-core` and `nisse-review` `nisse-review` (Part R) comes before `nisse-ops`: it writes only comments, so it @@ -796,6 +812,7 @@ the Terraform the operator is writing now. **M8.4 The ops tool VM and deployment From the architecture's open questions and older issues: filing issues from conversation; stacked PRs; releases; `nisse-ops` issuing credentials; a server database; recovering the agent host (an ops issue); more than one active work item; +commands from the status page, with a hold on a task or agent (X6); vision; one local model for every agent; several forges (#26); a room per project (#28). @@ -816,6 +833,7 @@ vision; one local model for every agent; several forges (#26); a room per projec | #69 inline review comments | M2.1 | | #70 watch stall | M2.1 | | #77 conversational agent | M2.3 (questions), M2.7 | +| #109 a UI for every agent's status (no shared database) | M6.6 | | #137 block on an unreachable build VM | M4.4 | | #144 redact secrets an MCP server returns | After M8.1 |