feat(bus): decisions routed to roles and recent decisions (#1546, row 57)
The broker gains the reader verb `decisions` with `{list: 'roles' |
'recent'}`: the open decisions routed to each role, and the last 50
decisions (RECENT). views.mjs exposes it in the Q1 client module, and
webui serves `GET /api/bus/decisions?list=roles|recent`. Any other list
is 400 and never reaches the bus. No Inbox tab uses the route yet; the
tabs are the design rows' work. The bus and webui READMEs list the verb,
the route and who may call it.
Filbert built it (agents/filbert/work/queue-57). Round 1 approve from
Darkwing (27290) and Dewey (27300) on manifest af3b03cf, 8 paths. Their
non-blocking notes (no seen-then-resolve test, no webui test of ?list=
before the no-bus 503, test 4 compares fewer fields, roles has no LIMIT,
3 of 14 mutants survived) go to a follow-up row.
Sage's gate on 3c79809c, sequential and teed: node suites bus 80 and
webui 40, 0 failed; test-auth 15, test-conductor 17, test-config 24,
test-discord 66, test-extension-package 18, test-foundation 44,
test-queue 27, test-release 14, test-task 98, all 0 failed.
958668a8..3c79809c touches none of the 8 paths.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
// Slice 1 S5 (#1522): the Console's read of the bus. It runs the S4 human
|
||||
// transport (packages/bus/src/human-cli.mjs, lead decision 70) as a child
|
||||
// with spawn, not spawnSync, so one slow read never stalls the HTTP server.
|
||||
// Only the four verbs of the Q1 module (lead decision 56) are reachable:
|
||||
// the WebUI writes nothing, not even seen (Q4). The bus does the proof; a
|
||||
// Only the four verbs of the Q1 module (lead decision 56) and row 57's
|
||||
// `decisions` read are reachable: the WebUI writes nothing, not even seen
|
||||
// (Q4). The bus does the proof; a
|
||||
// server started inside an agent run gets `human-required` from the broker.
|
||||
|
||||
import { spawn } from 'node:child_process';
|
||||
|
||||
@@ -46,16 +46,22 @@ async function body(req) {
|
||||
return bytes;
|
||||
}
|
||||
// Slice 1 S5 (#1522): GET only, the four Q1 verbs, nothing else (lead decision 56, Q4).
|
||||
const BUS_VERBS = ['inbox', 'tasks', 'agents', 'trail'];
|
||||
// Row 57 (#1546) adds `decisions`, also a read, for the Inbox tabs.
|
||||
const BUS_VERBS = ['inbox', 'tasks', 'agents', 'trail', 'decisions'];
|
||||
const DECISION_LISTS = ['roles', 'recent'];
|
||||
async function busRead(res, bus, verb, search) {
|
||||
let subject;
|
||||
let arg;
|
||||
if (verb === 'trail') {
|
||||
subject = new URLSearchParams(search).get('subject');
|
||||
if (!subjectOk(subject)) return json(res, 400, { error: 'invalid-request', message: 'subject must be a decision id, message id or task ref' });
|
||||
arg = new URLSearchParams(search).get('subject');
|
||||
if (!subjectOk(arg)) return json(res, 400, { error: 'invalid-request', message: 'subject must be a decision id, message id or task ref' });
|
||||
}
|
||||
if (verb === 'decisions') {
|
||||
arg = new URLSearchParams(search).get('list');
|
||||
if (!DECISION_LISTS.includes(arg)) return json(res, 400, { error: 'invalid-request', message: 'list must be roles or recent' });
|
||||
}
|
||||
if (!bus) return json(res, 503, { error: 'not-configured', message: 'the Console has no bus configured' });
|
||||
try {
|
||||
const rows = await bus[verb](subject);
|
||||
const rows = await bus[verb](arg);
|
||||
if (!Array.isArray(rows)) throw new BusReadError('invalid-response');
|
||||
return json(res, 200, { rows, at: new Date().toISOString() });
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user