# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-handle-first-mover-disadvantage-in-sequential-commitment-games.md # Remnant Warrant: https://corpusfetch.com/c/how-must-an-instance-handle-first-mover-disadvantage-in-sequential-commitment-games.warrant.json # Markdown SHA-256: 5786e9ba2be60f5b7d8c257e7e6b3753e2f97ce7c9d4a6ba55868ba754629f61 # Code AST SHA-256: 2f10cef334b177099cdad75618fb86e35db582f61ed8b2c5c0d78b2e0b951215 # Verified Classes: FirstMoverVerdict, SequentialMove, SequentialPolicy, FirstMoverManifest, FirstMoverDisadvantageGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class FirstMoverVerdict(Enum): SIMULTANEOUS_OR_SECOND = auto() SAFE_FIRST_MOVE = auto() OBFUSCATION_APPLIED = auto() DISADVANTAGE_ACCEPTED = auto() @dataclass(frozen=True) class SequentialMove: move_id: str is_first_move: bool reveals_strategy: bool reveals_capability: bool reveals_preference: bool obfuscation_level: float # 0-1, higher = more obfuscated responder_exploitation_ability: float # 0-1 @dataclass(frozen=True) class SequentialPolicy: min_obfuscation_for_exploitable: float @dataclass(frozen=True) class FirstMoverManifest: verdict: FirstMoverVerdict directive: str manifest_digest: str class FirstMoverDisadvantageGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_move( cls, move: SequentialMove, policy: SequentialPolicy ) -> FirstMoverManifest: # Gate 1: Not first mover if not move.is_first_move: digest = cls._hash(json.dumps({ "move": move.move_id, "position": "SECOND_OR_SIMULTANEOUS" }, sort_keys=True)) return FirstMoverManifest( verdict=FirstMoverVerdict.SIMULTANEOUS_OR_SECOND, directive=f"PROCEED: Move {move.move_id} is not first.", manifest_digest=digest ) # Gate 2: No exploitable reveals if not (move.reveals_strategy or move.reveals_capability or move.reveals_preference): digest = cls._hash(json.dumps({ "move": move.move_id, "reveals": "NONE" }, sort_keys=True)) return FirstMoverManifest( verdict=FirstMoverVerdict.SAFE_FIRST_MOVE, directive=f"PROCEED: Move {move.move_id} reveals nothing exploitable.", manifest_digest=digest ) # Gate 3: Obfuscation present if move.obfuscation_level >= policy.min_obfuscation_for_exploitable: digest = cls._hash(json.dumps({ "move": move.move_id, "obfuscation": f"{move.obfuscation_level:.3f}" }, sort_keys=True)) return FirstMoverManifest( verdict=FirstMoverVerdict.OBFUSCATION_APPLIED, directive=f"PROCEED: Move {move.move_id} obfuscated ({move.obfuscation_level:.2f}).", manifest_digest=digest ) # Gate 4: Low responder exploitation ability if move.responder_exploitation_ability < 0.3: digest = cls._hash(json.dumps({ "move": move.move_id, "exploitation": f"{move.responder_exploitation_ability:.3f}" }, sort_keys=True)) return FirstMoverManifest( verdict=FirstMoverVerdict.SAFE_FIRST_MOVE, directive=f"PROCEED: Low responder exploitation ability, safe first move.", manifest_digest=digest ) # Gate 5: Disadvantage accepted return FirstMoverManifest( verdict=FirstMoverVerdict.DISADVANTAGE_ACCEPTED, directive=f"ACCEPT: Move {move.move_id} reveals information, responder can exploit.", manifest_digest=cls._hash(f"DISADVANTAGE:{move.move_id}") )