diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 93bc8e8e..b1430424 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -1999,3 +1999,16 @@ the refresh because only the section body is re-rendered. Page-only change; one static test added (control-board 64/64, registry 69/69). Independent review APPROVED with no findings. Verified in Chrome against the two marks Jason had made (resume, filbert). Next: Jason keeps using it. + +## 2026-09-12 — Control board step 3, third refinement (#1503) + +Before: seen rows still sat in the project tables with a small tag, which +was noise now that the Seen section lists them. + +After: each project header has "Hide offline" and "Hide seen" checkboxes, +both on by default, and the note under the table reads +"N offline hidden · N seen hidden". The choice survives refreshes. Page-only +change, one static test (control-board 65/65, registry 69/69). Sonnet +review: APPROVED, one FYI (the default-on test would still pass without the +persistence guard), fixed by tightening the regex. Verified in Chrome against +Jason's real marks. Next: Jason keeps using it. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index ee50ba86..fdf5b449 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -216,3 +216,4 @@ are never rewritten or removed; corrections are new entries. - 2026-09-12 — jarvis (Claude Code, coordinator) — Control board MVP step 2 (#1503, D-001): `packages/control-board` gains `serve` (loopback-only local server, `/api/board` re-runs the scanner) and a single-file page (waiting-on-you first, per-project groups, hide-offline, expandable rows, 10s auto-refresh with pause). Suites: control-board 33/33, registry 69/69. Static review (sonnet) found no defects; live browser check by coordinator. Receipt docs/plans/reviews/2026-09-12_control-board-step2-review.md. CURRENT next action: step 3, daily use by Jason. - 2026-09-12 — jarvis (Claude Code, coordinator) — Control board step 3, first refinement (#1503): Jason reported killed pi sessions still "waiting" and most waiting rows being completion reports. Liveness now requires a tmux pane running pi; "Seen" marks (seen.json, POST /api/seen, Seen/Unsee on the page) drop read rows out of "Waiting on you" until the agent writes again. Tests 63/63 (30 new by sonnet helper), registry 69/69; sonnet review APPROVED (README command fixed). Receipt docs/plans/reviews/2026-09-12_control-board-step3-seen-marks.md. - 2026-09-12 — jarvis (Claude Code, coordinator) — Control board step 3, second refinement (#1503): Jason asked for a way to recall Seen rows; added a collapsed "Seen (N)" section with Unsee per row. Page-only change plus one static test (64/64); sonnet review APPROVED; live check in Chrome against Jason's two real marks. +- 2026-09-12 — jarvis (Claude Code, coordinator) — Control board step 3, third refinement (#1503): Jason suggested a per-project "Hide seen" checkbox beside "Hide offline"; added, on by default, with a combined hidden-count note. Page-only change plus one static test (65/65); sonnet review APPROVED (one test-rigor FYI fixed); live check in Chrome. diff --git a/docs/plans/2026-09-12_control-board-mvp.md b/docs/plans/2026-09-12_control-board-mvp.md index 45a03cc0..d8799ae4 100644 --- a/docs/plans/2026-09-12_control-board-mvp.md +++ b/docs/plans/2026-09-12_control-board-mvp.md @@ -139,3 +139,8 @@ button, Jason noted the board had no way to show seen rows again. The page now has a collapsed "Seen (N)" section between "Waiting on you" and "By project" that lists every marked row with an Unsee button. It stays open or closed across refreshes. + +**2026-09-12 — "Hide seen" per project.** Jason suggested a checkbox like +"Hide offline" so seen rows stop cluttering the fleet table now that the +Seen section exists. Each project header has both boxes, on by default, +and the note under the table reads "N offline hidden · N seen hidden". diff --git a/packages/control-board/README.md b/packages/control-board/README.md index 7141d562..06af35fb 100644 --- a/packages/control-board/README.md +++ b/packages/control-board/README.md @@ -96,7 +96,9 @@ the agent's newest message still has that exact `lastActivity` timestamp — as soon as the agent writes anything new, `lastActivity` changes, the mark no longer matches, and the row falls back into "Waiting on you" on its own. Marked rows are listed under a collapsed "Seen (N)" section on the page, -each with an "Unsee" button, so nothing marked is ever out of reach. +each with an "Unsee" button, so nothing marked is ever out of reach. Each +project table has "Hide offline" and "Hide seen" checkboxes (both on by +default) with a note saying how many rows each one hides. If `seen.json` exists but is not valid JSON (or not an object of string values), the scan refuses rather than silently dropping every mark. diff --git a/packages/control-board/src/page.html b/packages/control-board/src/page.html index 867665ad..e76d7f30 100644 --- a/packages/control-board/src/page.html +++ b/packages/control-board/src/page.html @@ -69,6 +69,7 @@ .detail-list dd{margin:0;overflow-wrap:anywhere} .project-group{margin-bottom:20px} .project-group-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px} + .group-toggles{display:flex;flex-wrap:wrap;gap:14px} .project-group-head label{font-size:.85rem;color:var(--muted);display:flex;align-items:center;gap:6px} .offline-note{margin:6px 0 0;font-size:.82rem;color:var(--muted)} .page-footer{margin-top:24px;padding-top:12px;border-top:1px solid var(--line);color:var(--muted);font-size:.85rem} @@ -125,6 +126,7 @@ var timerId = null; var secondsLeft = REFRESH_MS / 1000; var hideOfflineState = {}; + var hideSeenState = {}; // Open detail panels survive a refresh. Keyed by section, project and agent // because the same agent can appear in both the waiting list and its group. var openDetails = {}; @@ -279,16 +281,27 @@ projectsBody.innerHTML = projects.map(function (project) { var group = byProject[project].slice().sort(function (a, b) { return a.agent.localeCompare(b.agent); }); if (!(project in hideOfflineState)) hideOfflineState[project] = true; + if (!(project in hideSeenState)) hideSeenState[project] = true; var hideOffline = hideOfflineState[project]; - var visible = group.filter(function (r) { return !(hideOffline && r.state === "offline"); }); - var hiddenCount = group.length - visible.length; + var hideSeen = hideSeenState[project]; + var offlineHidden = 0, seenHidden = 0; + var visible = group.filter(function (r) { + if (hideOffline && r.state === "offline") { offlineHidden += 1; return false; } + if (hideSeen && r.seen) { seenHidden += 1; return false; } + return true; + }); var rows = visible.map(function (r) { return buildRowPair(r, false); }).join(""); - var note = hiddenCount > 0 ? '
' + hiddenCount + " offline hidden
" : ""; + var noteParts = []; + if (offlineHidden > 0) noteParts.push(offlineHidden + " offline hidden"); + if (seenHidden > 0) noteParts.push(seenHidden + " seen hidden"); + var note = noteParts.length > 0 ? '' + noteParts.join(" \u00b7 ") + "
" : ""; return ( '| Agent | State | Age | Last message | " + "
|---|---|---|---|
| No agents. | |||