Files
stack/agents/rocko/work/queue-219/r4/approved-tests.diff

53 lines
3.8 KiB
Diff

diff --git a/packages/bus/tests/grant-executor.test.mjs b/packages/bus/tests/grant-executor.test.mjs
index e449b7d77..46235d16b 100644
--- a/packages/bus/tests/grant-executor.test.mjs
+++ b/packages/bus/tests/grant-executor.test.mjs
@@ -1047,7 +1047,10 @@ test('sage-1908: once the agent of an applied grant is a creative role, host.run
const f = await setup(t);
assert.equal((await f.approve()).end.action, 'grant.applied');
const r = await restart(t, f, creativeOps(f.business));
- const cap = r.broker.bindLaunch({ business: 'demo', role: 'ops', run: 'ops-run', harness: 'pi', address: 'ops' });
+ const human = r.broker.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true });
+ const project = r.broker.request(human, { verb: 'project.create', args: { name: 'host grant check' } }).id;
+ const thread = r.broker.request(human, { verb: 'thread.create', args: { project, name: 'ops', instance: 'ops' } }).id;
+ const cap = r.broker.bindLaunch({ business: 'demo', role: 'ops', run: 'ops-run', harness: 'pi', address: 'ops', thread });
r.broker.request(cap, { verb: 'role.claim' });
const executor = hostExecutor({ credentials: r.credentials, root: join(f.dir, 'host-run') });
const before = f.requests().length;
diff --git a/packages/bus/tests/project-runtime.test.mjs b/packages/bus/tests/project-runtime.test.mjs
index a6086e56c..7275ad902 100644
--- a/packages/bus/tests/project-runtime.test.mjs
+++ b/packages/bus/tests/project-runtime.test.mjs
@@ -32,7 +32,8 @@ test('Broker keeps the sandbox client import closure: only the listed imports, n
// (#1692, D2.4) reads unhireableAction, the hire veto's action name.
// Row 236 (#1742, #436b) reads giteaName and parseGiteaUrl for the Gitea grant path.
// FED R3 r5 (row 274, #414) reads covers, a user's grant check, from it.
- "import { ID_PATTERN, THREAD_DEFINITION, END_PROTECTED, forkProblem, forkUrl, credentialKind, validArgv, commandAllowed, HOST_ID, CREATIVE_DEFINITIONS, unhireableAction, giteaName, parseGiteaUrl, covers } from '../../business/src/vocabulary.mjs';",
+ // Row 219 reads THREAD_DEFINITIONS from the same vocabulary for creative thread admission.
+ "import { ID_PATTERN, THREAD_DEFINITIONS, END_PROTECTED, forkProblem, forkUrl, credentialKind, validArgv, commandAllowed, HOST_ID, CREATIVE_DEFINITIONS, unhireableAction, giteaName, parseGiteaUrl, covers } from '../../business/src/vocabulary.mjs';",
]);
assert.doesNotMatch(source, /\bimport\s*\(/);
assert.doesNotMatch(readFileSync(new URL('../src/landing.mjs', import.meta.url), 'utf8'), /\bimport\b/);
diff --git a/packages/bus/tests/threads.test.mjs b/packages/bus/tests/threads.test.mjs
index 1410ec3fa..280e03184 100644
--- a/packages/bus/tests/threads.test.mjs
+++ b/packages/bus/tests/threads.test.mjs
@@ -640,3 +640,17 @@ test('C2-09a: explicit missing, non-thread and malformed selectors create no thr
const legacy = ctx.call('human', 'thread.create', { project, name: 'Default' });
assert.equal(legacy.instance, 'assistant');
});
+
+
+test('C2-09a: creative bindLaunch without a thread refuses thread-required', t => {
+ const creative = ['companion', 'ideas', 'research', 'proofreader', 'fact-checker', 'continuity'];
+ const extra = Object.fromEntries(creative.map((definition, i) => [`creative${i}`, { definition, authority: { withinRole: ['message.send'], crossRole: [] } }]));
+ const ctx = setup(t, demo({ roles: { ...roles, ...extra }, definitions: {
+ ...definitions, ...Object.fromEntries(creative.map(definition => [definition, {}])),
+ } }));
+ for (const instance of Object.keys(extra)) {
+ assert.throws(() => ctx.launch(`unthreaded-${instance}`, instance), { code: 'thread-required' });
+ }
+ assert.equal(ctx.count('SELECT count(*) n FROM threads'), 0);
+ assert.equal(ctx.count('SELECT count(*) n FROM role_claims'), 0);
+});