agent_os_kernel 3.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. agent_control_plane/__init__.py +662 -0
  2. agent_control_plane/a2a_adapter.py +543 -0
  3. agent_control_plane/adapter.py +417 -0
  4. agent_control_plane/agent_hibernation.py +394 -0
  5. agent_control_plane/agent_kernel.py +470 -0
  6. agent_control_plane/compliance.py +720 -0
  7. agent_control_plane/constraint_graphs.py +478 -0
  8. agent_control_plane/control_plane.py +854 -0
  9. agent_control_plane/example_executors.py +195 -0
  10. agent_control_plane/execution_engine.py +231 -0
  11. agent_control_plane/flight_recorder.py +846 -0
  12. agent_control_plane/governance_layer.py +435 -0
  13. agent_control_plane/hf_utils.py +563 -0
  14. agent_control_plane/interfaces/__init__.py +55 -0
  15. agent_control_plane/interfaces/kernel_interface.py +361 -0
  16. agent_control_plane/interfaces/plugin_interface.py +497 -0
  17. agent_control_plane/interfaces/protocol_interfaces.py +387 -0
  18. agent_control_plane/kernel_space.py +1009 -0
  19. agent_control_plane/langchain_adapter.py +424 -0
  20. agent_control_plane/lifecycle.py +3113 -0
  21. agent_control_plane/mcp_adapter.py +653 -0
  22. agent_control_plane/ml_safety.py +563 -0
  23. agent_control_plane/multimodal.py +727 -0
  24. agent_control_plane/mute_agent.py +422 -0
  25. agent_control_plane/observability.py +787 -0
  26. agent_control_plane/orchestrator.py +482 -0
  27. agent_control_plane/plugin_registry.py +750 -0
  28. agent_control_plane/policy_engine.py +954 -0
  29. agent_control_plane/process_isolation.py +777 -0
  30. agent_control_plane/shadow_mode.py +310 -0
  31. agent_control_plane/signals.py +493 -0
  32. agent_control_plane/supervisor_agents.py +430 -0
  33. agent_control_plane/time_travel_debugger.py +557 -0
  34. agent_control_plane/tool_registry.py +452 -0
  35. agent_control_plane/vfs.py +697 -0
  36. agent_kernel/__init__.py +69 -0
  37. agent_kernel/analyzer.py +435 -0
  38. agent_kernel/auditor.py +36 -0
  39. agent_kernel/completeness_auditor.py +237 -0
  40. agent_kernel/detector.py +203 -0
  41. agent_kernel/kernel.py +744 -0
  42. agent_kernel/memory_manager.py +85 -0
  43. agent_kernel/models.py +374 -0
  44. agent_kernel/nudge_mechanism.py +263 -0
  45. agent_kernel/outcome_analyzer.py +338 -0
  46. agent_kernel/patcher.py +582 -0
  47. agent_kernel/semantic_analyzer.py +316 -0
  48. agent_kernel/semantic_purge.py +349 -0
  49. agent_kernel/simulator.py +449 -0
  50. agent_kernel/teacher.py +85 -0
  51. agent_kernel/triage.py +152 -0
  52. agent_os/__init__.py +409 -0
  53. agent_os/_adversarial_impl.py +200 -0
  54. agent_os/_circuit_breaker_impl.py +232 -0
  55. agent_os/_mcp_metrics.py +193 -0
  56. agent_os/adversarial.py +20 -0
  57. agent_os/agents_compat.py +490 -0
  58. agent_os/audit_logger.py +135 -0
  59. agent_os/base_agent.py +651 -0
  60. agent_os/circuit_breaker.py +34 -0
  61. agent_os/cli/__init__.py +659 -0
  62. agent_os/cli/cmd_audit.py +128 -0
  63. agent_os/cli/cmd_init.py +152 -0
  64. agent_os/cli/cmd_policy.py +41 -0
  65. agent_os/cli/cmd_policy_gen.py +180 -0
  66. agent_os/cli/cmd_validate.py +258 -0
  67. agent_os/cli/mcp_scan.py +265 -0
  68. agent_os/cli/output.py +192 -0
  69. agent_os/cli/policy_checker.py +330 -0
  70. agent_os/compat.py +74 -0
  71. agent_os/constraint_graph.py +234 -0
  72. agent_os/content_governance.py +140 -0
  73. agent_os/context_budget.py +305 -0
  74. agent_os/credential_redactor.py +224 -0
  75. agent_os/diff_policy.py +89 -0
  76. agent_os/egress_policy.py +159 -0
  77. agent_os/escalation.py +276 -0
  78. agent_os/event_bus.py +124 -0
  79. agent_os/exceptions.py +180 -0
  80. agent_os/execution_context_policy.py +141 -0
  81. agent_os/github_enterprise.py +96 -0
  82. agent_os/health.py +20 -0
  83. agent_os/integrations/__init__.py +279 -0
  84. agent_os/integrations/a2a_adapter.py +279 -0
  85. agent_os/integrations/agent_lightning/__init__.py +30 -0
  86. agent_os/integrations/anthropic_adapter.py +420 -0
  87. agent_os/integrations/autogen_adapter.py +620 -0
  88. agent_os/integrations/base.py +1137 -0
  89. agent_os/integrations/compat.py +229 -0
  90. agent_os/integrations/config.py +98 -0
  91. agent_os/integrations/conversation_guardian.py +957 -0
  92. agent_os/integrations/crewai_adapter.py +467 -0
  93. agent_os/integrations/drift_detector.py +425 -0
  94. agent_os/integrations/dry_run.py +124 -0
  95. agent_os/integrations/escalation.py +582 -0
  96. agent_os/integrations/gemini_adapter.py +364 -0
  97. agent_os/integrations/google_adk_adapter.py +633 -0
  98. agent_os/integrations/guardrails_adapter.py +394 -0
  99. agent_os/integrations/health.py +197 -0
  100. agent_os/integrations/langchain_adapter.py +654 -0
  101. agent_os/integrations/llamafirewall.py +343 -0
  102. agent_os/integrations/llamaindex_adapter.py +188 -0
  103. agent_os/integrations/logging.py +191 -0
  104. agent_os/integrations/maf_adapter.py +631 -0
  105. agent_os/integrations/mistral_adapter.py +365 -0
  106. agent_os/integrations/openai_adapter.py +816 -0
  107. agent_os/integrations/openai_agents_sdk.py +406 -0
  108. agent_os/integrations/policy_compose.py +171 -0
  109. agent_os/integrations/profiling.py +144 -0
  110. agent_os/integrations/pydantic_ai_adapter.py +420 -0
  111. agent_os/integrations/rate_limiter.py +130 -0
  112. agent_os/integrations/rbac.py +143 -0
  113. agent_os/integrations/registry.py +113 -0
  114. agent_os/integrations/scope_guard.py +303 -0
  115. agent_os/integrations/semantic_kernel_adapter.py +769 -0
  116. agent_os/integrations/smolagents_adapter.py +629 -0
  117. agent_os/integrations/templates.py +178 -0
  118. agent_os/integrations/token_budget.py +134 -0
  119. agent_os/integrations/tool_aliases.py +190 -0
  120. agent_os/integrations/webhooks.py +177 -0
  121. agent_os/lite.py +208 -0
  122. agent_os/mcp_gateway.py +385 -0
  123. agent_os/mcp_message_signer.py +273 -0
  124. agent_os/mcp_protocols.py +161 -0
  125. agent_os/mcp_response_scanner.py +232 -0
  126. agent_os/mcp_security.py +924 -0
  127. agent_os/mcp_session_auth.py +231 -0
  128. agent_os/mcp_sliding_rate_limiter.py +184 -0
  129. agent_os/memory_guard.py +409 -0
  130. agent_os/metrics.py +134 -0
  131. agent_os/mute.py +428 -0
  132. agent_os/mute_agent.py +209 -0
  133. agent_os/policies/__init__.py +77 -0
  134. agent_os/policies/async_evaluator.py +275 -0
  135. agent_os/policies/backends.py +670 -0
  136. agent_os/policies/bridge.py +169 -0
  137. agent_os/policies/budget.py +85 -0
  138. agent_os/policies/cli.py +294 -0
  139. agent_os/policies/conflict_resolution.py +270 -0
  140. agent_os/policies/data_classification.py +252 -0
  141. agent_os/policies/evaluator.py +239 -0
  142. agent_os/policies/policy_schema.json +228 -0
  143. agent_os/policies/rate_limiting.py +145 -0
  144. agent_os/policies/schema.py +115 -0
  145. agent_os/policies/shared.py +331 -0
  146. agent_os/prompt_injection.py +694 -0
  147. agent_os/providers.py +182 -0
  148. agent_os/py.typed +0 -0
  149. agent_os/retry.py +81 -0
  150. agent_os/reversibility.py +251 -0
  151. agent_os/sandbox.py +432 -0
  152. agent_os/sandbox_provider.py +140 -0
  153. agent_os/secure_codegen.py +525 -0
  154. agent_os/security_skills.py +538 -0
  155. agent_os/semantic_policy.py +422 -0
  156. agent_os/server/__init__.py +15 -0
  157. agent_os/server/__main__.py +25 -0
  158. agent_os/server/app.py +277 -0
  159. agent_os/server/models.py +104 -0
  160. agent_os/shift_left_metrics.py +130 -0
  161. agent_os/stateless.py +742 -0
  162. agent_os/supervisor.py +148 -0
  163. agent_os/task_outcome.py +148 -0
  164. agent_os/transparency.py +181 -0
  165. agent_os/trust_root.py +128 -0
  166. agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
  167. agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
  168. agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
  169. agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
  170. agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
  171. agent_os_observability/__init__.py +27 -0
  172. agent_os_observability/dashboards.py +898 -0
  173. agent_os_observability/metrics.py +398 -0
  174. agent_os_observability/server.py +223 -0
  175. agent_os_observability/tracer.py +232 -0
  176. agent_primitives/__init__.py +24 -0
  177. agent_primitives/failures.py +84 -0
  178. agent_primitives/py.typed +0 -0
  179. amb_core/__init__.py +177 -0
  180. amb_core/adapters/__init__.py +57 -0
  181. amb_core/adapters/aws_sqs_broker.py +376 -0
  182. amb_core/adapters/azure_servicebus_broker.py +340 -0
  183. amb_core/adapters/kafka_broker.py +260 -0
  184. amb_core/adapters/nats_broker.py +285 -0
  185. amb_core/adapters/rabbitmq_broker.py +235 -0
  186. amb_core/adapters/redis_broker.py +262 -0
  187. amb_core/broker.py +145 -0
  188. amb_core/bus.py +481 -0
  189. amb_core/cloudevents.py +509 -0
  190. amb_core/dlq.py +345 -0
  191. amb_core/hf_utils.py +536 -0
  192. amb_core/memory_broker.py +410 -0
  193. amb_core/models.py +141 -0
  194. amb_core/persistence.py +529 -0
  195. amb_core/schema.py +294 -0
  196. amb_core/tracing.py +358 -0
  197. atr/__init__.py +640 -0
  198. atr/access.py +348 -0
  199. atr/composition.py +645 -0
  200. atr/decorator.py +357 -0
  201. atr/executor.py +384 -0
  202. atr/health.py +557 -0
  203. atr/hf_utils.py +449 -0
  204. atr/injection.py +422 -0
  205. atr/metrics.py +440 -0
  206. atr/policies.py +403 -0
  207. atr/py.typed +2 -0
  208. atr/registry.py +452 -0
  209. atr/schema.py +480 -0
  210. atr/tools/safe/__init__.py +75 -0
  211. atr/tools/safe/calculator.py +467 -0
  212. atr/tools/safe/datetime_tool.py +443 -0
  213. atr/tools/safe/file_reader.py +402 -0
  214. atr/tools/safe/http_client.py +316 -0
  215. atr/tools/safe/json_parser.py +374 -0
  216. atr/tools/safe/text_tool.py +537 -0
  217. atr/tools/safe/toolkit.py +175 -0
  218. caas/__init__.py +162 -0
  219. caas/api/__init__.py +7 -0
  220. caas/api/server.py +1328 -0
  221. caas/caching.py +834 -0
  222. caas/cli.py +210 -0
  223. caas/conversation.py +223 -0
  224. caas/decay.py +72 -0
  225. caas/detection/__init__.py +9 -0
  226. caas/detection/detector.py +238 -0
  227. caas/enrichment.py +130 -0
  228. caas/gateway/__init__.py +27 -0
  229. caas/gateway/trust_gateway.py +474 -0
  230. caas/hf_utils.py +479 -0
  231. caas/ingestion/__init__.py +23 -0
  232. caas/ingestion/processors.py +253 -0
  233. caas/ingestion/structure_parser.py +188 -0
  234. caas/models.py +356 -0
  235. caas/pragmatic_truth.py +444 -0
  236. caas/routing/__init__.py +10 -0
  237. caas/routing/heuristic_router.py +58 -0
  238. caas/storage/__init__.py +9 -0
  239. caas/storage/store.py +389 -0
  240. caas/triad.py +213 -0
  241. caas/tuning/__init__.py +9 -0
  242. caas/tuning/tuner.py +329 -0
  243. caas/vfs/__init__.py +14 -0
  244. caas/vfs/filesystem.py +452 -0
  245. cmvk/__init__.py +218 -0
  246. cmvk/audit.py +402 -0
  247. cmvk/benchmarks.py +478 -0
  248. cmvk/constitutional.py +904 -0
  249. cmvk/hf_utils.py +301 -0
  250. cmvk/metrics.py +473 -0
  251. cmvk/profiles.py +300 -0
  252. cmvk/py.typed +0 -0
  253. cmvk/types.py +12 -0
  254. cmvk/verification.py +956 -0
  255. emk/__init__.py +89 -0
  256. emk/causal.py +352 -0
  257. emk/hf_utils.py +421 -0
  258. emk/indexer.py +83 -0
  259. emk/py.typed +0 -0
  260. emk/schema.py +204 -0
  261. emk/sleep_cycle.py +347 -0
  262. emk/store.py +281 -0
  263. iatp/__init__.py +166 -0
  264. iatp/attestation.py +461 -0
  265. iatp/cli.py +317 -0
  266. iatp/hf_utils.py +472 -0
  267. iatp/ipc_pipes.py +580 -0
  268. iatp/main.py +412 -0
  269. iatp/models/__init__.py +447 -0
  270. iatp/policy_engine.py +337 -0
  271. iatp/py.typed +2 -0
  272. iatp/recovery.py +321 -0
  273. iatp/security/__init__.py +270 -0
  274. iatp/sidecar/__init__.py +519 -0
  275. iatp/telemetry/__init__.py +164 -0
  276. iatp/tests/__init__.py +1 -0
  277. iatp/tests/test_attestation.py +370 -0
  278. iatp/tests/test_cli.py +131 -0
  279. iatp/tests/test_ed25519_attestation.py +211 -0
  280. iatp/tests/test_models.py +130 -0
  281. iatp/tests/test_policy_engine.py +347 -0
  282. iatp/tests/test_recovery.py +281 -0
  283. iatp/tests/test_security.py +222 -0
  284. iatp/tests/test_sidecar.py +167 -0
  285. iatp/tests/test_telemetry.py +175 -0
  286. mcp_kernel_server/__init__.py +28 -0
  287. mcp_kernel_server/cli.py +274 -0
  288. mcp_kernel_server/resources.py +217 -0
  289. mcp_kernel_server/server.py +564 -0
  290. mcp_kernel_server/tools.py +1174 -0
  291. mute_agent/__init__.py +68 -0
  292. mute_agent/core/__init__.py +1 -0
  293. mute_agent/core/execution_agent.py +166 -0
  294. mute_agent/core/handshake_protocol.py +201 -0
  295. mute_agent/core/reasoning_agent.py +238 -0
  296. mute_agent/knowledge_graph/__init__.py +1 -0
  297. mute_agent/knowledge_graph/graph_elements.py +65 -0
  298. mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
  299. mute_agent/knowledge_graph/subgraph.py +224 -0
  300. mute_agent/listener/__init__.py +43 -0
  301. mute_agent/listener/adapters/__init__.py +31 -0
  302. mute_agent/listener/adapters/base_adapter.py +189 -0
  303. mute_agent/listener/adapters/caas_adapter.py +344 -0
  304. mute_agent/listener/adapters/control_plane_adapter.py +436 -0
  305. mute_agent/listener/adapters/iatp_adapter.py +332 -0
  306. mute_agent/listener/adapters/scak_adapter.py +251 -0
  307. mute_agent/listener/listener.py +610 -0
  308. mute_agent/listener/state_observer.py +436 -0
  309. mute_agent/listener/threshold_config.py +313 -0
  310. mute_agent/super_system/__init__.py +1 -0
  311. mute_agent/super_system/router.py +204 -0
  312. mute_agent/visualization/__init__.py +10 -0
  313. mute_agent/visualization/graph_debugger.py +502 -0
  314. nexus/README.md +60 -0
  315. nexus/__init__.py +51 -0
  316. nexus/arbiter.py +359 -0
  317. nexus/client.py +466 -0
  318. nexus/dmz.py +444 -0
  319. nexus/escrow.py +430 -0
  320. nexus/exceptions.py +286 -0
  321. nexus/pyproject.toml +36 -0
  322. nexus/registry.py +393 -0
  323. nexus/reputation.py +425 -0
  324. nexus/schemas/__init__.py +51 -0
  325. nexus/schemas/compliance.py +276 -0
  326. nexus/schemas/escrow.py +251 -0
  327. nexus/schemas/manifest.py +225 -0
  328. nexus/schemas/receipt.py +208 -0
  329. nexus/tests/__init__.py +0 -0
  330. nexus/tests/conftest.py +146 -0
  331. nexus/tests/test_arbiter.py +192 -0
  332. nexus/tests/test_dmz.py +194 -0
  333. nexus/tests/test_escrow.py +276 -0
  334. nexus/tests/test_exceptions.py +225 -0
  335. nexus/tests/test_registry.py +232 -0
  336. nexus/tests/test_reputation.py +328 -0
  337. nexus/tests/test_schemas.py +295 -0
cmvk/audit.py ADDED
@@ -0,0 +1,402 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ CMVK Audit Trail Module
5
+
6
+ Provides immutable audit logging for verification operations.
7
+ All verifications can be logged with timestamps, inputs, and results
8
+ for compliance and forensic analysis.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import hashlib
14
+ import json
15
+ import threading
16
+ import uuid
17
+ from dataclasses import asdict, dataclass, field
18
+ from datetime import UTC, datetime
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ import numpy as np
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class AuditEntry:
27
+ """
28
+ Immutable audit record for a single verification.
29
+
30
+ All fields are frozen to ensure auditability.
31
+
32
+ Attributes:
33
+ id: Unique identifier for this verification
34
+ timestamp: UTC timestamp of verification
35
+ operation: Type of verification operation
36
+ inputs_hash: SHA-256 hash of input data (for privacy)
37
+ result_summary: Summary of verification result
38
+ drift_score: The drift score from verification
39
+ confidence: The confidence score
40
+ metric_used: Distance metric used
41
+ profile_used: Threshold profile applied (if any)
42
+ passed: Whether verification passed thresholds
43
+ metadata: Additional context (user, session, etc.)
44
+ checksum: Integrity checksum for this entry
45
+ """
46
+
47
+ id: str
48
+ timestamp: str
49
+ operation: str
50
+ inputs_hash: str
51
+ result_summary: dict
52
+ drift_score: float
53
+ confidence: float
54
+ metric_used: str
55
+ profile_used: str | None
56
+ passed: bool
57
+ metadata: dict
58
+ checksum: str
59
+
60
+ def to_dict(self) -> dict:
61
+ """Convert to dictionary for serialization."""
62
+ return asdict(self)
63
+
64
+ def verify_integrity(self) -> bool:
65
+ """Verify the entry's checksum is valid."""
66
+ computed = _compute_checksum(
67
+ self.id,
68
+ self.timestamp,
69
+ self.operation,
70
+ self.inputs_hash,
71
+ self.drift_score,
72
+ self.confidence,
73
+ )
74
+ return computed == self.checksum
75
+
76
+
77
+ @dataclass
78
+ class AuditTrail:
79
+ """
80
+ Audit trail manager for verification operations.
81
+
82
+ Maintains an immutable log of all verifications with optional
83
+ persistence to file.
84
+
85
+ Thread-safe for concurrent verifications.
86
+ """
87
+
88
+ entries: list[AuditEntry] = field(default_factory=list)
89
+ persist_path: Path | None = None
90
+ auto_persist: bool = False
91
+ _lock: threading.Lock = field(default_factory=threading.Lock, repr=False)
92
+
93
+ def __post_init__(self) -> None:
94
+ """Load existing entries if persist path exists."""
95
+ if self.persist_path and self.persist_path.exists():
96
+ self._load_from_file()
97
+
98
+ def log(
99
+ self,
100
+ operation: str,
101
+ inputs: dict[str, Any],
102
+ drift_score: float,
103
+ confidence: float,
104
+ metric_used: str = "cosine",
105
+ profile_used: str | None = None,
106
+ passed: bool = True,
107
+ result_details: dict | None = None,
108
+ metadata: dict | None = None,
109
+ ) -> AuditEntry:
110
+ """
111
+ Log a verification operation.
112
+
113
+ Args:
114
+ operation: Type of operation (e.g., "verify_embeddings")
115
+ inputs: Input data (will be hashed, not stored directly)
116
+ drift_score: Drift score from verification
117
+ confidence: Confidence score
118
+ metric_used: Distance metric used
119
+ profile_used: Threshold profile applied
120
+ passed: Whether verification passed
121
+ result_details: Additional result information
122
+ metadata: Additional context (user, session, etc.)
123
+
124
+ Returns:
125
+ The created AuditEntry
126
+ """
127
+ entry_id = str(uuid.uuid4())
128
+ timestamp = datetime.now(UTC).isoformat()
129
+ inputs_hash = _hash_inputs(inputs)
130
+
131
+ checksum = _compute_checksum(
132
+ entry_id,
133
+ timestamp,
134
+ operation,
135
+ inputs_hash,
136
+ drift_score,
137
+ confidence,
138
+ )
139
+
140
+ entry = AuditEntry(
141
+ id=entry_id,
142
+ timestamp=timestamp,
143
+ operation=operation,
144
+ inputs_hash=inputs_hash,
145
+ result_summary=result_details or {},
146
+ drift_score=drift_score,
147
+ confidence=confidence,
148
+ metric_used=metric_used,
149
+ profile_used=profile_used,
150
+ passed=passed,
151
+ metadata=metadata or {},
152
+ checksum=checksum,
153
+ )
154
+
155
+ with self._lock:
156
+ self.entries.append(entry)
157
+ if self.auto_persist and self.persist_path:
158
+ self._persist_entry(entry)
159
+
160
+ return entry
161
+
162
+ def get_entries(
163
+ self,
164
+ start_time: datetime | None = None,
165
+ end_time: datetime | None = None,
166
+ operation: str | None = None,
167
+ passed_only: bool | None = None,
168
+ ) -> list[AuditEntry]:
169
+ """
170
+ Query audit entries with optional filters.
171
+
172
+ Args:
173
+ start_time: Filter entries after this time
174
+ end_time: Filter entries before this time
175
+ operation: Filter by operation type
176
+ passed_only: If True, only passed; if False, only failed; if None, all
177
+
178
+ Returns:
179
+ List of matching AuditEntry records
180
+ """
181
+ with self._lock:
182
+ results = list(self.entries)
183
+
184
+ if start_time:
185
+ start_iso = start_time.isoformat()
186
+ results = [e for e in results if e.timestamp >= start_iso]
187
+
188
+ if end_time:
189
+ end_iso = end_time.isoformat()
190
+ results = [e for e in results if e.timestamp <= end_iso]
191
+
192
+ if operation:
193
+ results = [e for e in results if e.operation == operation]
194
+
195
+ if passed_only is not None:
196
+ results = [e for e in results if e.passed == passed_only]
197
+
198
+ return results
199
+
200
+ def get_statistics(self) -> dict:
201
+ """
202
+ Calculate summary statistics for the audit trail.
203
+
204
+ Returns:
205
+ Dictionary with counts, pass rates, and drift statistics
206
+ """
207
+ with self._lock:
208
+ entries = list(self.entries)
209
+
210
+ if not entries:
211
+ return {"total_entries": 0}
212
+
213
+ drift_scores = [e.drift_score for e in entries]
214
+ passed_count = sum(1 for e in entries if e.passed)
215
+
216
+ # Group by operation
217
+ by_operation: dict[str, list[AuditEntry]] = {}
218
+ for e in entries:
219
+ by_operation.setdefault(e.operation, []).append(e)
220
+
221
+ operation_stats = {
222
+ op: {
223
+ "count": len(ops),
224
+ "pass_rate": sum(1 for e in ops if e.passed) / len(ops),
225
+ "mean_drift": float(np.mean([e.drift_score for e in ops])),
226
+ }
227
+ for op, ops in by_operation.items()
228
+ }
229
+
230
+ return {
231
+ "total_entries": len(entries),
232
+ "passed_count": passed_count,
233
+ "failed_count": len(entries) - passed_count,
234
+ "pass_rate": passed_count / len(entries),
235
+ "mean_drift": float(np.mean(drift_scores)),
236
+ "std_drift": float(np.std(drift_scores)),
237
+ "min_drift": float(np.min(drift_scores)),
238
+ "max_drift": float(np.max(drift_scores)),
239
+ "by_operation": operation_stats,
240
+ }
241
+
242
+ def verify_integrity(self) -> tuple[bool, list[str]]:
243
+ """
244
+ Verify integrity of all audit entries.
245
+
246
+ Returns:
247
+ Tuple of (all_valid, list of invalid entry IDs)
248
+ """
249
+ invalid_ids = []
250
+ with self._lock:
251
+ for entry in self.entries:
252
+ if not entry.verify_integrity():
253
+ invalid_ids.append(entry.id)
254
+
255
+ return len(invalid_ids) == 0, invalid_ids
256
+
257
+ def export_json(self, path: Path | str) -> None:
258
+ """Export audit trail to JSON file."""
259
+ path = Path(path)
260
+ with self._lock:
261
+ data = {
262
+ "exported_at": datetime.now(UTC).isoformat(),
263
+ "entry_count": len(self.entries),
264
+ "entries": [e.to_dict() for e in self.entries],
265
+ }
266
+
267
+ path.write_text(json.dumps(data, indent=2))
268
+
269
+ def export_csv(self, path: Path | str) -> None:
270
+ """Export audit trail to CSV file."""
271
+ import csv
272
+
273
+ path = Path(path)
274
+ with self._lock:
275
+ entries = list(self.entries)
276
+
277
+ if not entries:
278
+ path.write_text("")
279
+ return
280
+
281
+ fieldnames = [
282
+ "id",
283
+ "timestamp",
284
+ "operation",
285
+ "drift_score",
286
+ "confidence",
287
+ "metric_used",
288
+ "profile_used",
289
+ "passed",
290
+ "inputs_hash",
291
+ ]
292
+
293
+ with path.open("w", newline="") as f:
294
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
295
+ writer.writeheader()
296
+ for entry in entries:
297
+ writer.writerow({k: getattr(entry, k) for k in fieldnames})
298
+
299
+ def _load_from_file(self) -> None:
300
+ """Load entries from persist file."""
301
+ if not self.persist_path or not self.persist_path.exists():
302
+ return
303
+
304
+ try:
305
+ data = json.loads(self.persist_path.read_text())
306
+ for entry_dict in data.get("entries", []):
307
+ self.entries.append(AuditEntry(**entry_dict))
308
+ except (json.JSONDecodeError, TypeError) as e:
309
+ # Log warning but don't fail
310
+ print(f"Warning: Could not load audit trail from {self.persist_path}: {e}")
311
+
312
+ def _persist_entry(self, entry: AuditEntry) -> None:
313
+ """Append entry to persist file."""
314
+ if not self.persist_path:
315
+ return
316
+
317
+ # Read existing or create new
318
+ if self.persist_path.exists():
319
+ try:
320
+ data = json.loads(self.persist_path.read_text())
321
+ except json.JSONDecodeError:
322
+ data = {"entries": []}
323
+ else:
324
+ data = {"entries": []}
325
+
326
+ data["entries"].append(entry.to_dict())
327
+ data["updated_at"] = datetime.now(UTC).isoformat()
328
+ data["entry_count"] = len(data["entries"])
329
+
330
+ self.persist_path.write_text(json.dumps(data, indent=2))
331
+
332
+ def clear(self) -> None:
333
+ """Clear all entries (use with caution)."""
334
+ with self._lock:
335
+ self.entries.clear()
336
+
337
+
338
+ # ============================================================================
339
+ # Helper Functions
340
+ # ============================================================================
341
+
342
+
343
+ def _hash_inputs(inputs: dict[str, Any]) -> str:
344
+ """Create SHA-256 hash of inputs for privacy-preserving audit."""
345
+
346
+ def serialize(obj: Any) -> Any:
347
+ """Convert objects to JSON-serializable format."""
348
+ if isinstance(obj, np.ndarray) or hasattr(obj, "tolist"):
349
+ return obj.tolist()
350
+ elif hasattr(obj, "__dict__"):
351
+ return str(type(obj).__name__)
352
+ return obj
353
+
354
+ # Create deterministic JSON representation
355
+ serialized = json.dumps(
356
+ {k: serialize(v) for k, v in sorted(inputs.items())},
357
+ sort_keys=True,
358
+ )
359
+ return hashlib.sha256(serialized.encode()).hexdigest()
360
+
361
+
362
+ def _compute_checksum(*values: Any) -> str:
363
+ """Compute checksum for audit entry integrity."""
364
+ content = "|".join(str(v) for v in values)
365
+ return hashlib.sha256(content.encode()).hexdigest()[:16]
366
+
367
+
368
+ # ============================================================================
369
+ # Global Audit Trail Instance
370
+ # ============================================================================
371
+
372
+ _global_audit_trail: AuditTrail | None = None
373
+
374
+
375
+ def get_audit_trail() -> AuditTrail:
376
+ """Get or create the global audit trail instance."""
377
+ global _global_audit_trail
378
+ if _global_audit_trail is None:
379
+ _global_audit_trail = AuditTrail()
380
+ return _global_audit_trail
381
+
382
+
383
+ def configure_audit_trail(
384
+ persist_path: Path | str | None = None,
385
+ auto_persist: bool = False,
386
+ ) -> AuditTrail:
387
+ """
388
+ Configure the global audit trail.
389
+
390
+ Args:
391
+ persist_path: Path to persist audit entries
392
+ auto_persist: Whether to automatically persist each entry
393
+
394
+ Returns:
395
+ The configured AuditTrail instance
396
+ """
397
+ global _global_audit_trail
398
+ _global_audit_trail = AuditTrail(
399
+ persist_path=Path(persist_path) if persist_path else None,
400
+ auto_persist=auto_persist,
401
+ )
402
+ return _global_audit_trail