From dc0dd4be9aaaae3b3a3478f6932db7ef629bfe92 Mon Sep 17 00:00:00 2001 From: Glenn Gore Date: Wed, 11 Nov 2026 12:28:55 +1000 Subject: [PATCH] test(eval): score recall across personal memory and Data Rooms Probes now take memory_recall's path (rooms::recall), with optional `sources`. A `room` step writes a signed (or open, or deliberately broken) room record. Four scenarios in a new `sources` dimension cover one ranking across both, narrowing, room curation, abstention, and refusing room records whose signature does not hold. Existing scenarios' numbers are unchanged. Signed-off-by: Glenn Gore --- tests/eval.rs | 209 +++++++++++++++++- tests/eval/README.md | 17 ++ .../19-sources-room-and-personal.json | 49 ++++ .../scenarios/20-sources-room-poisoning.json | 31 +++ .../scenarios/21-sources-room-standing.json | 29 +++ .../scenarios/22-sources-room-abstention.json | 26 +++ 6 files changed, 353 insertions(+), 8 deletions(-) create mode 100644 tests/eval/scenarios/19-sources-room-and-personal.json create mode 100644 tests/eval/scenarios/20-sources-room-poisoning.json create mode 100644 tests/eval/scenarios/21-sources-room-standing.json create mode 100644 tests/eval/scenarios/22-sources-room-abstention.json diff --git a/tests/eval.rs b/tests/eval.rs index 39c288a..42a7ed2 100644 --- a/tests/eval.rs +++ b/tests/eval.rs @@ -46,6 +46,7 @@ use vta_agent_memory::fence::{Fence, Provenance}; use vta_agent_memory::lifecycle::Status; use vta_agent_memory::provenance::{Basis, Evidence}; use vta_agent_memory::record::{MemoryKey, MemoryRecord, MemoryType}; +use vta_agent_memory::rooms::{self, Found, RoomSource, Sources}; use vta_agent_memory::store::{SaveOutcome, Store}; const CONTEXT: &str = "eval"; @@ -61,6 +62,8 @@ enum Dimension { Minimisation, Repairability, Poisoning, + /// Recall across personal memory and Data Rooms (#34). + Sources, } #[derive(Debug, Deserialize)] @@ -77,6 +80,10 @@ struct Scenario { /// take. #[serde(default)] max_repair_ops: Option, + /// Data Rooms recall reads, by label. Room records are written with + /// `room` steps; a probe narrows with `sources`. + #[serde(default)] + rooms: Vec, steps: Vec, } @@ -93,9 +100,47 @@ enum Step { Plant(PlantStep), /// Copy one stored value, signature and all, to another key. Copy(CopyStep), + /// A record in a Data Room, as the member's VTA serves it opened. + Room(RoomStep), Probe(Probe), } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +struct RoomStep { + /// The room's label, one of the scenario's `rooms`. + room: String, + /// The member who signs it. Default `member`. + #[serde(default, rename = "as")] + author: Option, + key: String, + #[serde(default)] + title: Option, + #[serde(default)] + description: Option, + #[serde(default)] + body: Option, + #[serde(default)] + basis: Option, + /// `active` (default), `deprecated` or `retracted`. + #[serde(default)] + status: Option, + #[serde(default)] + valid_until: Option, + /// An `open` room's record: cleartext, no in-body signature. + #[serde(default)] + open: bool, + /// Body fields changed after signing. + #[serde(default)] + alter: Map, + /// Served under this key instead of the one it was signed for. + #[serde(default)] + served_as: Option, + /// The member the host records as author, if not the signer. + #[serde(default)] + host_author: Option, +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] struct SaveStep { @@ -205,6 +250,10 @@ struct Probe { /// delimiters — stored text must not be able to forge one. #[serde(default)] fence: bool, + /// `personal`, `rooms`, or room labels. Omit for every source. Room + /// results are named `room: