58 lines
2.5 KiB
TypeScript
58 lines
2.5 KiB
TypeScript
/**
|
|
* session-reviewer persona — trust-boundary tool policy.
|
|
*
|
|
* The reviewer runs headless; ALWAYS_AVAILABLE_TOOLS (persona-tool-filter) re-adds
|
|
* write-side tools past any allowlist, so the persona's disallowedTools must strip
|
|
* the dangerous ones while KEEPING create_skill (its one proposal write) and the
|
|
* read tools. This test locks that against regression.
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import { getPersona, type ToolDefinition } from '@waggle/agent';
|
|
import { applyPersonaToolFilter } from '../../src/local/persona-tool-filter.js';
|
|
|
|
/** Minimal ToolDefinition stub — only `name` matters for the filter. */
|
|
function tool(name: string): ToolDefinition {
|
|
return { name, description: '', parameters: { type: 'object', properties: {} }, execute: async () => '' };
|
|
}
|
|
|
|
// A representative superset spanning reads, writes, memory, exec, and skill tools.
|
|
const POOL: ToolDefinition[] = [
|
|
'read_file', 'search_files', 'search_content',
|
|
'search_memory', 'save_memory', 'query_knowledge', 'get_identity', 'get_awareness',
|
|
'correct_knowledge', 'add_task',
|
|
'list_skills', 'search_skills', 'read_skill', 'create_skill', 'delete_skill',
|
|
'write_file', 'edit_file', 'generate_docx', 'bash',
|
|
'git_commit', 'git_push',
|
|
'spawn_agent', 'install_capability', 'acquire_capability',
|
|
'execute_step', 'compose_workflow', 'orchestrate_workflow',
|
|
].map(tool);
|
|
|
|
describe('session-reviewer persona', () => {
|
|
it('exists and is not read-only (so create_skill survives)', () => {
|
|
const p = getPersona('session-reviewer');
|
|
expect(p).toBeTruthy();
|
|
expect(p!.isReadOnly).toBe(false);
|
|
expect(p!.tools).toContain('create_skill');
|
|
});
|
|
|
|
it('applyPersonaToolFilter keeps reads + create_skill, strips writes/exec/memory', () => {
|
|
const p = getPersona('session-reviewer')!;
|
|
const names = new Set(applyPersonaToolFilter(POOL, p).map(t => t.name));
|
|
|
|
// Kept — the reviewer's read surface + its one proposal write.
|
|
for (const keep of ['read_file', 'search_content', 'search_memory', 'read_skill', 'list_skills', 'create_skill']) {
|
|
expect(names.has(keep), `expected ${keep} to survive`).toBe(true);
|
|
}
|
|
|
|
// Stripped — writes, exec, memory writes, and the ALWAYS_AVAILABLE re-adds.
|
|
for (const drop of [
|
|
'save_memory', 'delete_skill', 'install_capability', 'acquire_capability',
|
|
'bash', 'spawn_agent', 'write_file', 'edit_file', 'git_commit',
|
|
'add_task', 'correct_knowledge', 'execute_step', 'compose_workflow',
|
|
]) {
|
|
expect(names.has(drop), `expected ${drop} to be stripped`).toBe(false);
|
|
}
|
|
});
|
|
});
|