# Control board step 3, first refinement: real liveness and "Seen" marks Date: 2026-09-12. Recorded by jarvis (Claude Code, coordinator). Tracking: #1503. Plan: `docs/plans/2026-09-12_control-board-mvp.md` (Step 3 log). ## What Jason reported After using the page: "most of the sessions are actually just in a complete state rather than waiting on me". Also, he had terminated the darkwing and dewey pi sessions, and both still showed "waiting". ## Cause 1. Liveness only asked tmux whether a session by that name existed. Both tmux sessions still existed (now running bash and Claude), so the scanner read the old pi session log as live status. 2. Pi records that the agent finished a reply, not whether that reply was a question or a completion report. Both landed in "waiting". ## What was built - `tmuxIsAlive` now lists the panes of the named tmux session and reports alive only if one runs `pi`. A session that exists but runs something else is offline. The tmux check is injectable for tests. - "Seen" marks: `/board/seen.json` maps `project/agent` to the `lastActivity` timestamp Jason marked. A marked row keeps its state but leaves "Waiting on you" until the agent writes anything newer, which changes the timestamp and clears the mark by itself. "Unsee" clears it by hand. The file is written only by clicks (atomic, mode 0600); a scan reads it and never rewrites it; a corrupt file refuses the scan (fail closed). - Server: `POST /api/seen` with a JSON body; requires `Content-Type: application/json` (so a page from another site cannot post it without a CORS preflight, which this server does not answer); body limit 4096 bytes; 400 on bad input; 500 if the rescan fails. Other methods 405. - Page: Seen / Unsee button beside the state badge, "seen" tag, footer count. CLI `scan --print` shows `s` for seen rows and a seen count. ## Tests `node --test packages/control-board/tests/`: 63 pass, 0 fail (30 new, written by a Claude Sonnet helper against the spec; no src change was needed). `node --test packages/mosaic/tests/`: 69 pass, 0 fail, unchanged. ## Live check Real tmux, full fleet, Chrome via DevTools on port 7332. Before: 18 rows waiting on Jason including darkwing and dewey. After the liveness fix: 16, both now offline (their tmux sessions run bash). Clicking Seen on zane wrote `{"fleet/zane": ""}` (mode 600), the row left "Waiting on you" and showed a seen tag with Unsee in its project table; the API reported 15 waiting and 1 seen. Unsee emptied the file and restored 16. Console: no messages. Screenshot `/tmp/control-board-seen.png` (not committed). The board was left with no marks. ## Independent review Reviewer: code-review agent (Claude Sonnet), read-only. It checked the pi runtime source to confirm a live pi pane reports `pi` as its command (pi sets its process title, and tool subprocesses do not take over the pane), traced the CORS argument for the POST route, the escaping in the new markup, the single-response paths in the server, and the stale-mark fail-safe. Verdict: APPROVED with one finding: the README quoted the tmux command without the `-s -t '='` flags the code uses. Fixed in README and plan page. ## Boundaries kept Loopback only, no auth, no daemon, no launcher changes, no new root files, no run records touched. `seen.json` is Jason's input, not derived data, and is the only board file a scan does not regenerate.