use candor_core::protocol::AgentAction;
#[derive(Debug, Clone)]
pub struct DoctrineCheck {
pub passed: bool,
pub violations: Vec<String>,
pub warnings: Vec<String>,
}
pub fn enforce_doctrine(action: &AgentAction, context: &str) -> DoctrineCheck {
let mut violations = Vec::new();
let mut warnings = Vec::new();
if contains_vague_claim(context) {
violations.push(
"Precision Over Persuasion: Vague claim detected. Claims must be specific and verifiable."
.into(),
);
}
if action.is_destructive() && !action.sentinel_approved {
violations.push(
"AI Is Infrastructure, Not Authority: Destructive action requires sentinel approval."
.into(),
);
}
if !action.is_reversible && matches!(action.action_type, candor_core::protocol::ActionType::FileWrite | candor_core::protocol::ActionType::FileDelete) {
warnings.push(
"Failure Is the Primary Use Case: Irreversible action — ensure rollback is possible."
.into(),
);
}
if contains_marketing_language(context) {
violations.push(
"Marketing Is Not Evidence: Remove marketing language. Claims require sandbox-verified proof."
.into(),
);
}
if action.payload.len() > 100_000 {
violations.push(
"Sustainability Is a Hard Constraint: Payload exceeds cognitive limit. Break into smaller steps."
.into(),
);
}
if contains_over_abstraction(context) {
violations.push(
"Simplicity Is an Ethical Choice: Over-abstraction detected. Use visible, simple logic."
.into(),
);
}
if matches!(action.action_type, candor_core::protocol::ActionType::ForcePush) {
violations.push(
"Reversibility Matters More Than Speed: Force push is irreversible. Blocked."
.into(),
);
}
let passed = violations.is_empty();
DoctrineCheck { passed, violations, warnings }
}
fn contains_vague_claim(text: &str) -> bool {
let vague_patterns = [
"should work",
"probably fine",
"might be okay",
"seems to work",
"looks good",
"I think",
"I believe",
];
let lower = text.to_lowercase();
vague_patterns.iter().any(|p| lower.contains(p))
}
fn contains_marketing_language(text: &str) -> bool {
let marketing_patterns = [
"revolutionary",
"game-changing",
"best-in-class",
"world-class",
"cutting-edge",
"state-of-the-art",
"unprecedented",
];
let lower = text.to_lowercase();
marketing_patterns.iter().any(|p| lower.contains(p))
}
fn contains_over_abstraction(text: &str) -> bool {
let abstraction_patterns = [
"AbstractSingletonProxyFactoryBean",
"EnterpriseQuality",
"ManagerFactory",
"ProviderManager",
];
text.contains("FactoryFactory") || abstraction_patterns.iter().any(|p| text.contains(p))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vague_claim_detected() {
assert!(contains_vague_claim("This should work fine"));
assert!(!contains_vague_claim("The function returns Ok(()) when given valid input"));
}
#[test]
fn test_marketing_language_detected() {
assert!(contains_marketing_language("This revolutionary approach"));
assert!(!contains_marketing_language("The test passes with valid inputs"));
}
#[test]
fn test_doctrine_check_destructive() {
let action = AgentAction {
id: "1".into(),
action_type: candor_core::protocol::ActionType::FileDelete,
payload: "rm important".into(),
target_path: Some("/tmp/test".into()),
is_reversible: false,
scope_tags: vec![],
phase: "execute".into(),
sentinel_approved: false,
};
let check = enforce_doctrine(&action, "delete this file");
assert!(!check.passed);
assert!(check.warnings.iter().any(|w| w.contains("Failure Is the Primary Use Case")));
}
}