Files
stack/docs/plans/2026-10-10_design-implementation.md
T
jason.woltjeandClaude Opus 5.5 f824fcc9e5 docs(plans): design implementation brief, lead decisions 80 and 81
Brief for rows 53 to 61 implementing docs/design (Jason's directive via
Mos, DECISIONS 1a312ff). Decision 80 records the Q14 window, rev7 item 6
checks and the freeze; decision 81 the row shape and the design's open
decisions.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:35:37 -05:00

410 lines
13 KiB
Markdown

# Design implementation: console and terminal rows (2026-10-10)
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`.
Jason accepted the design direction and handed the queue to Sage (Mos
relay, DECISIONS 1a312ff: "That design can be immediately implemented by
the Mosaic Stack agents ... I am going to leave this in your power").
Lead decision 81 records the shape. The design package is
`docs/design/` at 811e7ba5. Every row below reads
`docs/design/IMPLEMENTING.md` first; its sections "Strings to keep
exactly", "Boundaries" and "Acceptance" apply to every row and are not
repeated here.
Two rules apply to every row in this file.
- The Q14 freeze holds `packages/bus`, `packages/tasks`, `packages/cli`,
`scripts/bus-service.sh` and `scripts/mosaic` until ops-01 reports the
Q14 hold ended. A row that needs one of those paths doesn't start
before then. Importing from them is fine; changing them is not.
- No commit to the checkout, queue moves included, from
2026-10-11T15:00Z until ops-01 reports the hold ended. Work in your own
scratch tree during that window and commit nothing.
Design questions go to Sage, who relays them to the design session
(tmux `mosaic-design`) and back.
## Console tokens and shell restyle
### Problem
The console in `packages/webui` sets its colours inline: `theme()` in
`packages/webui/src/public/app.js` loops `setProperty` over `brand.js`
values. It has no shared component set and no loading, empty, error or
refusal states. The design (`docs/design/tokens.css`, `icons.svg`,
`mosaic-stack-design.html`) defines the tokens, icons, components and
five view states, and `IMPLEMENTING.md` sections "Tokens", "Icons and
the mark" and "Components" give the adoption steps.
### Owner and reviewer
- Owner: Dewey.
- Reviewers: Darkwing and Filbert.
### Files owned
- `packages/webui/src/public/` (not `shared/`, which other packages read)
- `packages/webui/src/serve.mjs`, only to add the new static files to the
`files` map
- `packages/webui/tests/`
- `packages/webui/README.md`
- `agents/dewey/work/queue-53/` for evidence
`docs/design/` is read-only for this row. Copy `tokens.css` and
`icons.svg` into `src/public/`, and add a test that fails when the copy
differs from `docs/design/`.
### What ships
- `tokens.css` served through the `files` map; `theme()` stops setting
properties inline. `data-palette` and `data-mode` stay. Add a System
choice that removes `data-mode`. The localStorage key stays
`mosaic-console-appearance`. Harbor following the system setting is
the default (decision 81).
- `--r` 6px and `--r-lg` 10px, the type scale from "Tokens", and
tabular numbers in tables.
- JetBrains Mono 400, 500 and 700 self-hosted, from the official
JetBrains release only, with each file's sha256 and the OFL text
committed beside it. If the seat can't fetch the release, ship the
system monospace stack and say so in the packet. Sage files the font
as a follow-up.
- The icon sprite, with the mark in one component and the placeholder
Relay mark.
- The command bar, section list, dense table, inspector, status mark,
class chip, copy command, toast, command palette (Ctrl+K) and not
found.
- Five states (normal, loading, empty, error with stale data, refusal)
on Board, Inbox, Tasks, Agents and Trail. Restyle only. No new data,
endpoints or writes.
- Tests: `node --test tests/` in `packages/webui` green, the browser
checks from "Acceptance" (no script errors, no sideways scroll at
400px, keyboard path, visible focus), seeded empty, stale-error and
refusal states, and the string grep test.
### Out of scope
New views (row 54), the terminal app (row 55), any backend read
(rows 56 to 61), Decision Seen from the web (decision 81: not in v1),
and the control board's own page on port 7331.
### Gate
Darkwing and Filbert approve on the row's issue, each naming the
candidate manifest. On Sage's gate rerun, `packages/webui` tests,
`node docs/design/tools/build-tokens.mjs --check` and every
`scripts/test-*.sh` are green.
## Read-only console views: Queue, Business and Settings
### Problem
The console can't show the queue, the business file or settings. The
data exists in modules with no endpoint: `list` and `show` in
`packages/queue/src/store.mjs`, `loadBusiness` in
`packages/business/src/business.mjs`, `loadRole` and `resolveInstance`
in `packages/business/src`, and `readNotifyConfig` in
`packages/cli/src/cli.mjs`.
### Owner and reviewer
- Owner: Dewey, after row 53 (both change `app.js` and the shell).
- Reviewers: Darkwing and Filbert.
### Files owned
- `packages/webui/src/` (not `public/shared/`)
- `packages/webui/tests/`
- `packages/webui/README.md`
- `agents/dewey/work/queue-54/`
No change to `packages/queue`, `packages/business` or `packages/cli`.
If a module lacks a read the view needs, stop and tell Sage.
### What ships
- `GET` JSON endpoints `/api/queue`, `/api/queue/<id>`,
`/api/business` and `/api/settings`. Keep the existing CSP, Host and
Origin checks. No write, no network call, no new dependency.
- Views `#/queue`, `#/business` and `#/settings`, with all five states.
A missing or invalid business file shows the refusal state with the
module's own refusal text.
- Secrets as metadata only. Show service, account, role and expiry. No
value, token or file path appears in any response or log. Notifier
settings show binding names only, never a Discord channel, guild or
user id. A test asserts each of these on a seeded fixture that holds
such values.
- Settings: appearance (the row 53 control), notifications (names only)
and about (loopback address, `RELEASE`). Read-only apart from
appearance.
- Queue rows show state, owner, reviewers and the brief link. Rows move
only through `queue move`; the view shows that command, not a button.
- Tests as in row 53.
### Out of scope
The Ledger view: the ledger CLI calls Gitea and reads the T3 database,
so it needs a cached report first and gets its own row later. Runs and
releases (row 56). Any backend read for the bus (rows 57 to 61).
### Gate
As row 53, plus the secret and id assertions above passing.
## Full-screen terminal app
### Problem
`mosaic` with no argument exits 4 with usage. The design specifies a
full-screen terminal app (`IMPLEMENTING.md` "The full-screen terminal
app") built on the conversation `Terminal` class
(`packages/conversation/src/terminal.mjs:54`).
### Owner and reviewer
- Owner: Darkwing.
- Reviewers: Dewey and Filbert.
- Starts after ops-01 reports the Q14 hold ended (`packages/cli` is
frozen). Rebase on row 41 if it has landed by then.
### Files owned
- `packages/cli/src/` (new app modules, and the no-argument entry)
- `packages/cli/tests/`
- `packages/cli/README.md`
- `docs/TOOLS.md`, the `mosaic` entry
- `agents/darkwing/work/queue-55/`
### What ships
- No-argument `mosaic` on a TTY opens the app (decision 81). Not on a
TTY it keeps today's usage text and exit 4. In an agent run it exits 3
through `transport.mjs`.
- Screens Inbox, Tasks, Agents, Trail and Help, with keys c, i, t, a, r,
j, k, `:`, `?` and `q`. Decide shows and runs the existing
`mosaic decide` flow with its strings unchanged.
- 16 ANSI colours, `NO_COLOR` honoured, fits 80x24, designed at 120x36.
- No new dependency.
- Tests: every screen fits 120 columns and 80x24, `NO_COLOR` output has
no escape codes, an agent-run environment exits 3, a non-TTY exits 4
with the usage text, and the string grep test.
### Out of scope
Talk and stop (after row 41), Decision Seen (needs its own CLI verb
row), the web console.
### Gate
Dewey and Filbert approve on the row's issue naming the candidate.
`packages/cli` tests and every `scripts/test-*.sh` are green on Sage's
gate rerun.
## Runs and releases reader module
### Problem
The run and release readers live inside `scripts/mosaic-task.mjs` and
`scripts/release.sh` and aren't exported, so the console can't show runs
or the active release.
### Owner and reviewer
- Owner: Rocko.
- Reviewers: Darkwing and Filbert.
### Files owned
- a new `packages/runs/` (module, tests, README)
- `scripts/mosaic-task.mjs`, only to import the extracted readers
- `agents/rocko/work/queue-56/`
### What ships
- A read-only module that lists runs under `<dataRoot>/runs/`, reads one
run's `result.json` and reads the release pointer and activation log
under `<dataRoot>/state/`. It never writes, prunes or follows a
symlink out of the data root.
- `mosaic-task.mjs list` and `show` use it, and their output is
byte-identical before and after on a seeded data root.
- Tests in `packages/runs` and `scripts/test-task.sh` green.
### Out of scope
The `#/runs` view (a later row on this module), `release.sh` behaviour,
and pruning.
### Gate
Darkwing and Filbert approve naming the candidate. `packages/runs`
tests and every `scripts/test-*.sh` are green on Sage's gate rerun, with
the byte-identical output check in the packet.
## Bus read: decisions routed to roles and recent decisions
### Problem
`inbox` returns open decisions for the caller's role only. The design's
Inbox tabs "Routed to roles" and "Recent" need a reader op for decisions
routed to other roles and for closed ones.
### Owner and reviewer
- Owner: Filbert, after row 41 (S6 rewrites `packages/bus`).
- Reviewers: Darkwing and Dewey.
### Files owned
`packages/bus/`, `packages/webui/src/bus.mjs` and its tests, and
`agents/filbert/work/queue-57/`.
### What ships
A reader op and its webui endpoint, read-only, with tests. The reader
session's authority doesn't widen: it reads what a human reader may
read today, and a test shows a role session can't use it to read
another role's open decisions.
### Out of scope
Decision Seen and any write.
### Gate
Darkwing and Dewey approve naming the candidate; bus, webui and every
`scripts/test-*.sh` green on Sage's gate rerun.
## Bus read: task priority and requirement
### Problem
Priority isn't in `task_current.fields`, and the requirement sits only
in the `task.created` event body, so the Tasks table can't show either.
### Owner and reviewer
- Owner: Darkwing, after row 41.
- Reviewers: Dewey and Filbert.
### Files owned
`packages/bus/`, `packages/tasks/`, the webui Tasks endpoint and tests,
and `agents/darkwing/work/queue-58/`.
### What ships
Both fields in the task read model, with a projection rebuild test, and
the two columns in the Tasks view.
### Out of scope
Field writers (row 61).
### Gate
Dewey and Filbert approve naming the candidate; bus, tasks, webui and
every `scripts/test-*.sh` green on Sage's gate rerun.
## Bus read: agent state per role
### Problem
The control board has state and Input needed per seat; the bus has
nothing per role. The Agents view needs both per role.
### Owner and reviewer
- Owner: Filbert, after row 41.
- Reviewers: Darkwing and Dewey.
### Files owned
`packages/bus/`, `packages/control-board/` (read side only), the webui
Agents endpoint and tests, and `agents/filbert/work/queue-59/`.
### What ships
A seat-to-role mapping read from committed data, or state on the bus.
The packet says which and why. The Agents view shows the state mark and
Input needed per role. Read-only.
### Out of scope
Launch budget and stop (after row 41, a later row).
### Gate
Darkwing and Dewey approve naming the candidate; bus, control-board,
webui and every `scripts/test-*.sh` green on Sage's gate rerun.
## Bus read: credential status on the broker
### Problem
`Credentials.status()` (`packages/bus/src/credentials.mjs:118`) isn't
exposed on the broker, so the console can't show credential health.
### Owner and reviewer
- Owner: Filbert, after row 41.
- Reviewers: Darkwing and Dewey.
### Files owned
`packages/bus/`, the webui endpoint and tests, and
`agents/filbert/work/queue-60/`.
### What ships
A broker read op returning service, account, role and expiry only. A
test on a seeded store holding a value, a token and a path shows none of
them in the op's output or the host log.
### Out of scope
Any credential write, rotation or new credential.
### Gate
Darkwing and Dewey approve naming the candidate; bus, webui and every
`scripts/test-*.sh` green on Sage's gate rerun.
## Task field-writer table as data
### Problem
Which actor may write which task field is prose in
`docs/plans/2026-10-04_slice-1.md` lines 62-72. The task inspector
needs it as data.
### Owner and reviewer
- Owner: Darkwing, after row 41.
- Reviewers: Dewey and Filbert.
### Files owned
`packages/tasks/`, the webui Tasks inspector and tests, and
`agents/darkwing/work/queue-61/`.
### What ships
The table as a committed data file with a schema, a test that the
writers the code enforces match it, and the inspector showing who may
write each field. The slice 1 prose stays the reviewed source; if the
code and prose disagree, stop and tell Sage.
### Out of scope
Changing who may write a field.
### Gate
Dewey and Filbert approve naming the candidate; tasks, webui and every
`scripts/test-*.sh` green on Sage's gate rerun.
## After row 41: Talk, launch budget, stop and Library
Not a queue row yet. Sage briefs these when row 41 lands, because they
read what S6 creates (`packages/harness`, `session.launched`,
`launch.revoke`). The same goes for the Ledger view's cached report and
a Decision Seen CLI verb.