Add control board status scanner and MVP plan (#1503)
Step 1 of the control board MVP (decision MOSAIC-STACK-D-001): a plan page, Gitea #1503, and packages/control-board, which reads each agent's newest pi session log plus tmux liveness and writes one status file per agent under <dataRoot>/board/. 23/23 tests; independent review approved after three fixes (length stopReason as error, unknown liveness state, secrets-boundary test). CURRENT.md now points at step 2, the page. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# control-board
|
||||
|
||||
Step 1 of the control board MVP (`docs/plans/2026-09-12_control-board-mvp.md`).
|
||||
This package scans your running pi agent sessions and writes one small JSON
|
||||
status file per agent, plus one summary file, so a later web page can show
|
||||
them all in one place. It reads pi session logs and checks tmux liveness. It
|
||||
does not launch, stop, or talk to any agent. Board files are derived and
|
||||
rewritable; they are not run records and are not evidence.
|
||||
|
||||
## States
|
||||
|
||||
| State | Plain-words meaning |
|
||||
|---------|----------------------|
|
||||
| working | The agent is in the middle of a turn: thinking or running a tool. |
|
||||
| waiting | The agent finished its turn. It is your move now. |
|
||||
| error | The agent's last turn ended in an error, was aborted, or was cut off. Go look at it. |
|
||||
| offline | There is no live tmux session for this agent right now. |
|
||||
| idle | The agent is live but has not had a conversation yet. |
|
||||
| unknown | The scanner could not ask tmux (missing or not answering). It does not assume the agent is alive. |
|
||||
|
||||
## Command
|
||||
|
||||
```
|
||||
node src/cli.mjs scan [--config PATH] [--repo PATH] [--fleet PATH|none] [--liveness tmux|assume-alive] [--print]
|
||||
```
|
||||
|
||||
- `--config PATH` — path to the system config file. Defaults to
|
||||
`~/.config/mosaic-dev/config.json`. This file must exist and name an
|
||||
absolute `dataRoot`, or the scanner refuses to run.
|
||||
- `--repo PATH` — path to a project checkout to scan for repo agents
|
||||
(`.pi/state/<agent>/sessions`). Defaults to the current directory.
|
||||
- `--fleet PATH|none` — path to the fleet agents directory
|
||||
(`<fleet>/<agent>/.pi/agent/sessions`, tmux socket `mosaic-fleet`).
|
||||
Defaults to `~/.mosaic/fleet/agents`. Pass `none` to skip fleet agents.
|
||||
- `--liveness tmux|assume-alive` — how to decide if an agent is alive.
|
||||
`tmux` (default) checks the real tmux session. `assume-alive` treats
|
||||
every agent as alive, useful for tests or environments without tmux.
|
||||
- `--print` — also print a one-line-per-agent table to stdout.
|
||||
|
||||
## Exit codes
|
||||
|
||||
- `0` — scan completed and status files were written.
|
||||
- `2` — refused: bad config, missing/invalid `dataRoot`, or bad arguments.
|
||||
The message on stderr says why.
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
node --test packages/control-board/tests/
|
||||
```
|
||||
|
||||
## Output layout
|
||||
|
||||
```
|
||||
<dataRoot>/board/
|
||||
index.json # summary: counts, waiting-on-you list, all records
|
||||
sessions/
|
||||
<project>/
|
||||
<agent>.json # one status record per agent
|
||||
```
|
||||
|
||||
## Example status record
|
||||
|
||||
```json
|
||||
{
|
||||
"agent": "darkwing",
|
||||
"project": "mosaic-stack",
|
||||
"state": "waiting",
|
||||
"waitingOnYou": true,
|
||||
"alive": true,
|
||||
"tmux": { "socket": null, "session": "darkwing" },
|
||||
"sessionFile": "/mnt/storage/src/mosaic-stack/.pi/state/darkwing/sessions/2026-09-12.jsonl",
|
||||
"sessionId": "01a06e48-0718-71f2-a889-c263c4800fb9",
|
||||
"cwd": "/mnt/storage/src/mosaic-stack",
|
||||
"lastActivity": "2026-09-12T15:04:33.000Z",
|
||||
"ageSeconds": 42,
|
||||
"lastAssistantText": "Ready for the next step whenever you are.",
|
||||
"lastError": null,
|
||||
"skippedLines": 0,
|
||||
"scannedAt": "2026-09-12T15:05:15.000Z"
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user