"""Structured audit log writer. Every agent action — including recommended-but-not-taken — must be written here before execution. This is the safety net. """ from __future__ import annotations import json import logging from datetime import datetime, timezone from pathlib import Path from .models import CandidateIncident, RCAResult logger = logging.getLogger(__name__) class AuditLog: """Appends structured JSON records to the audit log file. Minimum fields per record: timestamp, trigger type, raw signals, SLM diagnosis, action recommended, action taken, operator response, outcome. """ def __init__(self, log_path: Path) -> None: self.log_path = log_path def record_incident(self, incident: CandidateIncident) -> None: """Write a CandidateIncident trigger record.""" raise NotImplementedError def record_rca(self, result: RCAResult) -> None: """Write an RCA analysis result record.""" raise NotImplementedError def record_action( self, incident_id: str, action: str, taken: bool, operator_response: str = "", ) -> None: """Write an action record (taken or suppressed).""" raise NotImplementedError def _append(self, record: dict) -> None: """Append a JSON record to the log file, one record per line.""" record.setdefault("timestamp", datetime.now(tz=timezone.utc).isoformat()) with self.log_path.open("a") as f: f.write(json.dumps(record) + "\n")