Give loopd's tool port approvals, its own clock and plain denials

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-20 17:43:05 -07:00
parent 3ecaef3c8b
commit 1ceaa36b9b
8 changed files with 600 additions and 55 deletions
+21 -4
View File
@@ -1,5 +1,6 @@
//! Tests for one turn: record sequences and tool dispatch. Do not edit.
//! The limits and the append-only property are in `limits.rs`.
//! The limits and the append-only property are in `limits.rs`; denials and approvals are in
//! `turn_broker.rs`.
mod support;
#[path = "support/turn.rs"]
@@ -264,7 +265,7 @@ fn the_result_cap_applies_when_appended() {
}
#[test]
fn tool_failures_and_denials_become_results_the_model_can_read() {
fn a_tool_failure_becomes_a_result_the_model_can_read() {
let s = setup(vec![ToolResponse::Failed {
message: "disk on fire".to_string(),
}]);
@@ -273,8 +274,24 @@ fn tool_failures_and_denials_become_results_the_model_can_read() {
vec![Reply::fixture("tool_call"), Reply::fixture("plain")],
);
let mut session = s.session("a");
assert!(s.turn(&mut session, "x").0.is_ok());
let (result, events) = s.turn(&mut session, "x");
assert!(result.is_ok(), "{result:?}");
match &session.records()[4] {
LogRecord::ToolResult {
content,
class,
untrusted,
..
} => {
assert_eq!(content, "The tool failed: disk on fire");
assert_eq!((*class, *untrusted), (DataClass::Public, false));
}
other => panic!("{other:?}"),
}
assert!(
matches!(&session.records()[4], LogRecord::ToolResult { content, class: DataClass::Public, .. } if content.contains("disk on fire"))
!events
.iter()
.any(|e| matches!(e, TurnEvent::ToolDenied { .. })),
"a failure is not a denial"
);
}