agent_memgc/rules/
cache_layout.rs1use crate::domain::{InstructionBlock, LinterFinding, RuleCode, Severity};
2use regex::Regex;
3
4pub fn check_cache_layout(blocks: &[InstructionBlock]) -> Vec<LinterFinding> {
6 let mut findings = Vec::new();
7
8 let volatile_patterns = [
10 ("timestamp", r"\b\d{4}-\d{2}-\d{2}\b"),
11 ("time", r"\b\d{2}:\d{2}:\d{2}\b"),
12 ("session_id", r"(?i)session[_\s\-]?id"),
13 ("last_updated", r"(?i)last[_\s\-]updated"),
14 ("date_marker", r"(?i)date:\s*"),
15 ];
16
17 for block in blocks.iter().take(8) {
18 let text = &block.text;
19 if text.starts_with("# ") {
21 continue;
22 }
23
24 for (label, pattern) in &volatile_patterns {
25 if let Ok(re) = Regex::new(pattern) {
26 if re.is_match(text) {
27 findings.push(LinterFinding {
28 rule: RuleCode::MGC003,
29 severity: Severity::Info,
30 line: block.line_start,
31 target: format!("Volatile pattern: {label}"),
32 message: format!(
33 "Volatile dynamic content at line {} breaks prompt prefix caching.",
34 block.line_start
35 ),
36 suggestion: Some(
37 "Move dynamic timestamps, session IDs, and dates to the end of the prompt or into user messages so the static instruction prefix caches across turns."
38 .to_string(),
39 ),
40 fixable: true,
41 });
42 break;
43 }
44 }
45 }
46 }
47
48 findings
49}