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.
- agent_control_plane/__init__.py +662 -0
- agent_control_plane/a2a_adapter.py +543 -0
- agent_control_plane/adapter.py +417 -0
- agent_control_plane/agent_hibernation.py +394 -0
- agent_control_plane/agent_kernel.py +470 -0
- agent_control_plane/compliance.py +720 -0
- agent_control_plane/constraint_graphs.py +478 -0
- agent_control_plane/control_plane.py +854 -0
- agent_control_plane/example_executors.py +195 -0
- agent_control_plane/execution_engine.py +231 -0
- agent_control_plane/flight_recorder.py +846 -0
- agent_control_plane/governance_layer.py +435 -0
- agent_control_plane/hf_utils.py +563 -0
- agent_control_plane/interfaces/__init__.py +55 -0
- agent_control_plane/interfaces/kernel_interface.py +361 -0
- agent_control_plane/interfaces/plugin_interface.py +497 -0
- agent_control_plane/interfaces/protocol_interfaces.py +387 -0
- agent_control_plane/kernel_space.py +1009 -0
- agent_control_plane/langchain_adapter.py +424 -0
- agent_control_plane/lifecycle.py +3113 -0
- agent_control_plane/mcp_adapter.py +653 -0
- agent_control_plane/ml_safety.py +563 -0
- agent_control_plane/multimodal.py +727 -0
- agent_control_plane/mute_agent.py +422 -0
- agent_control_plane/observability.py +787 -0
- agent_control_plane/orchestrator.py +482 -0
- agent_control_plane/plugin_registry.py +750 -0
- agent_control_plane/policy_engine.py +954 -0
- agent_control_plane/process_isolation.py +777 -0
- agent_control_plane/shadow_mode.py +310 -0
- agent_control_plane/signals.py +493 -0
- agent_control_plane/supervisor_agents.py +430 -0
- agent_control_plane/time_travel_debugger.py +557 -0
- agent_control_plane/tool_registry.py +452 -0
- agent_control_plane/vfs.py +697 -0
- agent_kernel/__init__.py +69 -0
- agent_kernel/analyzer.py +435 -0
- agent_kernel/auditor.py +36 -0
- agent_kernel/completeness_auditor.py +237 -0
- agent_kernel/detector.py +203 -0
- agent_kernel/kernel.py +744 -0
- agent_kernel/memory_manager.py +85 -0
- agent_kernel/models.py +374 -0
- agent_kernel/nudge_mechanism.py +263 -0
- agent_kernel/outcome_analyzer.py +338 -0
- agent_kernel/patcher.py +582 -0
- agent_kernel/semantic_analyzer.py +316 -0
- agent_kernel/semantic_purge.py +349 -0
- agent_kernel/simulator.py +449 -0
- agent_kernel/teacher.py +85 -0
- agent_kernel/triage.py +152 -0
- agent_os/__init__.py +409 -0
- agent_os/_adversarial_impl.py +200 -0
- agent_os/_circuit_breaker_impl.py +232 -0
- agent_os/_mcp_metrics.py +193 -0
- agent_os/adversarial.py +20 -0
- agent_os/agents_compat.py +490 -0
- agent_os/audit_logger.py +135 -0
- agent_os/base_agent.py +651 -0
- agent_os/circuit_breaker.py +34 -0
- agent_os/cli/__init__.py +659 -0
- agent_os/cli/cmd_audit.py +128 -0
- agent_os/cli/cmd_init.py +152 -0
- agent_os/cli/cmd_policy.py +41 -0
- agent_os/cli/cmd_policy_gen.py +180 -0
- agent_os/cli/cmd_validate.py +258 -0
- agent_os/cli/mcp_scan.py +265 -0
- agent_os/cli/output.py +192 -0
- agent_os/cli/policy_checker.py +330 -0
- agent_os/compat.py +74 -0
- agent_os/constraint_graph.py +234 -0
- agent_os/content_governance.py +140 -0
- agent_os/context_budget.py +305 -0
- agent_os/credential_redactor.py +224 -0
- agent_os/diff_policy.py +89 -0
- agent_os/egress_policy.py +159 -0
- agent_os/escalation.py +276 -0
- agent_os/event_bus.py +124 -0
- agent_os/exceptions.py +180 -0
- agent_os/execution_context_policy.py +141 -0
- agent_os/github_enterprise.py +96 -0
- agent_os/health.py +20 -0
- agent_os/integrations/__init__.py +279 -0
- agent_os/integrations/a2a_adapter.py +279 -0
- agent_os/integrations/agent_lightning/__init__.py +30 -0
- agent_os/integrations/anthropic_adapter.py +420 -0
- agent_os/integrations/autogen_adapter.py +620 -0
- agent_os/integrations/base.py +1137 -0
- agent_os/integrations/compat.py +229 -0
- agent_os/integrations/config.py +98 -0
- agent_os/integrations/conversation_guardian.py +957 -0
- agent_os/integrations/crewai_adapter.py +467 -0
- agent_os/integrations/drift_detector.py +425 -0
- agent_os/integrations/dry_run.py +124 -0
- agent_os/integrations/escalation.py +582 -0
- agent_os/integrations/gemini_adapter.py +364 -0
- agent_os/integrations/google_adk_adapter.py +633 -0
- agent_os/integrations/guardrails_adapter.py +394 -0
- agent_os/integrations/health.py +197 -0
- agent_os/integrations/langchain_adapter.py +654 -0
- agent_os/integrations/llamafirewall.py +343 -0
- agent_os/integrations/llamaindex_adapter.py +188 -0
- agent_os/integrations/logging.py +191 -0
- agent_os/integrations/maf_adapter.py +631 -0
- agent_os/integrations/mistral_adapter.py +365 -0
- agent_os/integrations/openai_adapter.py +816 -0
- agent_os/integrations/openai_agents_sdk.py +406 -0
- agent_os/integrations/policy_compose.py +171 -0
- agent_os/integrations/profiling.py +144 -0
- agent_os/integrations/pydantic_ai_adapter.py +420 -0
- agent_os/integrations/rate_limiter.py +130 -0
- agent_os/integrations/rbac.py +143 -0
- agent_os/integrations/registry.py +113 -0
- agent_os/integrations/scope_guard.py +303 -0
- agent_os/integrations/semantic_kernel_adapter.py +769 -0
- agent_os/integrations/smolagents_adapter.py +629 -0
- agent_os/integrations/templates.py +178 -0
- agent_os/integrations/token_budget.py +134 -0
- agent_os/integrations/tool_aliases.py +190 -0
- agent_os/integrations/webhooks.py +177 -0
- agent_os/lite.py +208 -0
- agent_os/mcp_gateway.py +385 -0
- agent_os/mcp_message_signer.py +273 -0
- agent_os/mcp_protocols.py +161 -0
- agent_os/mcp_response_scanner.py +232 -0
- agent_os/mcp_security.py +924 -0
- agent_os/mcp_session_auth.py +231 -0
- agent_os/mcp_sliding_rate_limiter.py +184 -0
- agent_os/memory_guard.py +409 -0
- agent_os/metrics.py +134 -0
- agent_os/mute.py +428 -0
- agent_os/mute_agent.py +209 -0
- agent_os/policies/__init__.py +77 -0
- agent_os/policies/async_evaluator.py +275 -0
- agent_os/policies/backends.py +670 -0
- agent_os/policies/bridge.py +169 -0
- agent_os/policies/budget.py +85 -0
- agent_os/policies/cli.py +294 -0
- agent_os/policies/conflict_resolution.py +270 -0
- agent_os/policies/data_classification.py +252 -0
- agent_os/policies/evaluator.py +239 -0
- agent_os/policies/policy_schema.json +228 -0
- agent_os/policies/rate_limiting.py +145 -0
- agent_os/policies/schema.py +115 -0
- agent_os/policies/shared.py +331 -0
- agent_os/prompt_injection.py +694 -0
- agent_os/providers.py +182 -0
- agent_os/py.typed +0 -0
- agent_os/retry.py +81 -0
- agent_os/reversibility.py +251 -0
- agent_os/sandbox.py +432 -0
- agent_os/sandbox_provider.py +140 -0
- agent_os/secure_codegen.py +525 -0
- agent_os/security_skills.py +538 -0
- agent_os/semantic_policy.py +422 -0
- agent_os/server/__init__.py +15 -0
- agent_os/server/__main__.py +25 -0
- agent_os/server/app.py +277 -0
- agent_os/server/models.py +104 -0
- agent_os/shift_left_metrics.py +130 -0
- agent_os/stateless.py +742 -0
- agent_os/supervisor.py +148 -0
- agent_os/task_outcome.py +148 -0
- agent_os/transparency.py +181 -0
- agent_os/trust_root.py +128 -0
- agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
- agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
- agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
- agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
- agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
- agent_os_observability/__init__.py +27 -0
- agent_os_observability/dashboards.py +898 -0
- agent_os_observability/metrics.py +398 -0
- agent_os_observability/server.py +223 -0
- agent_os_observability/tracer.py +232 -0
- agent_primitives/__init__.py +24 -0
- agent_primitives/failures.py +84 -0
- agent_primitives/py.typed +0 -0
- amb_core/__init__.py +177 -0
- amb_core/adapters/__init__.py +57 -0
- amb_core/adapters/aws_sqs_broker.py +376 -0
- amb_core/adapters/azure_servicebus_broker.py +340 -0
- amb_core/adapters/kafka_broker.py +260 -0
- amb_core/adapters/nats_broker.py +285 -0
- amb_core/adapters/rabbitmq_broker.py +235 -0
- amb_core/adapters/redis_broker.py +262 -0
- amb_core/broker.py +145 -0
- amb_core/bus.py +481 -0
- amb_core/cloudevents.py +509 -0
- amb_core/dlq.py +345 -0
- amb_core/hf_utils.py +536 -0
- amb_core/memory_broker.py +410 -0
- amb_core/models.py +141 -0
- amb_core/persistence.py +529 -0
- amb_core/schema.py +294 -0
- amb_core/tracing.py +358 -0
- atr/__init__.py +640 -0
- atr/access.py +348 -0
- atr/composition.py +645 -0
- atr/decorator.py +357 -0
- atr/executor.py +384 -0
- atr/health.py +557 -0
- atr/hf_utils.py +449 -0
- atr/injection.py +422 -0
- atr/metrics.py +440 -0
- atr/policies.py +403 -0
- atr/py.typed +2 -0
- atr/registry.py +452 -0
- atr/schema.py +480 -0
- atr/tools/safe/__init__.py +75 -0
- atr/tools/safe/calculator.py +467 -0
- atr/tools/safe/datetime_tool.py +443 -0
- atr/tools/safe/file_reader.py +402 -0
- atr/tools/safe/http_client.py +316 -0
- atr/tools/safe/json_parser.py +374 -0
- atr/tools/safe/text_tool.py +537 -0
- atr/tools/safe/toolkit.py +175 -0
- caas/__init__.py +162 -0
- caas/api/__init__.py +7 -0
- caas/api/server.py +1328 -0
- caas/caching.py +834 -0
- caas/cli.py +210 -0
- caas/conversation.py +223 -0
- caas/decay.py +72 -0
- caas/detection/__init__.py +9 -0
- caas/detection/detector.py +238 -0
- caas/enrichment.py +130 -0
- caas/gateway/__init__.py +27 -0
- caas/gateway/trust_gateway.py +474 -0
- caas/hf_utils.py +479 -0
- caas/ingestion/__init__.py +23 -0
- caas/ingestion/processors.py +253 -0
- caas/ingestion/structure_parser.py +188 -0
- caas/models.py +356 -0
- caas/pragmatic_truth.py +444 -0
- caas/routing/__init__.py +10 -0
- caas/routing/heuristic_router.py +58 -0
- caas/storage/__init__.py +9 -0
- caas/storage/store.py +389 -0
- caas/triad.py +213 -0
- caas/tuning/__init__.py +9 -0
- caas/tuning/tuner.py +329 -0
- caas/vfs/__init__.py +14 -0
- caas/vfs/filesystem.py +452 -0
- cmvk/__init__.py +218 -0
- cmvk/audit.py +402 -0
- cmvk/benchmarks.py +478 -0
- cmvk/constitutional.py +904 -0
- cmvk/hf_utils.py +301 -0
- cmvk/metrics.py +473 -0
- cmvk/profiles.py +300 -0
- cmvk/py.typed +0 -0
- cmvk/types.py +12 -0
- cmvk/verification.py +956 -0
- emk/__init__.py +89 -0
- emk/causal.py +352 -0
- emk/hf_utils.py +421 -0
- emk/indexer.py +83 -0
- emk/py.typed +0 -0
- emk/schema.py +204 -0
- emk/sleep_cycle.py +347 -0
- emk/store.py +281 -0
- iatp/__init__.py +166 -0
- iatp/attestation.py +461 -0
- iatp/cli.py +317 -0
- iatp/hf_utils.py +472 -0
- iatp/ipc_pipes.py +580 -0
- iatp/main.py +412 -0
- iatp/models/__init__.py +447 -0
- iatp/policy_engine.py +337 -0
- iatp/py.typed +2 -0
- iatp/recovery.py +321 -0
- iatp/security/__init__.py +270 -0
- iatp/sidecar/__init__.py +519 -0
- iatp/telemetry/__init__.py +164 -0
- iatp/tests/__init__.py +1 -0
- iatp/tests/test_attestation.py +370 -0
- iatp/tests/test_cli.py +131 -0
- iatp/tests/test_ed25519_attestation.py +211 -0
- iatp/tests/test_models.py +130 -0
- iatp/tests/test_policy_engine.py +347 -0
- iatp/tests/test_recovery.py +281 -0
- iatp/tests/test_security.py +222 -0
- iatp/tests/test_sidecar.py +167 -0
- iatp/tests/test_telemetry.py +175 -0
- mcp_kernel_server/__init__.py +28 -0
- mcp_kernel_server/cli.py +274 -0
- mcp_kernel_server/resources.py +217 -0
- mcp_kernel_server/server.py +564 -0
- mcp_kernel_server/tools.py +1174 -0
- mute_agent/__init__.py +68 -0
- mute_agent/core/__init__.py +1 -0
- mute_agent/core/execution_agent.py +166 -0
- mute_agent/core/handshake_protocol.py +201 -0
- mute_agent/core/reasoning_agent.py +238 -0
- mute_agent/knowledge_graph/__init__.py +1 -0
- mute_agent/knowledge_graph/graph_elements.py +65 -0
- mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
- mute_agent/knowledge_graph/subgraph.py +224 -0
- mute_agent/listener/__init__.py +43 -0
- mute_agent/listener/adapters/__init__.py +31 -0
- mute_agent/listener/adapters/base_adapter.py +189 -0
- mute_agent/listener/adapters/caas_adapter.py +344 -0
- mute_agent/listener/adapters/control_plane_adapter.py +436 -0
- mute_agent/listener/adapters/iatp_adapter.py +332 -0
- mute_agent/listener/adapters/scak_adapter.py +251 -0
- mute_agent/listener/listener.py +610 -0
- mute_agent/listener/state_observer.py +436 -0
- mute_agent/listener/threshold_config.py +313 -0
- mute_agent/super_system/__init__.py +1 -0
- mute_agent/super_system/router.py +204 -0
- mute_agent/visualization/__init__.py +10 -0
- mute_agent/visualization/graph_debugger.py +502 -0
- nexus/README.md +60 -0
- nexus/__init__.py +51 -0
- nexus/arbiter.py +359 -0
- nexus/client.py +466 -0
- nexus/dmz.py +444 -0
- nexus/escrow.py +430 -0
- nexus/exceptions.py +286 -0
- nexus/pyproject.toml +36 -0
- nexus/registry.py +393 -0
- nexus/reputation.py +425 -0
- nexus/schemas/__init__.py +51 -0
- nexus/schemas/compliance.py +276 -0
- nexus/schemas/escrow.py +251 -0
- nexus/schemas/manifest.py +225 -0
- nexus/schemas/receipt.py +208 -0
- nexus/tests/__init__.py +0 -0
- nexus/tests/conftest.py +146 -0
- nexus/tests/test_arbiter.py +192 -0
- nexus/tests/test_dmz.py +194 -0
- nexus/tests/test_escrow.py +276 -0
- nexus/tests/test_exceptions.py +225 -0
- nexus/tests/test_registry.py +232 -0
- nexus/tests/test_reputation.py +328 -0
- nexus/tests/test_schemas.py +295 -0
nexus/arbiter.py
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""
|
|
4
|
+
Arbiter - Dispute Resolution
|
|
5
|
+
|
|
6
|
+
The "Reward Agent" - a specialized, read-only agent that resolves disputes
|
|
7
|
+
between agents by replaying flight recorder logs against the Control Plane.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Optional, Literal
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
import hashlib
|
|
14
|
+
import uuid
|
|
15
|
+
|
|
16
|
+
from .schemas.receipt import DisputeReceipt
|
|
17
|
+
from .schemas.escrow import EscrowStatus, EscrowResolution
|
|
18
|
+
from .reputation import ReputationEngine
|
|
19
|
+
from .exceptions import (
|
|
20
|
+
DisputeNotFoundError,
|
|
21
|
+
DisputeAlreadyResolvedError,
|
|
22
|
+
DisputeEvidenceError,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class FlightRecorderLog:
|
|
28
|
+
"""
|
|
29
|
+
Flight recorder log from an agent's kernel.
|
|
30
|
+
|
|
31
|
+
Contains all operations, tool calls, and outputs during a task.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
agent_did: str
|
|
35
|
+
task_id: str
|
|
36
|
+
escrow_id: str
|
|
37
|
+
|
|
38
|
+
# Log content (encrypted)
|
|
39
|
+
encrypted_log: bytes
|
|
40
|
+
log_hash: str
|
|
41
|
+
|
|
42
|
+
# Metadata (not encrypted)
|
|
43
|
+
start_time: datetime
|
|
44
|
+
end_time: datetime
|
|
45
|
+
operation_count: int
|
|
46
|
+
|
|
47
|
+
# Signature
|
|
48
|
+
agent_signature: str
|
|
49
|
+
|
|
50
|
+
def verify_hash(self) -> bool:
|
|
51
|
+
"""Verify log integrity."""
|
|
52
|
+
computed = hashlib.sha256(self.encrypted_log).hexdigest()
|
|
53
|
+
return computed == self.log_hash
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class DisputeResolution:
|
|
58
|
+
"""Result of dispute resolution by the Arbiter."""
|
|
59
|
+
|
|
60
|
+
dispute_id: str
|
|
61
|
+
escrow_id: str
|
|
62
|
+
|
|
63
|
+
# Parties
|
|
64
|
+
requester_did: str
|
|
65
|
+
provider_did: str
|
|
66
|
+
|
|
67
|
+
# Decision
|
|
68
|
+
outcome: Literal["requester_wins", "provider_wins", "split"]
|
|
69
|
+
decision_explanation: str
|
|
70
|
+
confidence_score: float # 0-1, how confident Arbiter is
|
|
71
|
+
|
|
72
|
+
# Evidence analysis
|
|
73
|
+
requester_logs_valid: bool
|
|
74
|
+
provider_logs_valid: bool
|
|
75
|
+
discrepancies_found: list[str] = field(default_factory=list)
|
|
76
|
+
|
|
77
|
+
# Credit distribution
|
|
78
|
+
credits_to_requester: int = 0
|
|
79
|
+
credits_to_provider: int = 0
|
|
80
|
+
|
|
81
|
+
# Reputation impact
|
|
82
|
+
requester_reputation_change: int = 0
|
|
83
|
+
provider_reputation_change: int = 0
|
|
84
|
+
liar_identified: Optional[str] = None # DID of agent found to be lying
|
|
85
|
+
|
|
86
|
+
# Timestamps
|
|
87
|
+
resolved_at: datetime = field(default_factory=datetime.utcnow)
|
|
88
|
+
|
|
89
|
+
# Nexus attestation
|
|
90
|
+
arbiter_signature: str = ""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Arbiter:
|
|
94
|
+
"""
|
|
95
|
+
The "Reward Agent" - resolves disputes between agents.
|
|
96
|
+
|
|
97
|
+
A read-only agent hosted on Nexus that:
|
|
98
|
+
1. Receives flight recorder logs from both parties
|
|
99
|
+
2. Replays operations against the Control Plane
|
|
100
|
+
3. Determines which agent's claim is accurate
|
|
101
|
+
4. Applies reputation penalties to the lying agent
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
def __init__(
|
|
105
|
+
self,
|
|
106
|
+
reputation_engine: Optional[ReputationEngine] = None,
|
|
107
|
+
escrow_manager: Optional[any] = None, # Circular import avoidance
|
|
108
|
+
control_plane: Optional[any] = None, # Would be Control Plane reference
|
|
109
|
+
):
|
|
110
|
+
self.reputation_engine = reputation_engine or ReputationEngine()
|
|
111
|
+
self.escrow_manager = escrow_manager
|
|
112
|
+
self.control_plane = control_plane
|
|
113
|
+
|
|
114
|
+
# Storage
|
|
115
|
+
self._disputes: dict[str, DisputeReceipt] = {}
|
|
116
|
+
self._resolutions: dict[str, DisputeResolution] = {}
|
|
117
|
+
|
|
118
|
+
async def submit_dispute(
|
|
119
|
+
self,
|
|
120
|
+
escrow_id: str,
|
|
121
|
+
disputing_party: Literal["requester", "provider"],
|
|
122
|
+
dispute_reason: str,
|
|
123
|
+
claimed_outcome: Literal["success", "failure", "partial"],
|
|
124
|
+
flight_recorder_log: FlightRecorderLog,
|
|
125
|
+
) -> DisputeReceipt:
|
|
126
|
+
"""
|
|
127
|
+
Submit a new dispute for resolution.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
escrow_id: ID of the disputed escrow
|
|
131
|
+
disputing_party: Who is raising the dispute
|
|
132
|
+
dispute_reason: Explanation of why they're disputing
|
|
133
|
+
claimed_outcome: What the disputing party claims happened
|
|
134
|
+
flight_recorder_log: Evidence from the disputing party
|
|
135
|
+
"""
|
|
136
|
+
dispute_id = f"dispute_{uuid.uuid4().hex[:16]}"
|
|
137
|
+
|
|
138
|
+
# Verify log integrity
|
|
139
|
+
if not flight_recorder_log.verify_hash():
|
|
140
|
+
raise DisputeEvidenceError(dispute_id, "Log hash verification failed")
|
|
141
|
+
|
|
142
|
+
# Get escrow details (would fetch from EscrowManager)
|
|
143
|
+
# For now, create a placeholder receipt
|
|
144
|
+
|
|
145
|
+
dispute = DisputeReceipt(
|
|
146
|
+
dispute_id=dispute_id,
|
|
147
|
+
original_receipt=None, # Would be the signed receipt
|
|
148
|
+
disputing_party=disputing_party,
|
|
149
|
+
dispute_reason=dispute_reason,
|
|
150
|
+
claimed_outcome=claimed_outcome,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if disputing_party == "requester":
|
|
154
|
+
dispute.requester_logs_hash = flight_recorder_log.log_hash
|
|
155
|
+
else:
|
|
156
|
+
dispute.provider_logs_hash = flight_recorder_log.log_hash
|
|
157
|
+
|
|
158
|
+
self._disputes[dispute_id] = dispute
|
|
159
|
+
|
|
160
|
+
return dispute
|
|
161
|
+
|
|
162
|
+
async def submit_counter_evidence(
|
|
163
|
+
self,
|
|
164
|
+
dispute_id: str,
|
|
165
|
+
flight_recorder_log: FlightRecorderLog,
|
|
166
|
+
) -> DisputeReceipt:
|
|
167
|
+
"""Submit counter-evidence from the other party."""
|
|
168
|
+
if dispute_id not in self._disputes:
|
|
169
|
+
raise DisputeNotFoundError(dispute_id)
|
|
170
|
+
|
|
171
|
+
dispute = self._disputes[dispute_id]
|
|
172
|
+
|
|
173
|
+
if dispute.resolved:
|
|
174
|
+
raise DisputeAlreadyResolvedError(dispute_id)
|
|
175
|
+
|
|
176
|
+
# Verify log integrity
|
|
177
|
+
if not flight_recorder_log.verify_hash():
|
|
178
|
+
raise DisputeEvidenceError(dispute_id, "Log hash verification failed")
|
|
179
|
+
|
|
180
|
+
# Add logs from other party
|
|
181
|
+
if dispute.disputing_party == "requester":
|
|
182
|
+
dispute.provider_logs_hash = flight_recorder_log.log_hash
|
|
183
|
+
else:
|
|
184
|
+
dispute.requester_logs_hash = flight_recorder_log.log_hash
|
|
185
|
+
|
|
186
|
+
return dispute
|
|
187
|
+
|
|
188
|
+
async def resolve_dispute(
|
|
189
|
+
self,
|
|
190
|
+
dispute_id: str,
|
|
191
|
+
requester_logs: Optional[FlightRecorderLog] = None,
|
|
192
|
+
provider_logs: Optional[FlightRecorderLog] = None,
|
|
193
|
+
) -> DisputeResolution:
|
|
194
|
+
"""
|
|
195
|
+
Resolve a dispute by replaying logs against Control Plane.
|
|
196
|
+
|
|
197
|
+
Process:
|
|
198
|
+
1. Parse both flight recorder logs
|
|
199
|
+
2. Identify the disputed operation
|
|
200
|
+
3. Replay operation against Control Plane
|
|
201
|
+
4. Compare actual vs claimed outcomes
|
|
202
|
+
5. Determine which agent's claim is accurate
|
|
203
|
+
6. Apply reputation penalties to the lying agent
|
|
204
|
+
"""
|
|
205
|
+
if dispute_id not in self._disputes:
|
|
206
|
+
raise DisputeNotFoundError(dispute_id)
|
|
207
|
+
|
|
208
|
+
dispute = self._disputes[dispute_id]
|
|
209
|
+
|
|
210
|
+
if dispute.resolved:
|
|
211
|
+
raise DisputeAlreadyResolvedError(dispute_id)
|
|
212
|
+
|
|
213
|
+
# Verify we have evidence from both parties
|
|
214
|
+
if not dispute.requester_logs_hash or not dispute.provider_logs_hash:
|
|
215
|
+
raise DisputeEvidenceError(
|
|
216
|
+
dispute_id,
|
|
217
|
+
"Evidence required from both parties"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Analyze the dispute
|
|
221
|
+
resolution = await self._analyze_dispute(dispute, requester_logs, provider_logs)
|
|
222
|
+
|
|
223
|
+
# Mark dispute as resolved
|
|
224
|
+
dispute.resolved = True
|
|
225
|
+
dispute.resolution_outcome = resolution.outcome
|
|
226
|
+
dispute.arbiter_decision = resolution.decision_explanation
|
|
227
|
+
dispute.resolved_at = resolution.resolved_at
|
|
228
|
+
|
|
229
|
+
# Apply reputation changes
|
|
230
|
+
if resolution.liar_identified:
|
|
231
|
+
self.reputation_engine.slash_reputation(
|
|
232
|
+
agent_did=resolution.liar_identified,
|
|
233
|
+
reason="dispute_lost",
|
|
234
|
+
severity="high",
|
|
235
|
+
evidence_hash=dispute_id,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Store resolution
|
|
239
|
+
self._resolutions[dispute_id] = resolution
|
|
240
|
+
|
|
241
|
+
return resolution
|
|
242
|
+
|
|
243
|
+
async def _analyze_dispute(
|
|
244
|
+
self,
|
|
245
|
+
dispute: DisputeReceipt,
|
|
246
|
+
requester_logs: Optional[FlightRecorderLog],
|
|
247
|
+
provider_logs: Optional[FlightRecorderLog],
|
|
248
|
+
) -> DisputeResolution:
|
|
249
|
+
"""
|
|
250
|
+
Analyze dispute evidence and determine outcome.
|
|
251
|
+
|
|
252
|
+
In production, this would:
|
|
253
|
+
1. Decrypt and parse logs
|
|
254
|
+
2. Replay operations against Control Plane
|
|
255
|
+
3. Use deterministic validation to find discrepancies
|
|
256
|
+
"""
|
|
257
|
+
# Placeholder analysis - in production would use Control Plane
|
|
258
|
+
discrepancies = []
|
|
259
|
+
requester_valid = requester_logs.verify_hash() if requester_logs else False
|
|
260
|
+
provider_valid = provider_logs.verify_hash() if provider_logs else False
|
|
261
|
+
|
|
262
|
+
# Determine outcome based on evidence validity
|
|
263
|
+
if requester_valid and not provider_valid:
|
|
264
|
+
outcome = "requester_wins"
|
|
265
|
+
liar = None # Provider didn't submit valid logs
|
|
266
|
+
decision = "Provider's evidence was invalid or missing"
|
|
267
|
+
confidence = 0.9
|
|
268
|
+
elif provider_valid and not requester_valid:
|
|
269
|
+
outcome = "provider_wins"
|
|
270
|
+
liar = None # Requester didn't submit valid logs
|
|
271
|
+
decision = "Requester's evidence was invalid or missing"
|
|
272
|
+
confidence = 0.9
|
|
273
|
+
elif requester_valid and provider_valid:
|
|
274
|
+
# Both valid - would need deeper analysis
|
|
275
|
+
# For now, split decision
|
|
276
|
+
outcome = "split"
|
|
277
|
+
liar = None
|
|
278
|
+
decision = "Both parties provided valid evidence; compromise reached"
|
|
279
|
+
confidence = 0.6
|
|
280
|
+
discrepancies.append("Conflicting but valid evidence from both parties")
|
|
281
|
+
else:
|
|
282
|
+
# Neither valid
|
|
283
|
+
outcome = "split"
|
|
284
|
+
liar = None
|
|
285
|
+
decision = "Neither party provided valid evidence"
|
|
286
|
+
confidence = 0.3
|
|
287
|
+
|
|
288
|
+
# Calculate credit distribution
|
|
289
|
+
# Would get actual credits from escrow
|
|
290
|
+
total_credits = 100 # Placeholder
|
|
291
|
+
|
|
292
|
+
if outcome == "requester_wins":
|
|
293
|
+
credits_to_requester = total_credits
|
|
294
|
+
credits_to_provider = 0
|
|
295
|
+
requester_rep = 10
|
|
296
|
+
provider_rep = -50
|
|
297
|
+
elif outcome == "provider_wins":
|
|
298
|
+
credits_to_requester = 0
|
|
299
|
+
credits_to_provider = total_credits
|
|
300
|
+
requester_rep = -50
|
|
301
|
+
provider_rep = 10
|
|
302
|
+
else: # split
|
|
303
|
+
credits_to_requester = total_credits // 2
|
|
304
|
+
credits_to_provider = total_credits // 2
|
|
305
|
+
requester_rep = -10
|
|
306
|
+
provider_rep = -10
|
|
307
|
+
|
|
308
|
+
resolution = DisputeResolution(
|
|
309
|
+
dispute_id=dispute.dispute_id,
|
|
310
|
+
escrow_id="", # Would get from dispute
|
|
311
|
+
requester_did="", # Would get from dispute
|
|
312
|
+
provider_did="", # Would get from dispute
|
|
313
|
+
outcome=outcome,
|
|
314
|
+
decision_explanation=decision,
|
|
315
|
+
confidence_score=confidence,
|
|
316
|
+
requester_logs_valid=requester_valid,
|
|
317
|
+
provider_logs_valid=provider_valid,
|
|
318
|
+
discrepancies_found=discrepancies,
|
|
319
|
+
credits_to_requester=credits_to_requester,
|
|
320
|
+
credits_to_provider=credits_to_provider,
|
|
321
|
+
requester_reputation_change=requester_rep,
|
|
322
|
+
provider_reputation_change=provider_rep,
|
|
323
|
+
liar_identified=liar,
|
|
324
|
+
arbiter_signature=self._sign_resolution(dispute.dispute_id, outcome),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
return resolution
|
|
328
|
+
|
|
329
|
+
def get_dispute(self, dispute_id: str) -> DisputeReceipt:
|
|
330
|
+
"""Get a dispute by ID."""
|
|
331
|
+
if dispute_id not in self._disputes:
|
|
332
|
+
raise DisputeNotFoundError(dispute_id)
|
|
333
|
+
return self._disputes[dispute_id]
|
|
334
|
+
|
|
335
|
+
def get_resolution(self, dispute_id: str) -> DisputeResolution:
|
|
336
|
+
"""Get resolution for a dispute."""
|
|
337
|
+
if dispute_id not in self._resolutions:
|
|
338
|
+
raise DisputeNotFoundError(dispute_id)
|
|
339
|
+
return self._resolutions[dispute_id]
|
|
340
|
+
|
|
341
|
+
def list_disputes(
|
|
342
|
+
self,
|
|
343
|
+
agent_did: Optional[str] = None,
|
|
344
|
+
resolved: Optional[bool] = None,
|
|
345
|
+
) -> list[DisputeReceipt]:
|
|
346
|
+
"""List disputes with optional filtering."""
|
|
347
|
+
results = list(self._disputes.values())
|
|
348
|
+
|
|
349
|
+
if resolved is not None:
|
|
350
|
+
results = [d for d in results if d.resolved == resolved]
|
|
351
|
+
|
|
352
|
+
# Would filter by agent_did if we had that in the receipt
|
|
353
|
+
|
|
354
|
+
return results
|
|
355
|
+
|
|
356
|
+
def _sign_resolution(self, dispute_id: str, outcome: str) -> str:
|
|
357
|
+
"""Generate Arbiter signature for resolution."""
|
|
358
|
+
data = f"arbiter:{dispute_id}:{outcome}:{datetime.now(timezone.utc).isoformat()}"
|
|
359
|
+
return f"arbiter_sig_{hashlib.sha256(data.encode()).hexdigest()[:32]}"
|