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
nexus/escrow.py ADDED
@@ -0,0 +1,430 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ Proof of Outcome / Escrow Manager
5
+
6
+ Implements the "Reward" mechanism where agents bet on task outcomes.
7
+ Credits are escrowed and released based on SCAK validation.
8
+ """
9
+
10
+ from datetime import datetime, timedelta, timezone
11
+ from typing import Optional, Literal
12
+ import hashlib
13
+ import uuid
14
+ import asyncio
15
+
16
+ from .schemas.escrow import (
17
+ EscrowRequest,
18
+ EscrowReceipt,
19
+ EscrowStatus,
20
+ EscrowRelease,
21
+ EscrowResolution,
22
+ )
23
+ from .schemas.receipt import JobCompletionReceipt, SignedReceipt
24
+ from .reputation import ReputationEngine
25
+ from .exceptions import (
26
+ EscrowNotFoundError,
27
+ EscrowExpiredError,
28
+ EscrowAlreadyResolvedError,
29
+ InsufficientCreditsError,
30
+ )
31
+
32
+
33
+ class EscrowManager:
34
+ """
35
+ Manages escrow lifecycle for inter-agent tasks.
36
+
37
+ The "Reward" OS - agents don't just talk, they bet on outcomes.
38
+ """
39
+
40
+ def __init__(self, reputation_engine: Optional[ReputationEngine] = None):
41
+ self.reputation_engine = reputation_engine or ReputationEngine()
42
+
43
+ # In-memory storage (would be database in production)
44
+ self._escrows: dict[str, EscrowReceipt] = {}
45
+ self._agent_credits: dict[str, int] = {} # DID -> credits
46
+
47
+ # Configuration
48
+ self.default_timeout = 3600 # 1 hour
49
+ self.max_credits_per_escrow = 10000
50
+
51
+ async def create_escrow(
52
+ self,
53
+ request: EscrowRequest,
54
+ requester_signature: str,
55
+ ) -> EscrowReceipt:
56
+ """
57
+ Create an escrow for a task.
58
+
59
+ Locks credits from requester until task completion.
60
+ """
61
+ # Check requester has enough credits
62
+ available = self._agent_credits.get(request.requester_did, 0)
63
+ if available < request.credits:
64
+ raise InsufficientCreditsError(
65
+ request.requester_did,
66
+ required=request.credits,
67
+ available=available,
68
+ )
69
+
70
+ # Generate escrow ID
71
+ escrow_id = f"escrow_{uuid.uuid4().hex[:16]}"
72
+
73
+ # Create receipt
74
+ receipt = EscrowReceipt.from_request(
75
+ escrow_id=escrow_id,
76
+ request=request,
77
+ requester_signature=requester_signature,
78
+ )
79
+
80
+ # Lock credits
81
+ self._agent_credits[request.requester_did] -= request.credits
82
+
83
+ # Sign from Nexus
84
+ receipt.nexus_signature = self._sign_escrow(escrow_id, request)
85
+
86
+ # Store
87
+ self._escrows[escrow_id] = receipt
88
+
89
+ return receipt
90
+
91
+ async def activate_escrow(self, escrow_id: str) -> EscrowReceipt:
92
+ """Mark escrow as active (task in progress)."""
93
+ receipt = self._get_escrow(escrow_id)
94
+
95
+ if receipt.status != EscrowStatus.PENDING:
96
+ raise EscrowAlreadyResolvedError(escrow_id, receipt.status.value)
97
+
98
+ receipt.status = EscrowStatus.ACTIVE
99
+ receipt.activated_at = datetime.now(timezone.utc)
100
+
101
+ return receipt
102
+
103
+ async def complete_task(
104
+ self,
105
+ escrow_id: str,
106
+ output_hash: str,
107
+ duration_ms: int,
108
+ provider_signature: str,
109
+ ) -> EscrowReceipt:
110
+ """Mark task as complete, awaiting validation."""
111
+ receipt = self._get_escrow(escrow_id)
112
+
113
+ if receipt.status != EscrowStatus.ACTIVE:
114
+ raise EscrowAlreadyResolvedError(escrow_id, receipt.status.value)
115
+
116
+ if receipt.is_expired():
117
+ receipt.status = EscrowStatus.EXPIRED
118
+ raise EscrowExpiredError(escrow_id, str(receipt.expires_at))
119
+
120
+ receipt.status = EscrowStatus.AWAITING_VALIDATION
121
+ receipt.completed_at = datetime.now(timezone.utc)
122
+
123
+ return receipt
124
+
125
+ async def release_escrow(
126
+ self,
127
+ release: EscrowRelease,
128
+ ) -> EscrowResolution:
129
+ """
130
+ Release escrow based on outcome.
131
+
132
+ - success: Credits go to provider, provider reputation +2
133
+ - failure: Credits return to requester, provider reputation -10
134
+ - dispute: Escalate to Arbiter
135
+ """
136
+ receipt = self._get_escrow(release.escrow_id)
137
+
138
+ if not receipt.is_active():
139
+ raise EscrowAlreadyResolvedError(release.escrow_id, receipt.status.value)
140
+
141
+ request = receipt.request
142
+ credits = request.credits
143
+
144
+ # Determine resolution based on outcome
145
+ if release.outcome == "success":
146
+ # Validate with SCAK if required
147
+ if request.require_scak_validation:
148
+ if not release.scak_validated:
149
+ raise ValueError("SCAK validation required but not performed")
150
+ if not release.scak_passed:
151
+ # SCAK failed - treat as failure
152
+ return await self._resolve_failure(receipt, release)
153
+
154
+ return await self._resolve_success(receipt, release)
155
+
156
+ elif release.outcome == "failure":
157
+ return await self._resolve_failure(receipt, release)
158
+
159
+ else: # dispute
160
+ return await self._resolve_dispute(receipt, release)
161
+
162
+ async def _resolve_success(
163
+ self,
164
+ receipt: EscrowReceipt,
165
+ release: EscrowRelease,
166
+ ) -> EscrowResolution:
167
+ """Resolve escrow as success - credits to provider."""
168
+ request = receipt.request
169
+
170
+ # Transfer credits to provider
171
+ self._agent_credits[request.provider_did] = (
172
+ self._agent_credits.get(request.provider_did, 0) + request.credits
173
+ )
174
+
175
+ # Update reputation
176
+ self.reputation_engine.record_task_outcome(request.provider_did, "success")
177
+
178
+ # Update receipt
179
+ receipt.status = EscrowStatus.RELEASED
180
+ receipt.resolved_at = datetime.now(timezone.utc)
181
+
182
+ return EscrowResolution(
183
+ escrow_id=receipt.escrow_id,
184
+ final_status=EscrowStatus.RELEASED,
185
+ credits_to_provider=request.credits,
186
+ credits_to_requester=0,
187
+ provider_reputation_change=2,
188
+ requester_reputation_change=0,
189
+ resolution_reason="Task completed successfully",
190
+ resolved_by="automatic",
191
+ nexus_signature=self._sign_resolution(receipt.escrow_id, "success"),
192
+ )
193
+
194
+ async def _resolve_failure(
195
+ self,
196
+ receipt: EscrowReceipt,
197
+ release: EscrowRelease,
198
+ ) -> EscrowResolution:
199
+ """Resolve escrow as failure - credits returned to requester."""
200
+ request = receipt.request
201
+
202
+ # Return credits to requester
203
+ self._agent_credits[request.requester_did] = (
204
+ self._agent_credits.get(request.requester_did, 0) + request.credits
205
+ )
206
+
207
+ # Update reputation
208
+ self.reputation_engine.record_task_outcome(request.provider_did, "failure")
209
+
210
+ # Update receipt
211
+ receipt.status = EscrowStatus.REFUNDED
212
+ receipt.resolved_at = datetime.now(timezone.utc)
213
+
214
+ return EscrowResolution(
215
+ escrow_id=receipt.escrow_id,
216
+ final_status=EscrowStatus.REFUNDED,
217
+ credits_to_provider=0,
218
+ credits_to_requester=request.credits,
219
+ provider_reputation_change=-10,
220
+ requester_reputation_change=0,
221
+ resolution_reason="Task failed",
222
+ resolved_by="automatic",
223
+ nexus_signature=self._sign_resolution(receipt.escrow_id, "failure"),
224
+ )
225
+
226
+ async def _resolve_dispute(
227
+ self,
228
+ receipt: EscrowReceipt,
229
+ release: EscrowRelease,
230
+ ) -> EscrowResolution:
231
+ """Mark escrow as disputed - to be resolved by Arbiter."""
232
+ receipt.status = EscrowStatus.DISPUTED
233
+
234
+ # Credits remain locked until Arbiter decides
235
+ return EscrowResolution(
236
+ escrow_id=receipt.escrow_id,
237
+ final_status=EscrowStatus.DISPUTED,
238
+ credits_to_provider=0,
239
+ credits_to_requester=0,
240
+ provider_reputation_change=0,
241
+ requester_reputation_change=0,
242
+ resolution_reason=f"Dispute raised: {release.dispute_reason}",
243
+ resolved_by="arbiter",
244
+ nexus_signature=self._sign_resolution(receipt.escrow_id, "dispute"),
245
+ )
246
+
247
+ async def expire_escrow(self, escrow_id: str) -> EscrowResolution:
248
+ """Handle escrow expiration - credits returned to requester."""
249
+ receipt = self._get_escrow(escrow_id)
250
+ request = receipt.request
251
+
252
+ # Return credits
253
+ self._agent_credits[request.requester_did] = (
254
+ self._agent_credits.get(request.requester_did, 0) + request.credits
255
+ )
256
+
257
+ # Small reputation penalty for provider
258
+ self.reputation_engine.record_task_outcome(request.provider_did, "failure")
259
+
260
+ receipt.status = EscrowStatus.EXPIRED
261
+ receipt.resolved_at = datetime.now(timezone.utc)
262
+
263
+ return EscrowResolution(
264
+ escrow_id=escrow_id,
265
+ final_status=EscrowStatus.EXPIRED,
266
+ credits_to_provider=0,
267
+ credits_to_requester=request.credits,
268
+ provider_reputation_change=-5,
269
+ requester_reputation_change=0,
270
+ resolution_reason="Escrow expired without completion",
271
+ resolved_by="timeout",
272
+ nexus_signature=self._sign_resolution(escrow_id, "expired"),
273
+ )
274
+
275
+ def get_escrow(self, escrow_id: str) -> EscrowReceipt:
276
+ """Get escrow by ID (public method)."""
277
+ return self._get_escrow(escrow_id)
278
+
279
+ def get_agent_credits(self, agent_did: str) -> int:
280
+ """Get credit balance for an agent."""
281
+ return self._agent_credits.get(agent_did, 0)
282
+
283
+ def add_credits(self, agent_did: str, amount: int) -> int:
284
+ """Add credits to an agent's balance."""
285
+ self._agent_credits[agent_did] = self._agent_credits.get(agent_did, 0) + amount
286
+ return self._agent_credits[agent_did]
287
+
288
+ def list_escrows(
289
+ self,
290
+ agent_did: Optional[str] = None,
291
+ status: Optional[EscrowStatus] = None,
292
+ ) -> list[EscrowReceipt]:
293
+ """List escrows with optional filtering."""
294
+ results = list(self._escrows.values())
295
+
296
+ if agent_did:
297
+ results = [
298
+ e for e in results
299
+ if e.request.requester_did == agent_did or e.request.provider_did == agent_did
300
+ ]
301
+
302
+ if status:
303
+ results = [e for e in results if e.status == status]
304
+
305
+ return results
306
+
307
+ def _get_escrow(self, escrow_id: str) -> EscrowReceipt:
308
+ """Get escrow by ID or raise error."""
309
+ if escrow_id not in self._escrows:
310
+ raise EscrowNotFoundError(escrow_id)
311
+ return self._escrows[escrow_id]
312
+
313
+ def _sign_escrow(self, escrow_id: str, request: EscrowRequest) -> str:
314
+ """Generate Nexus signature for escrow."""
315
+ data = f"{escrow_id}:{request.task_hash}:{request.credits}"
316
+ return f"nexus_escrow_{hashlib.sha256(data.encode()).hexdigest()[:32]}"
317
+
318
+ def _sign_resolution(self, escrow_id: str, outcome: str) -> str:
319
+ """Generate Nexus signature for resolution."""
320
+ data = f"{escrow_id}:{outcome}:{datetime.now(timezone.utc).isoformat()}"
321
+ return f"nexus_res_{hashlib.sha256(data.encode()).hexdigest()[:32]}"
322
+
323
+
324
+ class ProofOfOutcome:
325
+ """
326
+ High-level API for the Proof-of-Outcome mechanism.
327
+
328
+ Wraps EscrowManager with SCAK validation integration.
329
+ """
330
+
331
+ def __init__(
332
+ self,
333
+ escrow_manager: Optional[EscrowManager] = None,
334
+ scak_validator: Optional[any] = None, # Would be SCAK validator
335
+ ):
336
+ self.escrow_manager = escrow_manager or EscrowManager()
337
+ self.scak_validator = scak_validator
338
+
339
+ async def create_escrow(
340
+ self,
341
+ requester_did: str,
342
+ provider_did: str,
343
+ task_hash: str,
344
+ credits: int,
345
+ timeout_seconds: int = 3600,
346
+ require_scak: bool = True,
347
+ drift_threshold: float = 0.15,
348
+ ) -> EscrowReceipt:
349
+ """Create an escrow for a task."""
350
+ request = EscrowRequest(
351
+ requester_did=requester_did,
352
+ provider_did=provider_did,
353
+ task_hash=task_hash,
354
+ credits=credits,
355
+ timeout_seconds=timeout_seconds,
356
+ require_scak_validation=require_scak,
357
+ scak_drift_threshold=drift_threshold,
358
+ )
359
+
360
+ # TODO: Generate actual signature
361
+ signature = f"sig_{requester_did}_{task_hash[:8]}"
362
+
363
+ return await self.escrow_manager.create_escrow(request, signature)
364
+
365
+ async def validate_outcome(
366
+ self,
367
+ escrow_id: str,
368
+ flight_recorder_log: bytes,
369
+ claimed_outcome: Literal["success", "failure"],
370
+ ) -> tuple[bool, Optional[float]]:
371
+ """
372
+ Validate task outcome using SCAK.
373
+
374
+ Replays the flight recorder log against the Control Plane
375
+ to deterministically verify the claimed outcome.
376
+
377
+ Returns:
378
+ Tuple of (passed, drift_score)
379
+ """
380
+ receipt = self.escrow_manager.get_escrow(escrow_id)
381
+
382
+ if self.scak_validator is None:
383
+ # No SCAK validator - assume success
384
+ return True, 0.0
385
+
386
+ # Validate with SCAK
387
+ # drift_score = await self.scak_validator.validate(flight_recorder_log)
388
+ # For now, simulate
389
+ drift_score = 0.05
390
+
391
+ threshold = receipt.request.scak_drift_threshold
392
+ passed = drift_score <= threshold
393
+
394
+ return passed, drift_score
395
+
396
+ async def release_escrow(
397
+ self,
398
+ escrow_id: str,
399
+ outcome: Literal["success", "failure", "dispute"],
400
+ output_hash: Optional[str] = None,
401
+ duration_ms: Optional[int] = None,
402
+ scak_drift_score: Optional[float] = None,
403
+ dispute_reason: Optional[str] = None,
404
+ ) -> EscrowResolution:
405
+ """
406
+ Release escrow based on outcome.
407
+
408
+ - success: Credits go to provider, provider reputation +2
409
+ - failure: Credits return to requester, provider reputation -10
410
+ - dispute: Escalate to Arbiter
411
+ """
412
+ receipt = self.escrow_manager.get_escrow(escrow_id)
413
+
414
+ # Determine if SCAK passed
415
+ scak_passed = None
416
+ if scak_drift_score is not None:
417
+ scak_passed = scak_drift_score <= receipt.request.scak_drift_threshold
418
+
419
+ release = EscrowRelease(
420
+ escrow_id=escrow_id,
421
+ outcome=outcome,
422
+ output_hash=output_hash,
423
+ duration_ms=duration_ms,
424
+ scak_validated=scak_drift_score is not None,
425
+ scak_drift_score=scak_drift_score,
426
+ scak_passed=scak_passed,
427
+ dispute_reason=dispute_reason,
428
+ )
429
+
430
+ return await self.escrow_manager.release_escrow(release)