#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeViolation {
pub work_item_id: String,
pub timestamp: String,
pub command: String,
pub violation_type: ViolationType,
pub duration_ms: Option<u64>,
pub exit_code: Option<i32>,
pub message: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ViolationType {
CommandFailure,
TimingAnomaly,
TrustViolation,
}
impl std::fmt::Display for ViolationType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ViolationType::CommandFailure => write!(f, "command_failure"),
ViolationType::TimingAnomaly => write!(f, "timing_anomaly"),
ViolationType::TrustViolation => write!(f, "trust_violation"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ViolationSummary {
pub total_violations: usize,
pub command_failures: usize,
pub timing_anomalies: usize,
pub trust_violations: usize,
pub violations_per_session_avg: f64,
pub elevated: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandTiming {
pub command: String,
pub durations: Vec<u64>,
pub mean_ms: f64,
pub std_dev_ms: f64,
}
impl CommandTiming {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new(command: String, duration_ms: u64) -> Self {
Self {
command,
durations: vec![duration_ms],
mean_ms: duration_ms as f64,
std_dev_ms: 0.0,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn record(&mut self, duration_ms: u64) {
self.durations.push(duration_ms);
if self.durations.len() > 50 {
self.durations.remove(0);
}
self.recompute_stats();
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn is_anomalous(&self, duration_ms: u64) -> bool {
if self.durations.len() < 3 {
return false; }
let z_score = (duration_ms as f64 - self.mean_ms) / self.std_dev_ms.max(1.0);
z_score.abs() > 3.0
}
fn recompute_stats(&mut self) {
let n = self.durations.len() as f64;
self.mean_ms = self.durations.iter().sum::<u64>() as f64 / n;
let variance = self
.durations
.iter()
.map(|d| {
let diff = *d as f64 - self.mean_ms;
diff * diff
})
.sum::<f64>()
/ n;
self.std_dev_ms = variance.sqrt();
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ViolationTracker {
pub violations: Vec<RuntimeViolation>,
pub timings: HashMap<String, CommandTiming>,
}
impl ViolationTracker {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn record_failure(
&mut self,
work_item_id: &str,
command: &str,
exit_code: i32,
message: &str,
) {
self.violations.push(RuntimeViolation {
work_item_id: work_item_id.to_string(),
timestamp: chrono_now(),
command: command.to_string(),
violation_type: ViolationType::CommandFailure,
duration_ms: None,
exit_code: Some(exit_code),
message: message.to_string(),
});
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn record_execution(
&mut self,
work_item_id: &str,
command: &str,
duration_ms: u64,
) -> bool {
let is_anomalous = self
.timings
.get(command)
.map(|t| t.is_anomalous(duration_ms))
.unwrap_or(false);
self.timings
.entry(command.to_string())
.and_modify(|t| t.record(duration_ms))
.or_insert_with(|| CommandTiming::new(command.to_string(), duration_ms));
if is_anomalous {
let timing = &self.timings[command];
self.violations.push(RuntimeViolation {
work_item_id: work_item_id.to_string(),
timestamp: chrono_now(),
command: command.to_string(),
violation_type: ViolationType::TimingAnomaly,
duration_ms: Some(duration_ms),
exit_code: None,
message: format!(
"Execution time {}ms deviates >3 sigma from mean {:.0}ms (std: {:.0}ms)",
duration_ms, timing.mean_ms, timing.std_dev_ms
),
});
}
is_anomalous
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn record_trust_violation(
&mut self,
work_item_id: &str,
manifest_path: &str,
message: &str,
) {
self.violations.push(RuntimeViolation {
work_item_id: work_item_id.to_string(),
timestamp: chrono_now(),
command: manifest_path.to_string(),
violation_type: ViolationType::TrustViolation,
duration_ms: None,
exit_code: None,
message: message.to_string(),
});
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn summary(&self, historical_avg: f64) -> ViolationSummary {
let command_failures = self
.violations
.iter()
.filter(|v| v.violation_type == ViolationType::CommandFailure)
.count();
let timing_anomalies = self
.violations
.iter()
.filter(|v| v.violation_type == ViolationType::TimingAnomaly)
.count();
let trust_violations = self
.violations
.iter()
.filter(|v| v.violation_type == ViolationType::TrustViolation)
.count();
let total = self.violations.len();
ViolationSummary {
total_violations: total,
command_failures,
timing_anomalies,
trust_violations,
violations_per_session_avg: historical_avg,
elevated: total as f64 > historical_avg * 2.0,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub fn save(&self, project_path: &Path, work_item_id: &str) -> Result<()> {
let dir = project_path
.join(".pmat-work")
.join(work_item_id)
.join("violations");
std::fs::create_dir_all(&dir)?;
let path = dir.join("tracker.json");
let json = serde_json::to_string_pretty(self)?;
std::fs::write(path, json)?;
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub fn load(project_path: &Path, work_item_id: &str) -> Self {
let path = project_path
.join(".pmat-work")
.join(work_item_id)
.join("violations")
.join("tracker.json");
if !path.exists() {
return Self::default();
}
std::fs::read_to_string(&path)
.ok()
.and_then(|s| serde_json::from_str(&s).ok())
.unwrap_or_default()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustChainEntry {
pub manifest_path: String,
pub content_hash: String,
pub prev_hash: String,
pub chain_hash: String,
pub trusted_at: String,
}
impl TrustChainEntry {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new(manifest_path: &str, content_hash: &str, prev_hash: &str) -> Self {
let chain_input = format!("{}{}", content_hash, prev_hash);
let chain_hash = format!("{:x}", Sha256::digest(chain_input.as_bytes()));
Self {
manifest_path: manifest_path.to_string(),
content_hash: content_hash.to_string(),
prev_hash: prev_hash.to_string(),
chain_hash,
trusted_at: chrono_now(),
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn verify(&self) -> bool {
let chain_input = format!("{}{}", self.content_hash, self.prev_hash);
let expected = format!("{:x}", Sha256::digest(chain_input.as_bytes()));
self.chain_hash == expected
}
}
fn chrono_now() -> String {
let secs = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
format!("{}Z", secs)
}