- 1
//! Learning-loop tool classification (docs/design/26-learning.md): - 2
//! journaling tools are sanctioned under workspace-write, denied by - 3
//! read-only; session_search is a read everywhere reads are allowed. - 4
- 5
#![allow(clippy::unwrap_used, clippy::expect_used)] - 6
- 7
use serde_json::json; - 8
use vak_permission::{Mode, PermissionEngine}; - 9
- 10
#[test] - 11
fn learning_tools_allowed_under_workspace_write_without_rules() { - 12
let engine = PermissionEngine::default(); - 13
for tool in ["remember", "propose_skill"] { - 14
let d = engine.evaluate( - 15
tool, - 16
&json!({}), - 17
Mode::WorkspaceWrite, - 18
std::path::Path::new("/ws"), - 19
); - 20
assert!( - 21
matches!(d, vak_permission::Decision::Allow), - 22
"{tool} must not require approval: {d:?}" - 23
); - 24
} - 25
} - 26
- 27
#[test] - 28
fn remember_denied_in_read_only() { - 29
let engine = PermissionEngine::default(); - 30
let d = engine.evaluate( - 31
"remember", - 32
&json!({}), - 33
Mode::ReadOnly, - 34
std::path::Path::new("/ws"), - 35
); - 36
assert!(matches!(d, vak_permission::Decision::Deny { .. }), "{d:?}"); - 37
} - 38
- 39
#[test] - 40
fn session_search_is_a_read() { - 41
let engine = PermissionEngine::default(); - 42
for mode in [Mode::ReadOnly, Mode::WorkspaceWrite] { - 43
let d = engine.evaluate( - 44
"session_search", - 45
&json!({"query": "x"}), - 46
mode, - 47
std::path::Path::new("/ws"), - 48
); - 49
assert!( - 50
matches!(d, vak_permission::Decision::Allow), - 51
"{mode:?}: {d:?}" - 52
); - 53
} - 54
} - 55
- 56
/// Reading the Agent's own portfolio changes nothing. Found in a live run: - 57
/// "what commitments are you holding?" on an unattended surface was refused - 58
/// because the read needed an approver nobody could be. - 59
#[test] - 60
fn commitments_is_a_read() { - 61
let engine = PermissionEngine::default(); - 62
for mode in [Mode::ReadOnly, Mode::WorkspaceWrite] { - 63
let d = engine.evaluate( - 64
"commitments", - 65
&json!({"include_closed": true}), - 66
mode, - 67
std::path::Path::new("/ws"), - 68
); - 69
assert!( - 70
matches!(d, vak_permission::Decision::Allow), - 71
"{mode:?}: {d:?}" - 72
); - 73
} - 74
// An operator's rule still wins. - 75
let engine = PermissionEngine::from_rule_strings(&["-commitments".to_string()]).unwrap(); - 76
let d = engine.evaluate( - 77
"commitments", - 78
&json!({}), - 79
Mode::WorkspaceWrite, - 80
std::path::Path::new("/ws"), - 81
); - 82
assert!(matches!(d, vak_permission::Decision::Deny { .. }), "{d:?}"); - 83
} - 84
- 85
#[test] - 86
fn explicit_deny_rule_still_beats_learning_allowance() { - 87
// Severity aggregation: a user's deny rule outranks the built-in - 88
// WorkspaceWrite allowance. - 89
let engine = PermissionEngine::from_rule_strings(&["-remember".to_string()]).unwrap(); - 90
let d = engine.evaluate( - 91
"remember", - 92
&json!({}), - 93
Mode::WorkspaceWrite, - 94
std::path::Path::new("/ws"), - 95
); - 96
assert!(matches!(d, vak_permission::Decision::Deny { .. }), "{d:?}"); - 97
} - 98
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.