feat(webui,conversation): S5 WebUI views and CHAT-03 follow-ups (row 40, #1522)
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]>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Slice 1 S5: Gate E script (row 40, #1522; row 5, #1507)
|
||||
|
||||
Written 2026-10-09T23:28Z by Dewey. This replaces the draft in
|
||||
`SLICE1-VIEWS.md` section 4, now that S3 and S4 have landed. Gate E is
|
||||
Jason's: the demonstration with all seats, then his workday ruling (round 3,
|
||||
7B). Live cutover needs its own approval. Model calls during the
|
||||
demonstration are Jason's to start; no seat runs them for discovery.
|
||||
|
||||
## What is ready, and what waits
|
||||
|
||||
| Step | Needs | State on 2026-10-09 |
|
||||
|---|---|---|
|
||||
| 1 Console, board and Agents | S4 human CLI, a bus host | ready |
|
||||
| 2 A task appears in Tasks | S3 poller and Vikunja (tasks.mosaicstack.dev, project 32) | ready; the PM request itself waits on S6 |
|
||||
| 3 A decision through the inbox | S4 `mosaic decide` | ready |
|
||||
| 4 Trail to review and close | S2 trail, S3 events | ready |
|
||||
| 5 A conversation through CHAT-03 | the I3 seal and environment (this row); the controller entry point for the live PM session (S6) | the library is ready; a live session waits on S6 |
|
||||
| 6 Workday ruling | all of the above | Jason |
|
||||
|
||||
Nothing in `packages/` constructs a `Controller` outside the tests yet.
|
||||
S6 is where the stack launches the PM session; this row makes the controller
|
||||
safe to point at real Pi (the seal covers the command, the environment is
|
||||
an explicit list).
|
||||
|
||||
## Script
|
||||
|
||||
1. Start the bus host, the board and the Console, one terminal each:
|
||||
|
||||
```sh
|
||||
scripts/mosaic bus start mosaic-stack
|
||||
node packages/control-board/src/cli.mjs serve
|
||||
node packages/webui/src/cli.mjs serve
|
||||
```
|
||||
|
||||
The Console prints `Bus: the running bus host's business`. Open
|
||||
http://127.0.0.1:7330/. The board shows the seats. Agents shows each held
|
||||
role with its holder and harness; the gap labels say what the Q1 module
|
||||
doesn't return yet.
|
||||
2. Send the PM a one-sentence request (with S6: `mosaic talk`). Watch the
|
||||
task appear in Tasks with its requirement id within one poll. Open it:
|
||||
the snapshots say whether the stack wrote it or Vikunja was changed after.
|
||||
Edit the task in Vikunja and watch the badge change on the next poll.
|
||||
3. A gated decision reaches the inbox and the DM. Read it in Console, Copy
|
||||
the `mosaic decide <id> <key>` line and run it in a terminal (it asks for
|
||||
confirmation unless `--yes`). The inbox row closes on the next refresh,
|
||||
and the decision page shows the resolution.
|
||||
4. From the task page, follow "Trail with filters" through review and close.
|
||||
Each event names who did it; a decision link goes back to the inbox page.
|
||||
5. Drive a conversation through CHAT-03: connect the mediated terminal
|
||||
(`node packages/conversation/src/terminal.mjs --socket <path>`), watch as
|
||||
an observer, take control with Ctrl-T, send, then let another client take
|
||||
it back. The composer clears on each transfer.
|
||||
6. Use Console for the rest of the workday, then rule on it. Pass is Jason's
|
||||
say-so, not a test result.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Browser runs against an in-process broker with real broker rows:
|
||||
`packages/webui/tests/bus-browser.test.mjs`, screenshots under
|
||||
`WEBUI_EVIDENCE`.
|
||||
- The live run's screen captures, taken during the demonstration and kept
|
||||
under `agents/dewey/work/wui/evidence/`.
|
||||
- Anything that sent Jason to the board's own page, a terminal or Vikunja
|
||||
instead of Console goes in `docs/plans/DEFERRED.md`.
|
||||
|
||||
## Rollback
|
||||
|
||||
Stop the WebUI. The board at 7331 and the CLI are unchanged. Revert the S5
|
||||
commit to remove the views; there is no data to migrate. Decisions resolved
|
||||
with `mosaic decide` belong to the bus and are not rolled back.
|
||||
@@ -213,6 +213,9 @@ whatever S6 records, through `packages/conversation`.
|
||||
|
||||
## 4. Gate E
|
||||
|
||||
The script for the demonstration is now `S5-GATE-E.md` (2026-10-09).
|
||||
This section stays as the design draft it replaced.
|
||||
|
||||
Round 3, 7B: Gate E is shown during this step, not separately. The brief:
|
||||
an interactive demonstration with all seats, then Jason's workday ruling.
|
||||
Live cutover still needs its own approval.
|
||||
|
||||
@@ -56,4 +56,4 @@ Brief: `docs/plans/2026-10-04_slice-1.md`, S5. S5 follows S4. Until then only de
|
||||
| --- | --- | --- | --- | --- |
|
||||
| S5-D1 | Design note: routes, the four views, data sources, Gate E draft, open questions. Evidence: SLICE1-VIEWS.md. | Schema v3 (7ed83178) | done | Revision 2 records lead decision 56 (Q1 to Q5) and the stale-read finding (section 8). Revision 3 records v3b (lead decision 60), the Q1 reshape and the gap list (section 9). |
|
||||
| S5-D2 | Console mockup of inbox, tasks, agents and trail from fixture rows in the Q1 module's shapes; checked at the usual widths, palettes and modes. | S5-D1 | in review | `mockups/slice1/`; `checks/slice1-verify.mjs`: 15 checks, 0 failed, 2 not verified (forced colors, screen reader). Fixtures are raw schema v3b (179ffe35) rows; check 15 agrees with `task_current` and `tasks_open` on every task (lead decision 60). `q1.js` stands in for the four reader verbs, and check 16 matches it against the reader extracted from the S2c commit d27042fa (203 rows). S2b refused an agent message citing its decision; S2c (row 44, #1526, lead decision 65) restores it, and the probe confirms it on d27042fa (SLICE1-VIEWS.md section 10). The fixture carries the `message.send` `action.allowed` event for messages 101 and 102. Gaps for Rocko: SLICE1-VIEWS.md section 9. Next: switch to Rocko's pinned fixture when it arrives. Gaps went to S4, S6 and S3 (lead decision 63). |
|
||||
| S5-B1 | Build in `packages/webui`, `packages/conversation`, `packages/control-board`; I3 follow-ups; Gate E. | S4 done, S6 for the PM session | blocked | Wait for S4. |
|
||||
| S5-B1 | Build in `packages/webui`, `packages/conversation`, `packages/control-board`; I3 follow-ups; Gate E. | S4 done, S6 for the PM session | in progress | Row 40 in progress since 2026-10-09 (Sage). Views: `/api/bus/*` reads through the human transport, read-only, Copy for `mosaic decide`. CHAT-03: the seal covers the engine command, the engine environment is an explicit list, `escalating` clears after a throw, input after Ctrl-T or Ctrl-O waits for it (lead decision 56 Q5). Gate E script: `S5-GATE-E.md`; steps 2 and 5 wait on S6 for the live PM session. |
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# Slice 1 S5 mutation check (row 40, #1522)
|
||||
|
||||
Run 2026-10-09 by Dewey, finished 2026-10-10T00:01Z. Each mutant ran on a
|
||||
fresh scratch copy (`~/dewey-scratch/s5/mut`) of `packages/conversation`,
|
||||
`control-board`, `discord`, `seat`, `package.json`, `package-lock.json` and
|
||||
`docs/plans/chat-01`, with `node_modules` symlinked. Every mutant got the
|
||||
full conversation suite. The working tree was never mutated. The tools are
|
||||
`~/dewey-scratch/s5/mut-tools/` (`mutants.py`, `run.sh`).
|
||||
|
||||
| Mutant | Change | Result | Killed by |
|
||||
|---|---|---|---|
|
||||
| base | none | 157/157 | (baseline) |
|
||||
| esc | the force stop no longer clears `escalating` when the fence throws | killed | races: a force stop whose fence throws leaves no escalation flag behind |
|
||||
| seal | the seal check at bind always passes | killed | N24b |
|
||||
| keys | the envKeys check never finds a bad name | killed | N24b, N24 |
|
||||
| envall | the engine environment copies every name in the source | killed | N24b |
|
||||
| credname | envKeys skips the credential-name test | killed | N24b |
|
||||
| restart | `start()` skips the seal check | killed | N24b |
|
||||
| hold | no action holds input | killed | terminal: Ctrl-T then Enter in one chunk |
|
||||
| holdreload | only Ctrl-T holds input | killed | the same test's Ctrl-O case |
|
||||
| throwdrain | an action that throws drops the input held behind it | killed | terminal: an action that throws still releases the input held behind it |
|
||||
| manager | ScopeLauncher passes the engine environment without `MANAGER_ENV` | killed | K19 |
|
||||
|
||||
Two fixes came out of the runs:
|
||||
|
||||
- `manager` survived the first run, since no test launched a scope with only
|
||||
the engine environment (the cohort fixtures pass the whole test
|
||||
environment). K19 now launches `/bin/sleep` through ScopeLauncher with
|
||||
`engineEnv([])` and checks that the engine's environment names come only
|
||||
from ENGINE_ENV, MANAGER_ENV and the names systemd and the shim's shell
|
||||
set (`INVOCATION_ID`, `PWD`, `SHLVL`).
|
||||
- Under `seal` and `restart`, N24b failed but then held its controller's
|
||||
socket open, so `turns.test.mjs` ran until the 900 s timeout. The
|
||||
bind-time part of N24b now closes the controller in `finally`, and a
|
||||
regression there fails in seconds.
|
||||
|
||||
The first full run's baseline failed 2 tests because the copy lacked
|
||||
`docs/plans/chat-01/contracts.schema.json`. The runner now copies it.
|
||||
Results from that run were discarded.
|
||||
|
||||
## Round 2 (Filbert's comment 26993)
|
||||
|
||||
The same runner, the round 2 candidate, and every mutant from round 1, plus
|
||||
three for the round 2 changes. Each mutant ran the full conversation suite
|
||||
on a fresh scratch copy.
|
||||
|
||||
| Mutant | Change | Result | Killed by |
|
||||
|---|---|---|---|
|
||||
| base | none | 159/159 | (baseline) |
|
||||
| noapprove | `--no-approve` removed from SEAL_FLAGS | killed | smoke: sealed, pinned Pi ignores a trusted project's .pi resources |
|
||||
| queuecatch | `key()` chains on the queue without catching the previous chunk's throw | killed | terminal: after an action throws, later input still runs |
|
||||
| inputcatch | `input()` rethrows instead of setting the status line | killed | the same test |
|
||||
| esc | as round 1 | killed | races: a force stop whose fence throws leaves no escalation flag behind |
|
||||
| seal | as round 1 | killed | N24b |
|
||||
| keys | as round 1 | killed | N24b, N24 |
|
||||
| envall | as round 1 | killed | N24b, K19 |
|
||||
| credname | as round 1 | killed | N24b |
|
||||
| restart | as round 1 | killed | N24b |
|
||||
| hold | as round 1 | killed | terminal: Ctrl-T then Enter in one chunk; after an action throws |
|
||||
| holdreload | as round 1 | killed | terminal: Ctrl-T then Enter in one chunk (Ctrl-O case) |
|
||||
| throwdrain | as round 1 | killed | terminal: an action that throws still releases the input held behind it; after an action throws |
|
||||
| manager | as round 1 | killed | K19 |
|
||||
|
||||
`noapprove` is checked against the real pinned Pi 0.85.1 with no model
|
||||
call. The test's control runs the same trusted project with `--approve`
|
||||
after the seal, and that offers `skill:probe`, so the sealed assertion
|
||||
can see a load when one happens.
|
||||
|
||||
## Round 3 (Darkwing's comment 27001, Filbert's comment 27005)
|
||||
|
||||
The same runner on the round 3 candidate. The terminal mutants were rewritten for the new `#run`/`#feed` code, and the rest are as in round 2. Each mutant ran the full conversation suite on a fresh scratch copy.
|
||||
|
||||
| Mutant | Change | Result | Killed by |
|
||||
|---|---|---|---|
|
||||
| base | none | 161/161 | (baseline) |
|
||||
| holdowner | every run drains `held`, as in round 2 (T1) | killed, 160/161 | terminal: input held behind Ctrl-T waits for that takeover while an earlier action is still pending |
|
||||
| heldcatch | held input's `key()` returns the holder's promise (N4) | killed, 160/161 | terminal: input() reports an error when it happens … |
|
||||
| chunkstop | one try around the chunk's actions, so a throw skips the rest of the chunk | killed, 160/161 | the same test |
|
||||
| reportlate | `input()` catches at the end, as in round 2 (N4) | killed, 160/161 | the same test |
|
||||
| reportdrop | `input()`'s error is thrown and swallowed, never shown | killed, 159/161 | terminal: after an action throws, later input still runs; input() reports an error when it happens |
|
||||
| throwdrain | a throw leaves `#run` before the held input | killed, 158/161 | terminal: an action that throws still releases the input held behind it; after an action throws; input() reports an error when it happens |
|
||||
| queuecatch | as round 2 | killed, 160/161 | terminal: after an action throws, later input still runs |
|
||||
| noapprove | as round 2 | killed, 160/161 | smoke: sealed, pinned Pi ignores a trusted project's .pi resources |
|
||||
| esc | as round 1 | killed, 160/161 | races: a force stop whose fence throws leaves no escalation flag behind |
|
||||
| seal | as round 1 | killed, 160/161 | N24b |
|
||||
| keys | as round 1 | killed, 159/161 | N24b, N24 |
|
||||
| envall | as round 1 | killed, 159/161 | N24b, K19 |
|
||||
| credname | as round 1 | killed, 160/161 | N24b |
|
||||
| restart | as round 1 | killed, 160/161 | N24b |
|
||||
| hold | as round 1 | killed, 157/161 | terminal: Ctrl-T then Enter in one chunk; input held behind Ctrl-T waits for that takeover while an earlier action is still pending; after an action throws; input() reports an error when it happens |
|
||||
| holdreload | as round 1 | killed, 160/161 | terminal: Ctrl-T then Enter in one chunk (Ctrl-O case) |
|
||||
| manager | as round 1 | killed, 160/161 | K19 |
|
||||
|
||||
Round 2's `inputcatch` (`input()` rethrows) has no counterpart here: `input()` no longer catches a rejection, and with a reporter `#run` never throws. `reportdrop` and `reportlate` cover its two halves.
|
||||
|
||||
WebUI (Darkwing's note 1). `run.sh` copies only the conversation packages, so these ran `packages/webui/tests/bus.test.mjs` on a scratch copy of the packages it imports:
|
||||
|
||||
| Mutant | Change | Result | Killed by |
|
||||
|---|---|---|---|
|
||||
| base | none | 7/7 | (baseline) |
|
||||
| Mm | `humanCall`'s timeout rejects without `child.kill('SIGKILL')` | killed, 6/7 | humanCall kills a transport that runs past its timeout |
|
||||
| Mp | `serve --business` takes any value | killed, 6/7 | serve refuses a --business value that is not a business id |
|
||||
|
||||
Correction: the first Mm run hung, because the surviving child held the test process open. I stopped the child by PID. The test now kills a surviving child on cleanup, and the rerun failed the assertion in 1.5 s. Under Mp, `serve` started a real server on port 0 until spawnSync's 10 s timeout ended it.
|
||||
Reference in New Issue
Block a user