use crate::brain::agent::service::compaction_prompts::{
CompactionKind, PlanRecovery, append_skill_stamp, build_continuation,
};
const APPROVAL_TAIL: &str = "Tool approval is REQUIRED";
const SESSION_RECOVERY: &str = "SESSION RECOVERY";
#[test]
fn fun_regular_keeps_post_compaction_protocol_header() {
let body = build_continuation(CompactionKind::Regular, false, true, PlanRecovery::Active);
assert!(
body.contains("POST-COMPACTION PROTOCOL"),
"fun regular must include the numbered protocol header so the \
model picks up the task; got: {body}"
);
assert!(
!body.contains("Silently continue"),
"fun variant must not carry the silent directive: {body}"
);
}
#[test]
fn silent_regular_uses_silent_directive() {
let body = build_continuation(CompactionKind::Regular, true, true, PlanRecovery::Active);
assert!(
body.contains("Silently continue"),
"silent regular must explicitly tell the model to continue silently: {body}"
);
assert!(
!body.contains("POST-COMPACTION PROTOCOL"),
"silent variant must drop the verbose protocol header: {body}"
);
}
#[test]
fn fun_emergency_invites_fun_cheeky_remark() {
let body = build_continuation(CompactionKind::Emergency, false, true, PlanRecovery::Active);
assert!(
body.contains("fun/cheeky remark"),
"fun emergency must explicitly invite a fun/cheeky remark: {body}"
);
}
#[test]
fn silent_emergency_suppresses_acknowledgement() {
let body = build_continuation(CompactionKind::Emergency, true, true, PlanRecovery::Active);
assert!(
body.contains("Silently resume"),
"silent emergency must direct silent resumption: {body}"
);
assert!(
!body.contains("fun/cheeky remark"),
"silent variant must not invite a fun remark: {body}"
);
}
#[test]
fn fun_post_tool_keeps_cursing_allowed_explicit() {
let body = build_continuation(CompactionKind::PostTool, false, true, PlanRecovery::Active);
assert!(
body.contains("cursing allowed"),
"fun post-tool must keep the explicit cursing-allowed license: {body}"
);
assert!(body.contains("IMMEDIATE TASK"));
}
#[test]
fn silent_post_tool_drops_cursing_invitation() {
let body = build_continuation(CompactionKind::PostTool, true, true, PlanRecovery::Active);
assert!(!body.contains("cursing allowed"));
assert!(body.contains("Silently continue"));
}
#[test]
fn mid_loop_variants_diverge_on_silent_flag() {
let fun = build_continuation(CompactionKind::MidLoop, false, true, PlanRecovery::Active);
let silent = build_continuation(CompactionKind::MidLoop, true, true, PlanRecovery::Active);
assert_ne!(fun, silent, "the two modes must produce different prompts");
assert!(fun.contains("POST-COMPACTION PROTOCOL"));
assert!(silent.contains("Silently continue"));
}
#[test]
fn approval_tail_appended_when_auto_approve_disabled_in_both_modes() {
for kind in [
CompactionKind::Regular,
CompactionKind::MidLoop,
CompactionKind::Emergency,
CompactionKind::PostTool,
] {
let fun = build_continuation(kind, false, false, PlanRecovery::Active);
let silent = build_continuation(kind, true, false, PlanRecovery::Active);
assert!(
fun.contains(APPROVAL_TAIL),
"fun {kind:?} must append the approval reminder when auto_approve=false: {fun}"
);
assert!(
silent.contains(APPROVAL_TAIL),
"silent {kind:?} must append the approval reminder when auto_approve=false: {silent}"
);
}
}
#[test]
fn approval_tail_omitted_when_auto_approve_enabled() {
for kind in [
CompactionKind::Regular,
CompactionKind::MidLoop,
CompactionKind::Emergency,
CompactionKind::PostTool,
] {
let fun = build_continuation(kind, false, true, PlanRecovery::Active);
let silent = build_continuation(kind, true, true, PlanRecovery::Active);
assert!(
!fun.contains(APPROVAL_TAIL),
"fun {kind:?} must NOT carry the approval tail when auto_approve=true: {fun}"
);
assert!(
!silent.contains(APPROVAL_TAIL),
"silent {kind:?} must NOT carry the approval tail when auto_approve=true: {silent}"
);
}
}
#[test]
fn default_agent_config_is_fun_mode() {
let cfg = crate::config::AgentConfig::default();
assert!(
!cfg.silent_compaction,
"AgentConfig::default() must keep silent_compaction=false so fun \
post-compaction narration is the out-of-the-box behaviour"
);
}
#[test]
fn session_recovery_hint_present_in_all_variants() {
for kind in [
CompactionKind::Regular,
CompactionKind::MidLoop,
CompactionKind::Emergency,
CompactionKind::PostTool,
CompactionKind::Manual,
] {
for silent in [false, true] {
let body = build_continuation(kind, silent, true, PlanRecovery::Active);
assert!(
body.contains(SESSION_RECOVERY),
"{kind:?} silent={silent} must include the SESSION RECOVERY hint: {body}"
);
assert!(
body.contains("plan") && body.contains("start"),
"{kind:?} silent={silent} must tell the agent to call plan with start: {body}"
);
assert!(
body.contains("CODE.md"),
"{kind:?} silent={silent} must mention CODE.md for coding sessions: {body}"
);
}
}
}
#[test]
fn manual_compaction_is_brief() {
for silent in [false, true] {
let body = build_continuation(CompactionKind::Manual, silent, true, PlanRecovery::Active);
assert!(
!body.contains("POST-COMPACTION PROTOCOL"),
"Manual compaction must NOT use the full protocol: {body}"
);
assert!(
!body.contains("session_search"),
"Manual compaction must NOT instruct session_search (brief only): {body}"
);
assert!(
body.contains("IMMEDIATE TASK"),
"Manual compaction must still reference the IMMEDIATE TASK: {body}"
);
}
}
const STAMP_HEADER: &str = "SKILLS LOADED PRE-COMPACTION:";
const STAMP_ADVISORY: &str = "reload only those that are";
#[test]
fn skill_stamp_lists_active_skills_with_advisory_framing() {
let body = build_continuation(CompactionKind::Regular, false, true, PlanRecovery::Active);
let stamped = append_skill_stamp(body, &["opencrabs-dev".to_string(), "grafana".to_string()]);
assert!(
stamped.contains(STAMP_HEADER),
"stamp must carry the inventory header: {stamped}"
);
assert!(
stamped.contains("opencrabs-dev") && stamped.contains("grafana"),
"stamp must list every active skill: {stamped}"
);
assert!(
stamped.contains(STAMP_ADVISORY),
"stamp must be advisory (consider, reload selectively) not prescriptive: {stamped}"
);
}
#[test]
fn skill_stamp_is_silent_when_no_skills_active() {
for kind in [
CompactionKind::Regular,
CompactionKind::MidLoop,
CompactionKind::Emergency,
CompactionKind::PostTool,
CompactionKind::Manual,
] {
for silent in [false, true] {
let body = build_continuation(kind, silent, true, PlanRecovery::NoPlan);
let stamped = append_skill_stamp(body, &[]);
assert!(
!stamped.contains(STAMP_HEADER),
"{kind:?} silent={silent}: no skills → no stamp, zero marginal tokens: {stamped}"
);
}
}
}
#[test]
fn skill_stamp_rides_all_kinds_and_variants() {
let skills = vec!["opencrabs-dev".to_string()];
for kind in [
CompactionKind::Regular,
CompactionKind::MidLoop,
CompactionKind::Emergency,
CompactionKind::PostTool,
CompactionKind::Manual,
] {
for silent in [false, true] {
let body = build_continuation(kind, silent, true, PlanRecovery::Active);
let stamped = append_skill_stamp(body, &skills);
assert!(
stamped.contains(STAMP_HEADER) && stamped.contains(STAMP_ADVISORY),
"{kind:?} silent={silent}: stamp must ride every kind/variant: {stamped}"
);
}
}
}
#[test]
fn skill_stamp_sorts_names_for_determinism() {
let body = build_continuation(CompactionKind::Regular, false, true, PlanRecovery::NoPlan);
let stamped = append_skill_stamp(
body,
&["zeta".to_string(), "alpha".to_string(), "mid".to_string()],
);
let header_pos = stamped.find(STAMP_HEADER).expect("stamp present");
let list = &stamped[header_pos..];
let alpha = list.find("alpha").expect("alpha present");
let mid = list.find("mid").expect("mid present");
let zeta = list.find("zeta").expect("zeta present");
assert!(
alpha < mid && mid < zeta,
"stamp list must be sorted for deterministic rendering: {list}"
);
}