Dewey's round 3 candidate, manifest
agents/dewey/work/queue-40/candidate-manifest-r3.sha256 (d0aa0ded,
27 files, checked OK in the canonical tree).
- WebUI inbox, tasks, agents and trail views, read-only over /api/bus.
The README says the bus proof ends at the Console process.
- CHAT-03 seal: the engine command is fixed, the engine environment is
explicit, SEAL_FLAGS has --no-approve, escalating is cleared on throw.
- Terminal input typed after Ctrl-T or Ctrl-O is held. Only the run whose
own parse set held drains it (T1), and #run catches errors per action.
- DEFERRED keeps N2 and moves F2 to done, citing T1.
Reviews: Filbert approve (comment 27011, rev 260), Darkwing approve
(27013, rev 264). Landing gate on 8cad7722 plus the candidate: webui 22,
conversation 161, control-board 124, every scripts/test-*.sh green,
test-task 98/0. Mutant Mr survives; its flows test is the first
follow-up row.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
185 lines
11 KiB
Markdown
185 lines
11 KiB
Markdown
# Mosaic Console
|
|
|
|
Piece 4, #1507. The control board is the first and only WebUI screen.
|
|
|
|
## Run
|
|
|
|
Start the existing board in one terminal, then the WebUI in another:
|
|
|
|
```sh
|
|
node packages/control-board/src/cli.mjs serve
|
|
node packages/webui/src/cli.mjs serve
|
|
```
|
|
|
|
Open http://127.0.0.1:7330/. Optional `--port N` and
|
|
`--board http://127.0.0.1:7331` select another port or loopback board origin.
|
|
`--business ID` picks the business the bus views read; without it they read
|
|
the running bus host's business (`mosaic bus start <business>`).
|
|
Port 0 picks a free port. Ctrl-C stops each foreground server. No daemon,
|
|
installation, account, authentication or deployment is added.
|
|
|
|
Only HTTP loopback board origins are accepted. The WebUI binds to IPv4 loopback
|
|
by default, rejects nonlocal Host and cross-origin requests, sends no CORS
|
|
headers, refuses redirects and accepts only JSON object POST bodies up to 4096
|
|
bytes. Do not expose either unauthenticated server through a public proxy.
|
|
|
|
## Use
|
|
|
|
- Waiting on you uses the board's `waitingOnYou` flag across all projects.
|
|
- Select a project on the left to filter the session table. Counts show visible
|
|
rows out of the total when Hide offline or Hide seen hides anything.
|
|
- Select an agent to open its inspector. Arrow keys move between table agent
|
|
buttons, Enter opens, and Close or Escape in the inspector returns focus.
|
|
- Seen clears the row from Waiting on you until the board detects new activity.
|
|
The collapsed Seen section keeps those rows available; Unsee returns them.
|
|
- Reply appears only where the board's registration permits it. A failure shows
|
|
the board's stderr and keeps the draft. Transport success is the board's
|
|
`delivered` receipt, not proof that the seat processed the message.
|
|
- Refresh runs the existing board scan. Automatic refresh uses the board page's
|
|
ten-second interval; Pause stops it. Failed refreshes keep the last snapshot
|
|
with a warning. There are no automatic action retries.
|
|
- Palette and appearance use the existing brand tokens and persist in this
|
|
browser when local storage is available. No settings screen is added.
|
|
- History opens a read-only conversation view for a seat, from its Waiting
|
|
card, its table row or its inspector (#1507, CHAT-02). It shows the whole
|
|
branch with nothing clipped. Tool calls, tool results and thinking start
|
|
collapsed. Session text is always shown as text: Markdown stays as source,
|
|
and terminal controls, bidi controls and marks show as visible symbols. Reply in the view
|
|
uses the same board reply path as the inspector.
|
|
- The view checks for new entries on the same ten-second refresh, and Pause
|
|
stops it. It never switches on its own. A fork, a newer session for the seat
|
|
or a rewritten file each shows a marker with a button to open the other
|
|
history. Reloading after a rewrite keeps the branch the view was on; if that
|
|
branch is gone, the view opens the latest one and says so. Session lists
|
|
older sessions for the seat. Only repository Pi seats
|
|
have history; other harnesses say so.
|
|
|
|
Drafts and receipts stay in page memory, including across refresh, inspector
|
|
changes and a stale registration. Reloading or closing the page loses them.
|
|
A pending send stays disabled across refresh; new text typed during a send is
|
|
not cleared by the earlier send's success. If the proxy loses the response,
|
|
delivery may be unknown: inspect the seat before sending again.
|
|
|
|
## Inbox, tasks, agents and trails (slice 1 S5, #1522)
|
|
|
|
The Console sidebar adds Inbox, Tasks and Agents next to the control board,
|
|
which stays at `#/`. Routes: `#/inbox`, `#/inbox/<decision>`, `#/tasks`,
|
|
`#/tasks/<vikunja:project/task>`, `#/agents`, `#/trail/task/<ref>` and
|
|
`#/trail/decision/<id>`, with `?kind=` filters on a trail. The design
|
|
note is `agents/dewey/work/wui/SLICE1-VIEWS.md`.
|
|
|
|
- Every view reads the four verbs of the Q1 module (`packages/bus/src/views.mjs`,
|
|
lead decision 56): `inbox`, `tasks`, `agents` and `trail`. The CLI reads the
|
|
same functions, so both show the same broker data.
|
|
- Nothing writes. A decision shows `mosaic decide <id> <key>` for each choice,
|
|
with Copy, which only puts the command on the clipboard. It is answered in a
|
|
terminal (REQ-DEC-3, Q4). Seen is not set from the browser either. The
|
|
command has no `--business`, so `mosaic decide` uses the running bus host's
|
|
business, as the Console does by default. From a Console started with
|
|
`--business` for another business the copied command refuses (no bus host,
|
|
or no such decision) rather than answering elsewhere.
|
|
- What no Q1 verb returns is labelled where it would show, for example
|
|
"Bot names: not in the Q1 module" (lead decision 63). Nothing is guessed.
|
|
- A task's list row can only say its current state came from a Vikunja read,
|
|
since the list has no trail. The task page reads the trail and tells a task
|
|
the stack never created from one changed in Vikunja after the stack wrote it.
|
|
A stale poll read is shown in the snapshots and never as current.
|
|
- All bus- and agent-authored text is rendered inert: controls show as control
|
|
pictures or `[U+XXXX]`, and Markdown stays as source.
|
|
- Views refresh on the board's ten-second interval and stop on Pause. Focus,
|
|
open sections and the copy status survive a refresh.
|
|
- A failed read keeps the last good answer for that read and says it is old,
|
|
with the time it was read. A page never read shows the failure instead,
|
|
titled "Bus refused the read" (403: the bus refused the Console's read, for
|
|
example `human-required` from a Console started inside an agent run), "No bus to read" (no system
|
|
config, or no bus host and no `--business`) or "The read failed".
|
|
|
|
## Data and boundaries
|
|
|
|
GET `/api/board`, `/api/conversations` and `/api/conversation`, and POST
|
|
`/api/seen` and `/api/reply` proxy only those board paths. Only the two
|
|
conversation routes carry their query string; the board validates it. POST
|
|
bytes and upstream status/JSON are preserved. GET `/api/config` returns the
|
|
configured board URL for the page's error message. No scanner, registration,
|
|
session reader or transport is implemented here. The session reader is
|
|
`packages/conversation`, served by the board.
|
|
|
|
GET `/api/bus/inbox`, `/api/bus/tasks`, `/api/bus/agents` and
|
|
`/api/bus/trail?subject=<id>` are the bus reads (`src/bus.mjs`). Any other
|
|
method is 405. The subject must match the broker's identifier rule, else 400.
|
|
Each read runs the S4 human transport (`packages/bus/src/human-cli.mjs`) as
|
|
a child process, so a slow read doesn't stall the server. The bus checks
|
|
that child's ancestry, which ends at the Console process; it never sees the
|
|
browser or any other client of the port. So while the Console runs,
|
|
anything that can connect to its port (7330 by default) reads what a reader
|
|
capability reads ("Human and reader paths" in `packages/bus/README.md`):
|
|
the inbox, tasks, agents and trails. That includes a T3 seat using `curl`
|
|
and a managed S6 session, since S6 doesn't confine the network. No route
|
|
writes (Q4), so the exposure is reads only. Slice 1 doesn't change this
|
|
(Filbert F1 on #1522). Answers are `{ rows, at }`; failures are `{ error, message }`
|
|
with 403 for a refusal, 503 for no bus or no answer, and 502 for an answer
|
|
that can't be used. The bus needs the system config
|
|
(`~/.config/mosaic-dev/config.json`); without it the board still serves and
|
|
the bus routes answer `not-configured`.
|
|
|
|
Console's shared CSS, Console CSS, brand.js and local Manrope fonts were copied
|
|
unchanged from `agents/dewey/work/wui/`. Font license and source URLs accompany
|
|
the files under `src/public/assets/fonts/`. `live.css` contains the live-page
|
|
adaptations; original mockups and unrelated pending design work stay untouched.
|
|
Unsupported mockup fields and controls are listed in `docs/plans/DEFERRED.md`.
|
|
The source tree is a project filter; no invented workspace registration tree
|
|
or mockup session hierarchy is presented as live data.
|
|
|
|
## Verify
|
|
|
|
```sh
|
|
node --test packages/webui/tests/
|
|
node --test packages/control-board/tests/ packages/seat/tests/ packages/ledger/tests/ packages/mosaic/tests/
|
|
WEBUI_EVIDENCE=/tmp/webui-evidence node --test packages/webui/tests/browser.test.mjs
|
|
WEBUI_EVIDENCE=/tmp/webui-evidence node --test packages/webui/tests/conversation.test.mjs
|
|
WEBUI_EVIDENCE=/tmp/webui-evidence node --test packages/webui/tests/bus-browser.test.mjs
|
|
```
|
|
|
|
Node's test runner and installed `/usr/bin/chromium` are required. Set `CHROMIUM`
|
|
to another installed Chromium path. No npm download is needed. The copied CDP
|
|
helper starts a separate temporary browser profile and removes it on exit.
|
|
Tests use temporary board session/registration files and stub the board's
|
|
transport. They never send to real seats or read real session logs.
|
|
|
|
Browser tests exercise the rendered real board fixture, exact counts, project
|
|
filtering, keyboard return focus, Seen/Unsee, success/failure receipts, draft and
|
|
caret preservation, pending-send exclusion, storage denial, stale registration,
|
|
loading/empty/malformed/unreachable states and hostile text. Contrast is measured
|
|
on 330 rendered samples across ten palettes and three modes. Layouts are checked
|
|
at 320, 390, 768, 1440 and 2560px. Horizontal scrolling is intentional within the
|
|
dense table; the page itself must not overflow.
|
|
|
|
Conversation tests run the real board routes over temporary repository-layout
|
|
session files. They cover full-length answers, collapsed tools and thinking,
|
|
hostile content rendered inert, malformed-line and reconcile markers, forks, and
|
|
the return flow: a send from the view, a tool call and a delayed result while a
|
|
draft is typed, a peer message, a 4.5-million-character answer split into
|
|
continuation parts, and a relaunch mid-turn.
|
|
|
|
Bus tests (`bus.test.mjs`, `bus-browser.test.mjs`) run the routes and the
|
|
views against an in-process broker read through its reader session, so every
|
|
row has the broker's own shape. `humanCall` runs against a stub CLI script.
|
|
They cover each view, the gap labels, inert hostile text, Copy, the stale
|
|
fallback and each failure title, and that no route writes. They never start
|
|
the human CLI against a live bus.
|
|
|
|
No root CI workflow is configured for this package. These local tests are not a
|
|
claim of CI, deployment, live-seat delivery or user acceptance.
|
|
|
|
## User test and rollback
|
|
|
|
Gate E belongs to Jason on Monday 2026-09-14. Use Console to find who is waiting,
|
|
open a registered repo seat, reply and see its next answer after a scan. Mark a
|
|
completion Seen and find it again in Seen. Record any reason to open the board's
|
|
own page or a repo seat terminal in DEFERRED.md. Pass is Jason's end-of-day
|
|
say-so, not a test result. Keep #1507 open pending that ruling.
|
|
|
|
Rollback requires only stopping the WebUI and using the unchanged board at 7331.
|
|
Revert the scoped WebUI commit to remove it; there is no data migration to undo.
|
|
Seen and reply actions already taken belong to the board and are not rolled back.
|