use super::reminders::{directive_envelope_message, render_pending_reminders};
use crate::llm::helpers::{
DirectiveAuthority, ReminderPropagate, ReminderRoleHint, ReminderSource, SystemReminder,
};
fn reminder(
role_hint: ReminderRoleHint,
authority: DirectiveAuthority,
body: &str,
) -> SystemReminder {
SystemReminder {
id: format!("reminder-{}", role_hint.as_str()),
tags: vec!["test".to_string()],
dedupe_key: None,
ttl_turns: None,
preserve_on_compact: false,
propagate: ReminderPropagate::Session,
role_hint,
authority,
source: ReminderSource::InPipeline,
body: body.to_string(),
fired_at_turn: 0,
originating_agent_id: None,
}
}
fn envelope_message(reminders: &[SystemReminder]) -> serde_json::Value {
let rendered = render_pending_reminders(
&crate::llm::capabilities::Capabilities::default(),
reminders,
);
directive_envelope_message(&rendered).expect("a non-empty directive set renders an envelope")
}
fn envelope_text(reminders: &[SystemReminder]) -> String {
envelope_message(reminders)["content"]
.as_str()
.expect("envelope content is a string")
.to_string()
}
#[test]
fn a_completion_judge_directive_is_declared_harness_originated() {
let envelope = envelope_text(&[reminder(
ReminderRoleHint::System,
DirectiveAuthority::Corrective,
"The done judge says the task is not finished; keep working.",
)]);
assert!(
envelope.starts_with("<context-directives speaker=\"harness\">"),
"a corrective harness directive must open a harness-originated envelope; got:\n{envelope}"
);
}
#[test]
fn a_user_block_directive_keeps_the_person_speaker() {
let envelope = envelope_text(&[reminder(
ReminderRoleHint::UserBlock,
DirectiveAuthority::Contract,
"Ship the smallest change that fixes the bug.",
)]);
assert!(
envelope.starts_with("<context-directives speaker=\"person\">"),
"a user-block directive must keep the person speaker; got:\n{envelope}"
);
}
#[test]
fn a_harness_directive_makes_a_mixed_envelope_harness_originated() {
let envelope = envelope_text(&[
reminder(
ReminderRoleHint::UserBlock,
DirectiveAuthority::Contract,
"Ship the smallest change that fixes the bug.",
),
reminder(
ReminderRoleHint::Developer,
DirectiveAuthority::Corrective,
"The done judge says the task is not finished; keep working.",
),
]);
assert!(
envelope.starts_with("<context-directives speaker=\"harness\">"),
"one harness directive must make the envelope harness-originated; got:\n{envelope}"
);
}
#[test]
fn both_speakers_transport_as_user() {
for role_hint in [
ReminderRoleHint::System,
ReminderRoleHint::Developer,
ReminderRoleHint::UserBlock,
ReminderRoleHint::EphemeralCache,
] {
let message = envelope_message(&[reminder(
role_hint,
DirectiveAuthority::Corrective,
"keep going",
)]);
assert_eq!(
message["role"],
"user",
"role hint {} must still transport as user",
role_hint.as_str()
);
}
}