bus: review.request reports whether a reviewer holds the role (#1599)

Row 105. Built by a Haiku subagent under Researcher (decision 129),
packet agents/researcher/work/queue-105/r1/, candidate manifest
cd6d5eb3e4093ac157f63d05cb639d243d76c6bde1a03e78efb8f29e191b6b44.
Filbert approved on #1599, comment 28247.

The review.request reply and the review.requested event carry held,
the run id holding the reviewer role or null. The request_review tool
description says what null means. The broker change is live only at
a bus restart.

Sage's gate rerun on 79e126be0 with rows 101 and 105 applied, Docker
up: node suites bus 128, business 67, cli 146, control-board 124,
conversation 182, discord 178, harness 70, ledger 78, mosaic 69,
queue 155, runs 43, seat 109, tasks 92, webui 108; scripts auth 15,
conductor 17, config 24, discord 66, extension-package 18,
foundation 44, queue 28, release 14, task 98. All pass, 0 fail.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 16:26:12 -05:00
co-authored by Claude Opus 5.5
parent 056a20397d
commit 3a1e11b83e
5 changed files with 37 additions and 5 deletions
+26 -1
View File
@@ -106,7 +106,7 @@ test('review.request names the latest pushed commit and sends the reviewer a REV
const [e] = events('review.requested');
assert.equal(e.id, r.request);
assert.equal(e.subject, TASK);
assert.deepEqual(JSON.parse(e.body), { task_ref: TASK, project: 'stack', ref: 'work/vikunja-1-2', commit: A, to: 'reviewer', message: r.message });
assert.deepEqual(JSON.parse(e.body), { task_ref: TASK, project: 'stack', ref: 'work/vikunja-1-2', commit: A, to: 'reviewer', message: r.message, held: 'reviewer-run' });
const m = store.get('SELECT * FROM messages WHERE id=?', r.message);
assert.equal(m.to_role, 'reviewer');
assert.equal(m.from_role, 'coder');
@@ -115,6 +115,31 @@ test('review.request names the latest pushed commit and sends the reviewer a REV
assert.match(m.body, /please$/);
});
// Row 105 (#1599): the reply and the event say which run holds the reviewer role when the request is
// routed, or null when nobody holds it. A null request waits for the next claim, as before.
test('review.request says which run holds the reviewer role, or null, and a null request waits for a claim', (t) => {
const { b, store, call, push, events } = setup(t);
const routed = (mid) => store.all("SELECT op, holder_run FROM deliveries WHERE message=? AND op='routed' ORDER BY seq", mid).map((r) => ({ ...r }));
push(A);
const held = call('coder', 'review.request', { task_ref: TASK, commit: A, to: 'reviewer' });
assert.equal(held.held, 'reviewer-run');
assert.equal(JSON.parse(events('review.requested')[0].body).held, 'reviewer-run');
assert.deepEqual(routed(held.message), [{ op: 'routed', holder_run: 'reviewer-run' }]);
// The reviewer releases the role. The latest role_claims row is a release, so nobody holds it.
call('reviewer', 'role.release');
const waiting = call('coder', 'review.request', { task_ref: TASK, commit: A, to: 'reviewer' });
assert.equal(waiting.held, null);
assert.equal(JSON.parse(events('review.requested')[1].body).held, null);
assert.deepEqual(routed(waiting.message), [{ op: 'routed', holder_run: null }]);
// A run that claims the role is routed the waiting request, as #routeWaiting did before row 105.
const next = b.bindLaunch({ business: 'demo', role: 'reviewer', run: 'reviewer-2', harness: 'pi' });
b.request(next, { verb: 'role.claim', args: {} });
assert.deepEqual(routed(waiting.message), [
{ op: 'routed', holder_run: null },
{ op: 'routed', holder_run: 'reviewer-2' },
]);
});
test('review.request refuses a commit that isn\'t the latest push, a non-reviewer and a role without the action', (t) => {
const { call, push, events } = setup(t);
assert.throws(() => call('coder', 'review.request', { task_ref: TASK, commit: A, to: 'reviewer' }), /unknown-commit/);