feat(policy): enforce truthfulness and autonomy guardrails
Add runtime truthfulness modes and autonomy-level tool gating with audit metadata for overrides/denials. Wire policy through prompt assembly, tool execution context, and daemon/gateway agent paths; update tests and planning state for Phase 3 PR #2 completion.
This commit is contained in:
@@ -215,3 +215,191 @@ describe('configSchema automation', () => {
|
||||
expect(result.automation.cron[0].timezone).toBe('America/New_York');
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — intents', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults intents to disabled with no rules', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.intents.enabled).toBe(false);
|
||||
expect(result.intents.rules).toEqual([]);
|
||||
});
|
||||
|
||||
it('accepts intent rule config', () => {
|
||||
const result = configSchema.parse({
|
||||
...minimalConfig,
|
||||
intents: {
|
||||
enabled: true,
|
||||
match_threshold: 0.6,
|
||||
rules: [
|
||||
{
|
||||
name: 'deploy-rule',
|
||||
patterns: ['deploy *'],
|
||||
target: { type: 'agent', name: 'coder' },
|
||||
priority: 5,
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.intents.enabled).toBe(true);
|
||||
expect(result.intents.rules[0].target.type).toBe('agent');
|
||||
expect(result.intents.rules[0].target.name).toBe('coder');
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — routing_policy', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults routing_policy values', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.routing_policy.enabled).toBe(false);
|
||||
expect(result.routing_policy.fast_path_threshold).toBe(0.85);
|
||||
expect(result.routing_policy.llm_threshold).toBe(0.5);
|
||||
expect(result.routing_policy.default_path).toBe('llm');
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — history_index', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults history indexing config', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.history_index.enabled).toBe(false);
|
||||
expect(result.history_index.max_keywords).toBe(8);
|
||||
expect(result.history_index.search_limit).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — memory injection strategy', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults memory injection settings', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.memory.injection_strategy).toBe('all');
|
||||
expect(result.memory.max_injection_tokens).toBe(2000);
|
||||
});
|
||||
|
||||
it('accepts adaptive memory injection settings', () => {
|
||||
const result = configSchema.parse({
|
||||
...minimalConfig,
|
||||
memory: {
|
||||
injection_strategy: 'adaptive',
|
||||
max_injection_tokens: 1200,
|
||||
},
|
||||
});
|
||||
expect(result.memory.injection_strategy).toBe('adaptive');
|
||||
expect(result.memory.max_injection_tokens).toBe(1200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — compaction importance threshold', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults compaction importance threshold to disabled behavior', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.compaction.importance_threshold).toBe(1);
|
||||
});
|
||||
|
||||
it('accepts a custom importance threshold', () => {
|
||||
const result = configSchema.parse({
|
||||
...minimalConfig,
|
||||
compaction: {
|
||||
importance_threshold: 0.5,
|
||||
},
|
||||
});
|
||||
expect(result.compaction.importance_threshold).toBe(0.5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — prompt context level', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults prompt.context_level to normal', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.prompt.context_level).toBe('normal');
|
||||
});
|
||||
|
||||
it('accepts valid context levels', () => {
|
||||
const result = configSchema.parse({
|
||||
...minimalConfig,
|
||||
prompt: {
|
||||
context_level: 'debug',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.prompt.context_level).toBe('debug');
|
||||
});
|
||||
|
||||
it('rejects invalid context levels', () => {
|
||||
expect(() => configSchema.parse({
|
||||
...minimalConfig,
|
||||
prompt: {
|
||||
context_level: 'verbose',
|
||||
},
|
||||
})).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('configSchema — agents truthfulness/autonomy', () => {
|
||||
const minimalConfig = {
|
||||
telegram: { bot_token: 'test', allowed_chat_ids: [1] },
|
||||
models: { default: { provider: 'anthropic', model: 'claude-3' } },
|
||||
};
|
||||
|
||||
it('defaults to standard truthfulness and autonomy', () => {
|
||||
const result = configSchema.parse(minimalConfig);
|
||||
expect(result.agents.truthfulness_mode).toBe('standard');
|
||||
expect(result.agents.autonomy_level).toBe('standard');
|
||||
});
|
||||
|
||||
it('accepts explicit truthfulness and autonomy modes', () => {
|
||||
const result = configSchema.parse({
|
||||
...minimalConfig,
|
||||
agents: {
|
||||
truthfulness_mode: 'strict',
|
||||
autonomy_level: 'conservative',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.agents.truthfulness_mode).toBe('strict');
|
||||
expect(result.agents.autonomy_level).toBe('conservative');
|
||||
});
|
||||
|
||||
it('rejects invalid truthfulness_mode', () => {
|
||||
expect(() => configSchema.parse({
|
||||
...minimalConfig,
|
||||
agents: {
|
||||
truthfulness_mode: 'always',
|
||||
},
|
||||
})).toThrow();
|
||||
});
|
||||
|
||||
it('rejects invalid autonomy_level', () => {
|
||||
expect(() => configSchema.parse({
|
||||
...minimalConfig,
|
||||
agents: {
|
||||
autonomy_level: 'manual',
|
||||
},
|
||||
})).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user