docs(plans): decisions read follow-up brief after row 57

Darkwing N1/N2 (27290), Dewey survivors recent-closed-first-event and
web-503-first (27300), and Filbert's trail comment note. Owner Filbert;
reviewers Darkwing and Dewey. No roles LIMIT here; paging is the design
row's call.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-11 15:37:54 -05:00
co-authored by Claude Opus 5.5
parent f78ba57d70
commit e5af27e982
@@ -0,0 +1,73 @@
# Bus decisions read: follow-up after row 57 (2026-10-11)
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`
and amends no section of the design-implementation brief. One row.
## Decisions read follow-up: seen-then-resolve, list-before-503 and full-row tests
### Problem
Row 57 (#1546, f78ba57d) added the bus reader verb `decisions` with
`list: 'roles' | 'recent'` and `GET /api/bus/decisions?list=`. Darkwing
(comment 27290) and Dewey (comment 27300) approved on manifest af3b03cf
and left test gaps, none blocking. Filbert's handoff named the same ones.
- Darkwing N1, Dewey mutant `recent-closed-first-event`. No test decision
is marked seen before it closes, so a `closed` taken from the
decision's first `decision_events` row instead of its closing row
passes every test. Test 4 can't catch it either: it finds the trail
event by `row.closed.seq`, and a `seen` row matches just as well. Seen
then resolved is the normal sequence in real use.
- Dewey mutant `web-503-first`. `serve.mjs` checks `?list=` before it
checks for a bus, but the only no-bus test (`bus.test.mjs`, the 503
case) doesn't call the new route. With no bus configured, a bad list
could answer 503 instead of 400 and no test would fail.
- Darkwing N2. Test 4 compares seven columns plus `options`. It doesn't
compare `blocking`, the authorization context, `task_ref`,
`requirement_ref` or `supersedes`, so "each row equals trail" is
narrower than the packet says. Dewey's probe found every column right,
so this guards what already holds.
- Filbert's note. The comment above the `decisions` case in
`packages/bus/src/broker.mjs` says each row is "what trail gives the
same session for that id". Trail gives the decision and its events, so
the comment should say which part the row equals.
### Owner and reviewer
Owner: Filbert. Reviewers: Darkwing and Dewey.
### Files owned
- `packages/bus/src/broker.mjs`, the comment only unless a test exposes a
defect
- `packages/bus/tests/decisions.test.mjs`
- `packages/webui/tests/bus.test.mjs`
- `packages/bus/README.md`, only if the comment fix changes what it says
### What ships
- A test that marks a decision seen, resolves it, and asserts the
`recent` row's `closed.op` is `resolved` and its `closed.seq` is the
resolve event's. Mutant `recent-closed-first-event` fails it.
- In the no-bus webui test, `GET /api/bus/decisions?list=bad` answers
400. Mutant `web-503-first` fails it.
- Test 4 compares the whole `#decisionView` row against the trail
decision, minus the fields the view adds, instead of naming columns.
- The broker comment says exactly what each row equals.
- The packet reruns both named mutants against the candidate and lists
them killed.
### Out of scope
A `LIMIT` on `roles`. Dewey notes it returns every open role decision in
one read. That is fine at slice 1 volumes, and whether the list pages is
the call of the design row that shows it, so this row adds no cap.
`roles` order stays raise order (`seq`), as row 57 documented (Darkwing
N3, Dewey survivor `roles-gated-first`). No behavior change ships here
unless a new test finds a defect, and then the packet says so.
### Gate
Darkwing and Dewey approve on the row's issue naming the candidate
manifest. The bus and webui node suites and every `scripts/test-*.sh`
green on Sage's gate rerun.