bus, harness: decision.raise takes one recommendation key and says which field failed (row 112, #1606)
A recommendation that isn't exactly one option key now refuses invalid-recommendation, checked after the options, instead of sharing invalid-options with bad option lists. The raise_decision tool text says recommendation is one key with the reason in question, and that approvalChoice defaults to yes. The bus README lists the three codes, the field each names and the check order; a malformed option object refuses invalid-request. No schema change. Candidate manifest 013c82c2fd99d23d92f6bed543a788aa04ff97b164019ccb15252ae808b4138e (Darkwing round 2, packetfee89d52f), BASE96656dd21. Approved by Filbert (comment 28383) and Sage (comment 28384). Sage gate rerun atf63fc20e4plus the candidate passed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -155,6 +155,37 @@ test('within-role decisions close atomically and invalid options or blocking omi
|
||||
assert.throws(() => raise(b, c, 'made.up'), /unknown-action/);
|
||||
assert.equal(call(b, c, 'inbox').length, 0);
|
||||
});
|
||||
test('a recommendation that is not exactly one option key refuses invalid-recommendation after the options', (t) => {
|
||||
const { b, agent, store } = setup(t),
|
||||
c = agent('coder');
|
||||
call(b, c, 'role.claim');
|
||||
const count = () => [
|
||||
store.get('SELECT count(*) AS n FROM decisions').n,
|
||||
store.get('SELECT count(*) AS n FROM messages').n,
|
||||
];
|
||||
const before = count();
|
||||
for (const recommendation of ['yes: it matches the direction', 'maybe', undefined])
|
||||
assert.throws(() => raise(b, c, 'prd.approve', { recommendation }), /invalid-recommendation/);
|
||||
const dup = [
|
||||
{ key: 'yes', text: 'a' },
|
||||
{ key: 'yes', text: 'b' },
|
||||
];
|
||||
assert.throws(() => raise(b, c, 'prd.approve', { options: dup, recommendation: 'yes' }), /invalid-options/);
|
||||
assert.throws(() => raise(b, c, 'prd.approve', { options: dup, recommendation: 'yes: a reason' }), /invalid-options/);
|
||||
assert.throws(
|
||||
() => raise(b, c, 'prd.approve', { options: [{ key: 'yes', text: 'a' }], recommendation: 'no' }),
|
||||
/invalid-options/,
|
||||
);
|
||||
const shaped = (o) => raise(b, c, 'prd.approve', { options: [{ key: 'yes', text: 'a' }, o], recommendation: 'no' });
|
||||
assert.throws(() => shaped({ key: 'no bad', text: 'b' }), /invalid-options/);
|
||||
assert.throws(() => shaped({ key: 'no', text: '' }), /invalid-options/);
|
||||
for (const o of [{ key: 'no' }, { key: 'no', text: 'b', why: 'c' }, 'no'])
|
||||
assert.throws(() => shaped(o), /invalid-request/, 'a malformed option object is a malformed argument');
|
||||
assert.deepEqual(count(), before, 'a refused raise writes no decision and no message');
|
||||
assert.equal(call(b, c, 'inbox').length, 0);
|
||||
const d = raise(b, c, 'prd.approve', { recommendation: 'yes' });
|
||||
assert.equal(store.get('SELECT recommendation FROM decisions WHERE id=?', d.id).recommendation, 'yes');
|
||||
});
|
||||
test('observer capabilities read human inbox but cannot mutate or forge launch identity', (t) => {
|
||||
const { b, agent } = setup(t),
|
||||
c = agent('coder');
|
||||
|
||||
Reference in New Issue
Block a user