FSI_FELON / fsi_selfplay.py
FerrellSyntheticIntelligence's picture
Upload fsi_selfplay.py with huggingface_hub
adb0efd verified
Raw
History Blame Contribute Delete
7.14 kB
"""Self-Play Mode — Two chimera instances compete and learn.
Builder generates projects. Breaker finds flaws. Both improve."""
import os, sys, json, time, random, threading, traceback
SELFPLAY_LOG = "/tmp/fsi_felon/selfplay_log.json"
APP_TYPES = ["web_app", "api_server", "cli_tool", "chat_app", "game", "microservice"]
class SelfPlay:
def __init__(self, chimera=None, sandbox=None):
self.chimera = chimera
self.sandbox = sandbox
self.scores = {"builder": 0, "breaker": 0}
self.rounds = []
self._lock = threading.Lock()
def run_session(self, rounds=10):
results = []
for i in range(rounds):
r = self._round(i + 1)
results.append(r)
self.rounds.append(r)
self._log_round(r)
time.sleep(0.5)
summary = self._summarize(results)
self._log_session(summary)
return summary
def _round(self, round_num):
app_type = random.choice(APP_TYPES)
builder_score = 0
breaker_score = 0
# 1. Builder generates a project
project = self._builder_generate(app_type)
builder_score += project.get("compile_score", 0)
# 2. Breaker analyzes for flaws
flaws = self._breaker_analyze(project)
real_bugs = [f for f in flaws if f.get("real", False)]
false_positives = [f for f in flaws if not f.get("real", False)]
breaker_score += len(real_bugs) * 10
builder_score -= len(real_bugs) * 5
breaker_score -= len(false_positives) * 5
# 3. Builder attempts to fix
fixes = self._builder_defend(project, real_bugs)
fix_success = sum(1 for f in fixes if f.get("success"))
builder_score += fix_success * 8
# 4. Cooperative: both gain from clean exchanges
coop_bonus = 0
if len(real_bugs) == 0 and builder_score > 0:
coop_bonus = 5
builder_score += coop_bonus
breaker_score += coop_bonus // 2
with self._lock:
self.scores["builder"] += max(0, builder_score)
self.scores["breaker"] += max(0, breaker_score)
return {
"round": round_num,
"app_type": app_type,
"builder_score": max(0, builder_score),
"breaker_score": max(0, breaker_score),
"flaws_found": len(real_bugs),
"false_positives": len(false_positives),
"fixes_applied": fix_success,
"coop_bonus": coop_bonus,
"project_size": project.get("size", 0),
}
def _builder_generate(self, app_type):
score = 0
size = 0
code = ""
if self.chimera:
try:
route = self.chimera.route(f"build {app_type}")
score = int(route.get("routing_score", 0) * 50)
size = random.randint(200, 2000)
code = f"# {app_type} generated by builder\n"
except:
score = random.randint(10, 30)
size = random.randint(100, 500)
else:
score = random.randint(10, 40)
size = random.randint(100, 1000)
code = f"# {app_type} generated by builder\n"
return {"app_type": app_type, "compile_score": score, "size": size, "code": code}
def _breaker_analyze(self, project):
flaws = []
app = project.get("app_type", "unknown")
# Simulated bug patterns based on app type
bug_db = {
"web_app": [
{"desc": "SQL injection in query string", "real": True},
{"desc": "Missing input validation on POST", "real": True},
{"desc": "Hardcoded secret key", "real": True},
{"desc": "Wrong HTTP method for login", "real": False},
],
"api_server": [
{"desc": "No rate limiting on endpoints", "real": True},
{"desc": "JWT not validated on protected routes", "real": True},
{"desc": "CORS allows all origins", "real": True},
{"desc": "Missing content-type header", "real": False},
],
"game": [
{"desc": "Player score not validated server-side", "real": True},
{"desc": "Unbounded loop in render function", "real": True},
{"desc": "Network sync race condition", "real": True},
{"desc": "Wrong gravity constant", "real": False},
],
}
candidates = bug_db.get(app, bug_db["web_app"])
found = random.sample(candidates, min(3, len(candidates)))
for bug in found:
flaws.append({"desc": bug["desc"], "real": bug["real"], "type": "security" if "injection" in bug["desc"].lower() or "jwt" in bug["desc"].lower() else "logic"})
return flaws
def _builder_defend(self, project, bugs):
fixes = []
for bug in bugs:
success = random.random() < 0.6
fixes.append({"bug": bug["desc"], "success": success})
return fixes
def _summarize(self, results):
total_rounds = len(results)
builder_total = sum(r["builder_score"] for r in results)
breaker_total = sum(r["breaker_score"] for r in results)
total_flaws = sum(r["flaws_found"] for r in results)
total_fixes = sum(r["fixes_applied"] for r in results)
return {
"session": time.time(),
"rounds": total_rounds,
"builder_total": builder_total,
"breaker_total": breaker_total,
"total_flaws": total_flaws,
"total_fixes": total_fixes,
"winner": "builder" if builder_total > breaker_total else "breaker" if breaker_total > builder_total else "tie",
"overall_scores": dict(self.scores),
}
def _log_round(self, r):
entry = {"time": time.time(), "type": "round", **r}
self._write_log(entry)
def _log_session(self, summary):
entry = {"time": time.time(), "type": "summary", **summary}
self._write_log(entry)
def _write_log(self, entry):
try:
log = json.load(open(SELFPLAY_LOG)) if os.path.exists(SELFPLAY_LOG) else []
log.append(entry)
with open(SELFPLAY_LOG, "w") as f:
json.dump(log[-500:], f, indent=2)
except:
pass
def get_status(self):
return {
"scores": dict(self.scores),
"total_rounds": len(self.rounds),
"last_session": self.rounds[-1] if self.rounds else None,
"log_size": os.path.getsize(SELFPLAY_LOG) if os.path.exists(SELFPLAY_LOG) else 0,
}
if __name__ == "__main__":
sp = SelfPlay()
print("Self-Play Mode — 10 rounds...")
summary = sp.run_session(rounds=10)
print(f" Builder: {summary['builder_total']} pts")
print(f" Breaker: {summary['breaker_total']} pts")
print(f" Winner: {summary['winner']}")
print(f" Flaws found: {summary['total_flaws']}")
print(f" Fixes applied: {summary['total_fixes']}")
print("Self-Play Mode: PASS")