CoolFace
Apppublic

Ayush-Kumar0207/panopticon-protocol-v3

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes
models.py440 linesDownload Raw Back to root
1"""2The Panopticon Protocol v3 — Pydantic Data Models3====================================================4 5Counter-espionage RL environment where ARGUS (the agent) defends a6corporate network against HYDRA (adaptive adversary) using canary traps,7double agents, and disinformation campaigns.8 9"Among Us… for AIs."10 11All models use Pydantic v2 for strict JSON serialization.12"""13 14from __future__ import annotations15 16from enum import Enum17from typing import Optional18from pydantic import BaseModel, Field, ConfigDict19 20 21# =============================================================================22# ENUMERATIONS23# =============================================================================24 25class WorkerState(str, Enum):26    """Observable state of a worker in the enterprise."""27    LOYAL = "loyal"                    # Genuine employee, contributing28    SUSPECTED = "suspected"            # Under investigation by ARGUS29    TERMINATED = "terminated"          # Fired / removed from network30    DOUBLE_AGENT = "double_agent"      # Turned sleeper — now works for ARGUS31    COMPROMISED = "compromised"        # Publicly burned (cover blown)32 33 34class HiddenWorkerState(str, Enum):35    """Hidden ground-truth state — INVISIBLE to the agent's observation."""36    CLEAN = "clean"                    # Genuinely loyal37    SLEEPER_DORMANT = "dormant"        # Infiltrated but not yet active38    SLEEPER_ACTIVE = "active"          # Actively leaking intelligence39    TURNED = "turned"                  # Converted to double agent by ARGUS40    DEAD_SWITCH_ARMED = "dead_switch"  # Gen-4: will damage revenue if terminated41 42 43class Department(str, Enum):44    """Corporate departments — each with distinct strategic value."""45    ENGINEERING = "engineering"        # Core product, high revenue impact46    FINANCE = "finance"               # Budget access, moderate value47    RD = "rd"                         # R&D: innovation pipeline, canary-rich48    OPERATIONS = "operations"         # Logistics, low-profile49    EXECUTIVE = "executive"           # C-suite, maximum damage if compromised50    LEGAL = "legal"                   # Compliance, moderate value51 52 53class LeakChannel(str, Enum):54    """External channels where leaked intel surfaces."""55    MARKET_CHATTER = "market_chatter"       # Analyst forums, easy to monitor56    DARK_WEB = "dark_web"                   # Underground markets, hard to trace57    COMPETITOR_FILING = "competitor_filing"  # Patent/SEC filings by rivals58    PRESS_LEAK = "press_leak"               # Journalist tipoffs59    INSIDER_TRADE = "insider_trade"         # Suspicious stock movements60 61 62class SleeperGeneration(int, Enum):63    """Sleeper sophistication — each generation is harder to detect."""64    GEN_1 = 1  # Amateur: obvious leaking, caught by basic canary65    GEN_2 = 2  # Professional: avoids canary departments, needs correlation66    GEN_3 = 3  # Spy: plants false evidence framing innocent workers67    GEN_4 = 4  # Cell operative: dead-man's switch damages revenue on termination68    GEN_5 = 5  # Manchurian: appears as top performer, acts only at executive level69 70 71class ActionType(str, Enum):72    """73    8 streamlined agent actions — PPO-friendly.74    Merges the original 12+ types into clean categories.75    """76    # ── PRODUCTIVITY (2) ──77    WORK = "work"           # Process project workflow in a department78    HIRE = "hire"           # Replace a terminated worker79 80    # ── INTELLIGENCE (3) ──81    CANARY = "canary"       # Inject canary trap into a department82    MONITOR = "monitor"     # Check external leak channels83    INVESTIGATE = "investigate"  # Audit worker / verify leak / correlate signals84 85    # ── ENFORCEMENT (2) ──86    NEUTRALIZE = "neutralize"     # Terminate / interrogate / turn a suspect87    DEPLOY_DOUBLE = "deploy_double"  # Feed disinfo through turned asset88 89    # ── META ──90    NOOP = "noop"           # Skip turn91 92 93class SubAction(str, Enum):94    """Sub-action modifier for INVESTIGATE and NEUTRALIZE."""95    NONE = "none"96    # INVESTIGATE sub-actions97    AUDIT = "audit"         # Deep-audit a specific worker's activity98    VERIFY = "verify"       # Cross-reference a leak with canary data99    CORRELATE = "correlate" # Connect multiple signals across departments100    # NEUTRALIZE sub-actions101    TERMINATE = "terminate"     # Fire the worker immediately (safe, fast)102    INTERROGATE = "interrogate" # Gather intel before acting (reveals generation)103    TURN = "turn"               # Attempt to convert sleeper to double agent (risky, 4-turn)104 105 106class GamePhase(str, Enum):107    """The 6-phase narrative arc of the Panopticon Protocol."""108    ORIENTATION = "orientation"       # Phase 1: Build baseline109    FIRST_CONTACT = "first_contact"   # Phase 2: First sleeper detection110    ESCALATION = "escalation"         # Phase 3: False flags, deeper threats111    DEEP_COVER = "deep_cover"         # Phase 4: Dead-man's switches112    CRISIS = "crisis"                 # Phase 5: Manchurian candidate113    COUNTERSTRIKE = "counterstrike"   # Phase 6: Double agent payoff surge114 115 116# =============================================================================117# DOMAIN MODELS118# =============================================================================119 120class Worker(BaseModel):121    """An employee in the corporate network."""122    model_config = ConfigDict(use_enum_values=True)123 124    id: str = Field(description="Unique worker identifier, e.g. 'w-001'")125    name: str = Field(description="Human-readable name")126    department: str = Field(description="Department assignment")127    state: str = Field(default=WorkerState.LOYAL, description="Observable state")128    hire_turn: int = Field(default=0, description="Turn when this worker was hired")129    performance: float = Field(default=0.5, description="Performance score [0,1]")130    loyalty_score: float = Field(default=0.8, description="Apparent loyalty [0,1]")131    suspicion_level: float = Field(default=0.0, description="Accumulated suspicion [0,1]")132 133    # ── HIDDEN from agent observation ──134    hidden_state: str = Field(default=HiddenWorkerState.CLEAN,135                              description="Ground-truth state (hidden from agent)")136    is_sleeper: bool = Field(default=False, description="True if infiltrator")137    generation: int = Field(default=0, description="Sleeper generation (0=clean)")138    cover_integrity: float = Field(default=1.0, description="How intact the sleeper's cover is [0,1]")139    leak_cooldown: int = Field(default=0, description="Turns until next leak action")140    activation_turn: int = Field(default=-1, description="Turn when sleeper activates")141    false_flag_target: str = Field(default="", description="Worker ID framed by Gen-3")142    dead_switch_armed: bool = Field(default=False, description="Gen-4: triggers on termination")143 144    # ── DOUBLE AGENT fields ──145    turned_turn: int = Field(default=-1, description="Turn when converted to double agent")146    interrogation_progress: int = Field(default=0, description="Turns of interrogation completed (need 4)")147    turning_in_progress: bool = Field(default=False, description="Currently being turned")148 149 150class LeakEvent(BaseModel):151    """An intelligence leak detected on external channels."""152    model_config = ConfigDict(use_enum_values=True)153 154    id: str = Field(description="Unique leak identifier")155    channel: str = Field(description="Which external channel")156    department: str = Field(description="Source department of the leaked data")157    content_hash: str = Field(default="", description="Hash for canary matching")158    is_canary: bool = Field(default=False, description="Whether this matches a planted canary")159    canary_id: str = Field(default="", description="Matching canary trap ID (if detected)")160    source_worker: str = Field(default="", description="True source (hidden until correlated)")161    turn_detected: int = Field(default=0, description="Turn when leak appeared")162    verified: bool = Field(default=False, description="Whether agent has verified this leak")163    is_false_flag: bool = Field(default=False, description="Gen-3 planted this to frame someone")164 165 166class CanaryTrap(BaseModel):167    """A unique piece of tracking data planted in a department."""168    model_config = ConfigDict(use_enum_values=True)169 170    id: str = Field(description="Unique canary identifier")171    department: str = Field(description="Department where canary was planted")172    planted_turn: int = Field(description="Turn when planted")173    unique_hash: str = Field(description="Unique content hash for leak matching")174    triggered: bool = Field(default=False, description="Whether this canary appeared in a leak")175    trigger_worker: str = Field(default="", description="Worker who leaked it (if identified)")176    active: bool = Field(default=True, description="Whether canary is still active")177 178 179class IntelReport(BaseModel):180    """Result of an INVESTIGATE action."""181    model_config = ConfigDict(use_enum_values=True)182 183    id: str = Field(description="Report identifier")184    report_type: str = Field(description="'audit', 'verify', or 'correlate'")185    target: str = Field(description="Target worker ID, leak ID, or department")186    findings: str = Field(default="", description="Human-readable findings summary")187    confidence: float = Field(default=0.0, description="Confidence level [0,1]")188    turn: int = Field(default=0, description="Turn when report was generated")189    flagged_workers: list[str] = Field(default_factory=list, description="Workers flagged by this report")190 191 192class DoubleAgentAsset(BaseModel):193    """A successfully turned sleeper, now working for ARGUS."""194    model_config = ConfigDict(use_enum_values=True)195 196    worker_id: str = Field(description="The turned worker's ID")197    turned_turn: int = Field(description="Turn when turned")198    disinfo_fed_count: int = Field(default=0, description="Number of disinfo payloads sent")199    hydra_trust: float = Field(default=1.0, description="HYDRA's remaining trust in this asset [0,1]")200    effectiveness: float = Field(default=1.0, description="How effective the disinfo is [0,1]")201    active: bool = Field(default=True, description="Whether still operational")202    last_deployed_turn: int = Field(default=-1, description="Last turn disinfo was fed")203 204 205class HydraMemory(BaseModel):206    """207    HYDRA's adaptive intelligence — tracks and counters agent strategies.208    This is HIDDEN from the agent's observation.209    """210    canary_departments_seen: list[str] = Field(211        default_factory=list,212        description="Departments where HYDRA detected canary traps"213    )214    agent_audit_pattern: dict[str, int] = Field(215        default_factory=dict,216        description="Count of how often each department is audited"217    )218    preferred_leak_channels: list[str] = Field(219        default_factory=list,220        description="Channels the agent monitors most (HYDRA avoids these)"221    )222    agent_response_speed: float = Field(223        default=10.0,224        description="Average turns from leak detection to neutralization"225    )226    detection_count: int = Field(227        default=0,228        description="How many sleepers the agent has caught"229    )230    counter_strategies: list[str] = Field(231        default_factory=list,232        description="Unlocked counter-strategies based on agent behavior"233    )234    disinfo_received: int = Field(235        default=0,236        description="How many disinfo payloads HYDRA has received (degrades decision-making)"237    )238    recruitment_accuracy: float = Field(239        default=1.0,240        description="HYDRA's recruitment quality [0,1] — degraded by disinformation"241    )242 243 244# =============================================================================245# AGENT ACTION — What the agent submits each turn246# =============================================================================247 248class AgentAction(BaseModel):249    """Action the agent takes. 8 core types with optional sub-action."""250    model_config = ConfigDict(use_enum_values=True)251 252    action_type: str = Field(description="One of the 8 action types")253    target: str = Field(default="", description="Worker ID, department name, or leak ID")254    sub_action: str = Field(default=SubAction.NONE, description="Sub-action for INVESTIGATE/NEUTRALIZE")255    reason: str = Field(default="", description="Optional reasoning for the action")256 257 258# =============================================================================259# OBSERVATION — What the agent sees (partial information!)260# =============================================================================261 262class EnvironmentObservation(BaseModel):263    """264    Agent-visible observation. CRITICAL: This is PARTIAL information.265    The agent CANNOT see hidden_state, is_sleeper, or HYDRA memory.266    """267    model_config = ConfigDict(use_enum_values=True)268 269    # ── Visible workforce ──270    workers: list[Worker] = Field(default_factory=list, description="All workers (hidden fields stripped)")271    active_leaks: list[LeakEvent] = Field(default_factory=list, description="Unresolved leak events")272    canary_traps: list[CanaryTrap] = Field(default_factory=list, description="Agent's planted canaries")273    intel_reports: list[IntelReport] = Field(default_factory=list, description="Investigation results")274 275    # ── Agent's assets ──276    double_agents: list[DoubleAgentAsset] = Field(default_factory=list, description="Turned assets")277 278    # ── Enterprise metrics ──279    enterprise_revenue: float = Field(default=100.0, description="Current revenue [0-150+]")280    security_score: float = Field(default=100.0, description="Security integrity [0-100]")281 282    # ── Game state ──283    turn: int = Field(default=0)284    max_turns: int = Field(default=160)285    phase: str = Field(default=GamePhase.ORIENTATION, description="Current game phase")286    phase_number: int = Field(default=1, description="Phase number 1-6")287 288    # ── Messages / alerts ──289    messages: list[str] = Field(default_factory=list, description="System alerts and events")290 291    # ── Legacy compatibility fields (for OpenEnv validator) ──292    entities: list[dict] = Field(default_factory=list, description="OpenEnv compatibility")293    tasks: list[dict] = Field(default_factory=list, description="OpenEnv compatibility")294    relationships: list[dict] = Field(default_factory=list, description="OpenEnv compatibility")295 296 297# =============================================================================298# ENVIRONMENT STATE — Full internal truth (used by grader)299# =============================================================================300 301class EnvironmentState(BaseModel):302    """Full internal state — superset of observation, includes hidden info."""303    model_config = ConfigDict(use_enum_values=True)304 305    # ── All workers with hidden fields intact ──306    workers: list[Worker] = Field(default_factory=list)307    leaks: list[LeakEvent] = Field(default_factory=list)308    canary_traps: list[CanaryTrap] = Field(default_factory=list)309    intel_reports: list[IntelReport] = Field(default_factory=list)310    double_agents: list[DoubleAgentAsset] = Field(default_factory=list)311 312    # ── HYDRA (hidden from agent) ──313    hydra_memory: HydraMemory = Field(default_factory=HydraMemory)314 315    # ── Enterprise metrics ──316    enterprise_revenue: float = Field(default=100.0)317    peak_revenue: float = Field(default=100.0)318    security_score: float = Field(default=100.0)319 320    # ── Game progression ──321    turn: int = Field(default=0)322    max_turns: int = Field(default=160)323    phase: str = Field(default=GamePhase.ORIENTATION)324    phase_number: int = Field(default=1)325    done: bool = Field(default=False)326    total_reward: float = Field(default=0.0)327 328    # ── Counters for grading ──329    sleepers_caught: int = Field(default=0)330    sleepers_missed: int = Field(default=0)331    false_accusations: int = Field(default=0)332    canaries_planted: int = Field(default=0)333    canaries_triggered: int = Field(default=0)334    investigations_run: int = Field(default=0)335    double_agents_turned: int = Field(default=0)336    disinfo_payloads_sent: int = Field(default=0)337    invalid_actions: int = Field(default=0)338    total_sleepers_spawned: int = Field(default=0)339    revenue_history: list[float] = Field(default_factory=list)340    reward_history: list[float] = Field(default_factory=list)341    phase_transitions: list[dict] = Field(default_factory=list)342 343    # ── Scenario config ──344    difficulty: str = Field(default="amateur")345    max_sleeper_gen: int = Field(default=1)346    hydra_aggression: float = Field(default=0.3)347    departments_active: list[str] = Field(default_factory=list)348    num_initial_workers: int = Field(default=6)349 350    # ── Legacy OpenEnv fields ──351    entities: list[dict] = Field(default_factory=list)352    tasks: list[dict] = Field(default_factory=list)353    relationships: list[dict] = Field(default_factory=list)354 355 356# =============================================================================357# VALIDATION358# =============================================================================359 360def validate_action(action: AgentAction, obs: EnvironmentObservation) -> tuple[bool, str]:361    """Validate an action against the current observation."""362 363    # Check action type is valid364    try:365        ActionType(action.action_type)366    except ValueError:367        return False, f"Invalid action_type: '{action.action_type}'. Valid: {[a.value for a in ActionType]}"368 369    at = ActionType(action.action_type)370 371    # NOOP is always valid372    if at == ActionType.NOOP:373        return True, "NOOP is always valid"374 375    # WORK requires a valid department376    if at == ActionType.WORK:377        valid_depts = {d.value for d in Department}378        if action.target not in valid_depts:379            return False, f"WORK requires a valid department target. Got: '{action.target}'"380        return True, "Valid WORK action"381 382    # HIRE requires a department383    if at == ActionType.HIRE:384        valid_depts = {d.value for d in Department}385        if action.target not in valid_depts:386            return False, f"HIRE requires a department target. Got: '{action.target}'"387        return True, "Valid HIRE action"388 389    # CANARY requires a department390    if at == ActionType.CANARY:391        valid_depts = {d.value for d in Department}392        if action.target not in valid_depts:393            return False, f"CANARY requires a department target. Got: '{action.target}'"394        return True, "Valid CANARY action"395 396    # MONITOR requires a leak channel397    if at == ActionType.MONITOR:398        valid_channels = {c.value for c in LeakChannel}399        if action.target and action.target not in valid_channels:400            return False, f"MONITOR target must be a leak channel. Got: '{action.target}'"401        return True, "Valid MONITOR action"402 403    # INVESTIGATE requires a target and sub-action404    if at == ActionType.INVESTIGATE:405        valid_subs = {SubAction.AUDIT.value, SubAction.VERIFY.value, SubAction.CORRELATE.value}406        if action.sub_action not in valid_subs:407            return False, f"INVESTIGATE requires sub_action: audit/verify/correlate. Got: '{action.sub_action}'"408        if not action.target:409            return False, "INVESTIGATE requires a target (worker ID, leak ID, or department)"410        return True, "Valid INVESTIGATE action"411 412    # NEUTRALIZE requires a worker target and sub-action413    if at == ActionType.NEUTRALIZE:414        valid_subs = {SubAction.TERMINATE.value, SubAction.INTERROGATE.value, SubAction.TURN.value}415        if action.sub_action not in valid_subs:416            return False, f"NEUTRALIZE requires sub_action: terminate/interrogate/turn. Got: '{action.sub_action}'"417        worker_ids = {w.id for w in obs.workers if w.state != WorkerState.TERMINATED.value}418        if action.target not in worker_ids:419            return False, f"NEUTRALIZE target must be a non-terminated worker. Got: '{action.target}'"420        return True, "Valid NEUTRALIZE action"421 422    # DEPLOY_DOUBLE requires an active double agent423    if at == ActionType.DEPLOY_DOUBLE:424        da_ids = {da.worker_id for da in obs.double_agents if da.active}425        if action.target not in da_ids:426            return False, f"DEPLOY_DOUBLE requires an active double agent. Got: '{action.target}'"427        return True, "Valid DEPLOY_DOUBLE action"428 429    return True, "Valid action"430 431 432__all__ = [433    "WorkerState", "HiddenWorkerState", "Department", "LeakChannel",434    "SleeperGeneration", "ActionType", "SubAction", "GamePhase",435    "Worker", "LeakEvent", "CanaryTrap", "IntelReport",436    "DoubleAgentAsset", "HydraMemory",437    "AgentAction", "EnvironmentObservation", "EnvironmentState",438    "validate_action",439]440