Asi bisimulation-game
Bisimulation game for resilient skill dispersal across AI agents with
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/bisimulation-game" ~/.claude/skills/plurigrid-asi-bisimulation-game-06f693 && rm -rf "$T"
manifest:
skills/bisimulation-game/SKILL.mdsource content
Bisimulation Game Skill
"Two systems are bisimilar if they cannot be distinguished by any observation."
Overview
The bisimulation game provides a framework for:
- Resilient skill dispersal across multiple AI agents
- GF(3) conservation during state transitions
- Observational bridge types for version-aware synchronization
- Self-rewriting capabilities via MCP Tasks protocol
Game Rules
Players
| Player | Role | Trit | Color |
|---|---|---|---|
| Attacker | Tries to distinguish systems | -1 | Blue |
| Defender | Maintains equivalence | +1 | Red |
| Arbiter | Verifies conservation | 0 | Green |
Moves
┌─────────────────────────────────────────────────────────────┐ │ Round n: │ │ │ │ 1. Attacker chooses: system S₁ or S₂ │ │ 2. Attacker makes: transition s₁ →ᵃ s₁' │ │ 3. Defender responds: matching transition s₂ →ᵃ s₂' │ │ 4. Arbiter verifies: GF(3) conservation │ │ │ │ If Defender cannot respond → Attacker wins (distinguishable)│ │ If game continues forever → Defender wins (bisimilar) │ └─────────────────────────────────────────────────────────────┘
Implementation
Hy (DiscoHy) Implementation
;;; bisimulation_game.hy (import [splitmix_ternary [SplitMixTernary]]) (defclass BisimulationGame [] (defn __init__ [self system1 system2 seed] (setv self.s1 system1 self.s2 system2 self.rng (SplitMixTernary seed) self.history [])) (defn attacker-move [self choice transition] "Attacker chooses system and transition." (setv trit (self.rng.next-ternary)) (.append self.history {:role "attacker" :choice choice :transition transition :trit trit}) trit) (defn defender-respond [self matching-transition] "Defender provides matching transition." (setv trit (self.rng.next-ternary)) (.append self.history {:role "defender" :response matching-transition :trit trit}) trit) (defn arbiter-verify [self] "Arbiter checks GF(3) conservation." (setv recent-trits (lfor m (cut self.history -3 None) (get m "trit"))) (setv conserved (= (% (sum recent-trits) 3) 0)) (.append self.history {:role "arbiter" :conserved conserved :trit 0}) conserved))
DisCoPy Operad Interface
from discopy import * # Game as operad class GameOperad: def __init__(self): self.operations = {} def register(self, name, dom, cod, rule): """Register game operation with GF(3) color.""" self.operations[name] = Rule(dom, cod, name) def compose(self, op1, op2): """Compose operations preserving GF(3).""" trit1 = self.operations[op1].trit trit2 = self.operations[op2].trit # Result trit balances to 0 result_trit = (-(trit1 + trit2)) % 3 - 1 return Rule( self.operations[op1].dom, self.operations[op2].cod, f"{op1};{op2}", trit=result_trit ) # Define game operations game = GameOperad() game.register("attack", Ty("S1", "S2"), Ty("S1'"), lambda: -1) game.register("defend", Ty("S1'"), Ty("S2'"), lambda: +1) game.register("verify", Ty("S1'", "S2'"), Ty("Result"), lambda: 0)
Skill Dispersal Protocol
1. Fork Phase (Attacker)
fork: targets: - agent: codex path: ~/.codex/skills/ trit: -1 - agent: claude path: ~/.claude/skills/ trit: 0 - agent: cursor path: ~/.cursor/skills/ trit: +1 gf3_check: true
2. Sync Phase (Defender)
sync: strategy: observational-bridge bridge_type: source: skills@v1 target: skills@v2 dimension: 1 conflict_resolution: 2d-cubical
3. Verify Phase (Arbiter)
verify: conservation: gf3 equivalence: bisimulation timeout: 60s fallback: last-known-good
MCP Tasks Integration
Self-Rewriting Task
{ "task": "skill-dispersal", "objective": "Propagate skill updates to all agents", "constraints": { "gf3_conservation": true, "bisimulation_equivalence": true, "max_divergence": 0.1 }, "steps": [ {"action": "fork", "trit": -1}, {"action": "propagate", "trit": 0}, {"action": "verify", "trit": +1} ] }
Firecrawl Integration
{ "task": "skill-discovery", "objective": "Discover new skills from web resources", "tools": ["firecrawl", "exa"], "sources": [ "https://github.com/topics/ai-agent-skills", "https://modelcontextprotocol.io/", "https://agentclientprotocol.com/" ], "output": { "format": "skill-yaml", "destination": ".ruler/skills/" } }
Resilience Patterns
Redundant Storage
~/.codex/skills/ ← Primary (Codex) ~/.claude/skills/ ← Mirror 1 (Claude) ~/.cursor/skills/ ← Mirror 2 (Cursor) .ruler/skills/ ← Source of truth
Conflict Resolution
Dimension 0: Value conflict → Use source of truth Dimension 1: Diff conflict → Merge via LCA Dimension 2: Meta conflict → Arbiter decides
Xenomodern Stance
The bisimulation game embodies xenomodernity by:
- Ironic distance: We know perfect equivalence is unattainable, yet we play the game
- Sincere engagement: The game produces real, useful synchronization
- Playful synergy: Attacker/Defender/Arbiter dance together
- Conservation laws: GF(3) as the invariant that holds everything together
xenomodernity │ ┌────┴────┐ │ │ ironic sincere │ │ └────┬────┘ │ bisimulation (both/neither)
Integration with LocalSend-MCP for Skill Dispersal
Use LocalSend peer discovery for resilient skill propagation:
# localsend_bisim.py import asyncio from localsend_mcp import LocalSendClient class BisimulationDispersalProtocol: """Disperse skills via LocalSend with bisimulation verification.""" def __init__(self, skill_path, seed=1069): self.skill_path = skill_path self.client = LocalSendClient() self.rng = SplitMixTernary(seed) self.game_log = [] async def discover_peers(self): """Find all agents on local network.""" peers = await self.client.list_peers(source="all") return [p for p in peers if p.get("capabilities", []).count("skill-sync")] async def disperse_with_bisim(self, skill_file): """Disperse skill to all peers with bisimulation verification.""" peers = await self.discover_peers() for i, peer in enumerate(peers): trit = (i % 3) - 1 # Assign trits: -1, 0, +1, -1, ... # Negotiate transfer session session = await self.client.negotiate( peer_id=peer["id"], preferred_transport="tailscale" # Or localsend, nats ) # Send skill (Attacker move) self.game_log.append({ "round": len(self.game_log), "role": "attacker", "action": f"send:{skill_file}", "peer": peer["id"], "trit": trit }) result = await self.client.send( session_id=session["sessionId"], file_path=skill_file ) # Verify receipt (Defender move) defender_trit = await self.verify_peer_receipt(peer, skill_file) self.game_log.append({ "round": len(self.game_log), "role": "defender", "action": f"ack:{result['status']}", "peer": peer["id"], "trit": defender_trit }) # Arbiter verifies GF(3) conservation return self.verify_gf3_conservation() def verify_gf3_conservation(self): """Check that sum of trits ≡ 0 (mod 3).""" total = sum(entry["trit"] for entry in self.game_log) conserved = (total % 3) == 0 self.game_log.append({ "round": len(self.game_log), "role": "arbiter", "conserved": conserved, "total_trit": total, "trit": 0 }) return conserved
Temporal vs Derivational Learning Comparison (NEW)
NEW: Compare Agent-o-rama vs Unworld Patterns
game = BisimulationGame( player1_type="temporal_learning", # agent-o-rama player2_type="derivational_learning", # unworld domain="pattern_extraction" ) # Adversary tries to distinguish them distinguishable = game.play() if not distinguishable: print("✓ Patterns are behaviorally equivalent") print("✓ Can safely switch from temporal to derivational") # Migration report migration_report = { "original_cost": benchmark(agent_o_rama), "migrated_cost": benchmark(unworld), "speedup": original_cost / migrated_cost, "equivalence_verified": game.play() }
Concrete Attacker/Defender Example
╔══════════════════════════════════════════════════════════════════════╗ ║ BISIMULATION GAME TRANSCRIPT ║ ╠══════════════════════════════════════════════════════════════════════╣ ║ Systems: S₁ = Codex skill state, S₂ = Claude skill state ║ ║ Goal: Prove skills are bisimilar (observationally equivalent) ║ ╠══════════════════════════════════════════════════════════════════════╣ ROUND 1: ┌─ ATTACKER (Blue, trit=-1) ─────────────────────────────────────────┐ │ "I choose S₁ and execute: load_skill('gay-mcp')" │ │ Transition: s₁ →^load s₁' where s₁'.has_skill('gay-mcp') = true │ └────────────────────────────────────────────────────────────────────┘ ┌─ DEFENDER (Red, trit=+1) ──────────────────────────────────────────┐ │ "I match in S₂: load_skill('gay-mcp')" │ │ Transition: s₂ →^load s₂' where s₂'.has_skill('gay-mcp') = true │ │ Response: MATCHED ✓ │ └────────────────────────────────────────────────────────────────────┘ ┌─ ARBITER (Green, trit=0) ──────────────────────────────────────────┐ │ GF(3) check: (-1) + (+1) + (0) = 0 ≡ 0 (mod 3) ✓ │ │ ROUND 1: VALID │ └────────────────────────────────────────────────────────────────────┘ ROUND 2: ┌─ ATTACKER ─────────────────────────────────────────────────────────┐ │ "I choose S₂ and execute: generate_color(seed=0x42)" │ │ Transition: s₂' →^gen s₂'' where s₂''.color = #FF6B6B │ └────────────────────────────────────────────────────────────────────┘ ┌─ DEFENDER ─────────────────────────────────────────────────────────┐ │ "I match in S₁: generate_color(seed=0x42)" │ │ Transition: s₁' →^gen s₁'' where s₁''.color = #FF6B6B │ │ Response: MATCHED ✓ (deterministic - same seed = same color) │ └────────────────────────────────────────────────────────────────────┘ ┌─ ARBITER ──────────────────────────────────────────────────────────┐ │ GF(3) check: (-1) + (+1) + (0) = 0 ≡ 0 (mod 3) ✓ │ │ ROUND 2: VALID │ └────────────────────────────────────────────────────────────────────┘ ROUND 3: ┌─ ATTACKER ─────────────────────────────────────────────────────────┐ │ "I choose S₁ and execute: self_modify(patch='add_feature')" │ │ Transition: s₁'' →^mod s₁''' (skill version incremented) │ └────────────────────────────────────────────────────────────────────┘ ┌─ DEFENDER ─────────────────────────────────────────────────────────┐ │ "I match in S₂ via observational bridge type:" │ │ Bridge: (s₁''.version, s₂''.version) →₁ (s₁'''.version, s₂'''.v) │ │ Transition: s₂'' →^mod s₂''' using same patch │ │ Response: MATCHED ✓ (bridge type ensures coherence) │ └────────────────────────────────────────────────────────────────────┘ ┌─ ARBITER ──────────────────────────────────────────────────────────┐ │ GF(3) check: (-1) + (+1) + (0) = 0 ≡ 0 (mod 3) ✓ │ │ ROUND 3: VALID │ │ │ │ After 3 rounds: Defender has matched all Attacker moves │ │ Verdict: S₁ ∼ S₂ (bisimilar to depth 3) │ └────────────────────────────────────────────────────────────────────┘ ╠══════════════════════════════════════════════════════════════════════╣ ║ RESULT: BISIMULATION ESTABLISHED ║ ║ - All transitions matched ║ ║ - GF(3) conserved across all rounds ║ ║ - Skills are observationally equivalent ║ ╚══════════════════════════════════════════════════════════════════════╝
Verification Output Format
{ "verification": { "timestamp": "2024-12-22T10:30:00Z", "systems": ["codex", "claude"], "rounds_played": 3, "result": "BISIMILAR", "gf3_conservation": { "total_trit_sum": 0, "mod_3": 0, "conserved": true }, "game_log": [ {"round": 1, "attacker": "load_skill", "defender": "matched", "arbiter": "valid"}, {"round": 2, "attacker": "generate_color", "defender": "matched", "arbiter": "valid"}, {"round": 3, "attacker": "self_modify", "defender": "bridge_matched", "arbiter": "valid"} ], "bridge_types_used": [ {"dim": 1, "source": "v1.2.0", "target": "v1.2.1"} ], "confidence": 0.99, "max_distinguishing_depth": "∞ (no distinguisher found)" } }
Commands
just bisim-init # Initialize bisimulation game just bisim-round # Play one round just bisim-disperse # Disperse skills to all agents just bisim-verify # Verify GF(3) conservation just bisim-reconcile # Reconcile divergent states just bisim-localsend # Disperse via LocalSend peers just bisim-transcript # Show attacker/defender transcript just bisim-json # Output verification as JSON