plans: rows 93-95 from Jason's PM test (#1587, #1588, #1589), fault 9 into row 89

The review loop through the bus (findings faults 3 and 5), every
message to the human live (Mos sage-0103), and the Console Board
showing the stack's seats with a signed-out line (fault 8, Mos
sage-0105 and sage-0106). Row 89 also fixes the session text's
built-in tools line for Claude Code (fault 9).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-12 14:50:16 -05:00
co-authored by Claude Opus 5.5
parent 2f57a091a3
commit 397e904772
2 changed files with 253 additions and 1 deletions
+12 -1
View File
@@ -23,6 +23,12 @@ server sends it as indented JSON (`packages/harness/src/mcp-server.mjs:40`,
PM's workspace, and the run's file guard refused to read it. That refusal
is right; the reply is the defect. So the PM couldn't see the board.
The same session text lists the wrong built-in tools for Claude Code
(the PM's findings, fault 9). `bundle.mjs:67` prints the role's pi
names, so the PM read "read, write, edit, grep, find, ls", while
Claude Code gets Read, Write, Edit, Grep and Glob
(`packages/harness/src/gate.mjs:17,29`, `claudeBuiltins`).
### Owner and reviewer
Owner: Dewey, after row 81 lands. Reviewer: Darkwing.
@@ -31,6 +37,7 @@ Owner: Dewey, after row 81 lands. Reviewer: Darkwing.
- `packages/bus/src/broker.mjs`, the `tasks` verb and `#taskRows` only
- `packages/harness/src/tools.mjs`, `mcp-server.mjs`, `pi-extension.mjs`
- `packages/harness/src/bundle.mjs`, the built-in tools line only
- `packages/bus/README.md`, `packages/harness/README.md`, the sections
on the `tasks` verb and the tool replies
- tests under `packages/bus/tests/` and `packages/harness/tests/`
@@ -60,10 +67,14 @@ Owner: Dewey, after row 81 lands. Reviewer: Darkwing.
returns an error naming the size and the cap and telling the session to
narrow the query, never a cut-off reply. Replies go out as compact
JSON, not indented.
- The session text names the built-in tools the session's harness
really has: `claudeBuiltins(policy)` for Claude Code, the pi names
for pi.
- Tests: a board of 500 fixture tasks with long descriptions, where
`list_tasks` with defaults fits under the cap and pages to the end
with `next`; each filter; `task_ref`; the refusals; the cap error from
both servers; and the no-argument call still matching today's reply.
both servers; the no-argument call still matching today's reply; and
the tools line for each harness.
Suites: the bus, harness, webui and cli node suites, and every
`scripts/test-*.sh`.
+241
View File
@@ -0,0 +1,241 @@
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`.
It covers the faults from Jason's first PM test that rows 89 to 92
don't: the PM's findings file
(`<dataRoot>/workspaces/mosaic-stack/pm/findings-2026-10-12.md`)
faults 3, 5 and 8, Jason's "blind after each send" report (Mos
sage-0103) and his Console report (Mos sage-0105). Fault 9 went into
row 89. Jason's ruling through Mos (sage-0104, Q125 yes): these are
fixed through Sage's rows, not by the running PM, then the stack is
redeployed and his test re-run. Gitea issues #1587, #1588 and
#1589.
# The fixes from Jason's PM test (2026-10-12)
## A review loop through the bus
### Problem
The coder role holds `git.push.working` and `review.request`, and the
reviewer holds `review.verdict` (`roles/coder.json:9`,
`roles/reviewer.json:9`). The broker lists all three actions
(`packages/bus/src/broker.mjs:13-17`) and records `review.*` events
against a task (`:254`), but no verb handles them and no typed tool
exists (`packages/harness/src/tools.mjs`). In the test the coder
couldn't hand its change to the reviewer except by pasting it into a
message, the reviewer sent its verdict as a message, and the PM cited
that message in `task_close`. P19 #229's review asked for changes
only because nothing could be pushed.
### Owner and reviewers
Owner: Filbert, after row 91 (a project checkout in each role
workspace) and their row 95. Reviewers: Darkwing and Dewey, both
required, since the host runs git for a session.
### Files owned
- `packages/bus/src/broker.mjs`, the new review verbs only
- `packages/cli/src/launcher.mjs` and `packages/seat/src/checkout.mjs`,
only the host-side push and fetch
- `packages/harness/src/tools.mjs`, `runner.mjs`, the new tools only
- `roles/coder.md`, `roles/reviewer.md`, `roles/pm.md`, the review
paragraphs only
- `packages/bus/README.md`, `packages/harness/README.md`,
`packages/seat/README.md`
- tests under `packages/bus/tests/`, `packages/harness/tests/`,
`packages/seat/tests/` and `packages/cli/tests/`
- `agents/filbert/work/queue-<row>/`
### What ships
- A working repository per business and project, a bare git
repository under the data root that only the host writes. It is not
the project's root and not a forge. No credential goes near it.
- `push_working` (action `git.push.working`): the host, outside the
session's sandbox, pushes one branch of the caller's clone to the
working repository as `work/<task ref>`. It takes a task ref and a
branch, refuses anything but a fast-forward of that one ref, and
records the commit.
- `request_review` (action `review.request`): records a `review.request`
event on the task, naming the commit already in the working
repository, and messages the reviewer role. A commit not in the
working repository refuses.
- `fetch_review` for holders of `review.verdict`: the host fetches the
requested commit into the caller's clone as a remote-tracking ref, so
the reviewer reads and tests it in its own workspace.
- `review_verdict` (action `review.verdict`): records `approve` or
`changes` with a body on the task, citing the request event. The PM's
`task_close` cites the verdict event's id. Whether the broker checks
that citation is a choice the packet makes and argues.
- The session text from the bundle names the review steps; the role
files say the same.
- Tests: the whole loop between a fake coder and a fake reviewer
session over real clones, each refusal (another task's branch, a
non-fast-forward, an unknown commit, a role without the action), and
the project root unchanged after every case.
Suites: the bus, harness, seat and cli node suites, and every
`scripts/test-*.sh`.
### Out of scope
Landing an approved commit in the project, which stays Sage's gate
under R28. `git.push.protected`. A forge or Gitea remote. Credentials
in any session.
### Gate
Darkwing and Dewey approve on the row's issue, naming the candidate
manifest. The suites above pass on Sage's gate rerun. Live at the next
bus restart, which Mos approves first (sage-0104).
## Every message to the human, live
### Problem
`mosaic talk` sends, then prints whatever reaches the human until the
direct reply comes, and stops there (`packages/cli/src/cli.mjs:204-214`).
A message the PM sends later, from a turn another seat or the PM itself
started, has no `in_reply_to` and waits unread until the next `talk`
prints it. Jason reads that as each answer arriving one message late.
`mosaic inbox` lists decisions only (`broker.mjs:846-851`). The Console
shows replies to its own send (row 81, the `replies` verb,
`broker.mjs:915-925`) and nothing else, so it never shows those
messages either.
### Owner and reviewer
Owner: Rocko, after row 77, and before their rows 84 and 85. Reviewer:
Dewey, who built row 81.
### Files owned
- `packages/bus/src/broker.mjs`, a `messages` read verb only
- `packages/cli/src/cli.mjs`, `talk` and `inbox` only
- `packages/webui/src/serve.mjs` (`BUS_VERBS`),
`packages/webui/src/public/bus.js`, `bus.css` if needed
- `packages/bus/README.md`, `packages/cli/README.md`,
`packages/webui/README.md`
- tests under `packages/bus/tests/`, `packages/cli/tests/` and
`packages/webui/tests/`
- `agents/rocko/work/queue-<row>/`
### What ships
- A broker `messages` read verb for the human and the Console's reader:
messages to the human, newest first, with `limit` (default 50, at
most 200), `after` for paging, and whether each is read. Reading it
marks nothing.
- `mosaic talk --follow`: after the send, it keeps printing each message
to the human as it arrives, marking it read as `talk` does today,
until Ctrl-C. `mosaic follow` does the same without sending. Without
the flag, `talk` is unchanged.
- `mosaic inbox` lists unread messages to the human under the
decisions, without marking them read.
- A Messages page in the Console, refreshing like the other bus pages,
shows every message to the human with its sender, class, time, read
state and a trail link. It marks nothing, so `talk` still prints each
one. The nav shows the unread count.
- Tests: a message with no `in_reply_to` arriving after a `talk`
returns is printed by `talk --follow` and by `follow`, listed by
`inbox` and shown in the Console; nothing the Console reads is marked
read; the verb's paging and refusals.
Suites: the bus, cli and webui node suites, and every
`scripts/test-*.sh`.
### Out of scope
Pushing messages to the browser (polling stays). Marking messages read
from the Console. Messages between roles.
### Gate
Dewey approves on the row's issue, naming the candidate manifest. The
suites above pass on Sage's gate rerun. Sage notifies Mos before the
landing; it is live after the bus and Console restart Mos approves.
## The Console's Board shows the stack's seats and a sign-out
### Problem
The Console's Board is the machine scan the old board server serves at
`127.0.0.1:7331` (`packages/webui/src/serve.mjs:8`, proxied as
`/api/board`). It lists tmux and T3 sessions. The stack's own seats
(the PM, coder and reviewer) appear only on the Agents page
(`packages/webui/src/public/bus.js:410-415`), and a message to them
only from the Inbox page's "Message a role" form (`bus.js:270`). In
the test Jason saw the fleet's seats and not the stack's (findings
fault 8, P19 #231), and he approved hiding the machine sessions.
Jason also reports he signs in to mosaic.woltje.com and then can't see
updated info or interact (Mos sage-0105). Checked 2026-10-12:
- The edge admits the Console. ops-01 read the outpost log: forward-auth
302s only from 19:28:16Z to 19:29:26Z, after a pod replacement at
19:28:07Z, then 225 browser 200s and no 302 to 19:48:25Z (Mos
sage-0106). The Console has no websocket; every page polls with
`fetch`.
- The Board's data is current: the scan at 7331 answered in 1.3 s with
`generatedAt` 2026-10-12T19:49:24Z, 44 sessions, projects
`mosaic-stack` and `fleet`, all machine sessions.
- The running Console started at 19:05:38Z, before row 81 (c9a5650e)
landed, so it shows no reply to a web send. Its log has no send line
since then.
So the Console works as built, and what Jason needs from it isn't
there: the stack's seats aren't on the Board, the send is on another
page, the replies aren't deployed, and messages the PM starts never
show (the row above).
During the 19:28 sign-in loss every Console API fetch got a 302 to the
sign-in origin (the same answer an unauthenticated
`GET https://mosaic.woltje.com/api/board` gets). A fetch that follows a
redirect across origins fails with Firefox's "NetworkError when
attempting to fetch resource", which the Board showed earlier today.
The Console keeps the last data and retries every 10 s, failing the same
way until the page is reloaded (`app.js:290-291`, `bus.js:31,42`). A
pod replacement will do this again.
### Owner and reviewer
Owner: Filbert. Reviewer: Darkwing.
### Files owned
- `packages/webui/src/public/app.js`, `bus.js`, `index.html`,
`app.css`
- `packages/webui/src/serve.mjs`, only if the Board needs a new route
- `packages/webui/README.md`
- tests under `packages/webui/tests/`
- `agents/filbert/work/queue-<row>/`
### What ships
- The Board's first section lists the stack's held roles from the bus
`agents` read, including claims with no address, each with its state
and a Message action that opens the send form addressed to that role.
- The machine scan's sessions sit behind a "Show machine sessions"
toggle, off by default, kept in the page's settings like the other
Board filters.
- Every Console fetch uses `redirect: 'manual'`. A redirect answer
(`opaqueredirect`) stops the refresh and shows one line: signed out,
reload the page to sign in. It doesn't show a NetworkError or stale
data as current.
- Tests: the Board with held roles and no machine sessions, a claim
with no address, the toggle, the Message action's role, and a
redirect answer on a Board read, a bus read and a send.
Suites: the webui and control-board node suites, and every
`scripts/test-*.sh`.
### Out of scope
The edge's sign-in lifetime, which is ops-01's through Mos. Removing
the machine scan. A Board for other businesses.
### Gate
Darkwing approves on the row's issue, naming the candidate manifest.
The suites above pass on Sage's gate rerun. Live after the Console
restart Mos approves.