use crate::{CognitiveContext, Message};
pub fn render(ctx: &CognitiveContext) -> Result<Vec<Message>, String> {
let mut out = Vec::new();
let mut sys = String::new();
sys.push_str(&ctx.system_directive);
sys.push_str("\n\n### SYSTEM PROTOCOL ###\n");
sys.push_str("You operate under LogLine OS. Output MUST be a valid JSON object representing a TDLN Semantic Unit.\n");
sys.push_str("Do NOT include natural language outside JSON. If you must think, put it BEFORE the JSON and then a single JSON block.\n");
sys.push_str("Format example: {\"kind\":\"verb\",\"slots\":{\"k\":\"v\"}}\n");
if !ctx.constraints.is_empty() {
sys.push_str("\n### ACTIVE KERNEL CONSTRAINTS ###\n");
sys.push_str("Violating these causes gate rejection:\n");
for c in &ctx.constraints {
sys.push_str(&format!("- {c}\n"));
}
}
if !ctx.recall.is_empty() {
sys.push_str("\n### RELEVANT MEMORY (RECALL) ###\n");
for m in &ctx.recall {
sys.push_str(&format!("- {m}\n"));
}
}
out.push(Message::system(sys));
out.extend(ctx.history.clone());
Ok(out)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn render_includes_protocol() {
let ctx = CognitiveContext {
system_directive: "You are a planner.".into(),
..Default::default()
};
let msgs = render(&ctx).unwrap();
assert_eq!(msgs.len(), 1);
assert!(msgs[0].content.contains("SYSTEM PROTOCOL"));
assert!(msgs[0].content.contains("JSON"));
}
#[test]
fn render_includes_constraints() {
let ctx = CognitiveContext {
system_directive: "Brain".into(),
constraints: vec!["No transfers over 500".into()],
..Default::default()
};
let msgs = render(&ctx).unwrap();
assert!(msgs[0].content.contains("No transfers over 500"));
assert!(msgs[0].content.contains("KERNEL CONSTRAINTS"));
}
#[test]
fn render_includes_recall() {
let ctx = CognitiveContext {
system_directive: "Brain".into(),
recall: vec!["User balance: 420".into()],
..Default::default()
};
let msgs = render(&ctx).unwrap();
assert!(msgs[0].content.contains("User balance: 420"));
assert!(msgs[0].content.contains("RECALL"));
}
#[test]
fn render_appends_history() {
let ctx = CognitiveContext {
system_directive: "Brain".into(),
history: vec![
Message::user("hello"),
Message::assistant("hi"),
],
..Default::default()
};
let msgs = render(&ctx).unwrap();
assert_eq!(msgs.len(), 3);
assert_eq!(msgs[1].role, "user");
assert_eq!(msgs[2].role, "assistant");
}
#[test]
fn stable_render() {
let ctx = CognitiveContext {
system_directive: "Test".into(),
recall: vec!["mem".into()],
history: vec![Message::user("hello")],
constraints: vec!["rule".into()],
};
let a = render(&ctx).unwrap();
let b = render(&ctx).unwrap();
assert_eq!(a, b);
}
}