53 lines
3.8 KiB
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);
|
|
+});
|