chore: add hermes-autoresearch harness config and scripts
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -45,3 +45,4 @@ Thumbs.db
|
||||
# Work logs
|
||||
arbejdslog.txt
|
||||
hermes_driver.sh
|
||||
runs/
|
||||
|
||||
23
.hermes/autoresearch_config.json
Normal file
23
.hermes/autoresearch_config.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"repo_path": "/home/alex/pony",
|
||||
"proposal_command": [
|
||||
"python3",
|
||||
"/home/alex/pony/.hermes/autoresearch_proposal.py",
|
||||
"Improve game balance: adjust one theme scene difficulty (let/normal/svaert) or stat (krop/sind/charme) in themes.py to bring win rate closer to 50%. Only change one scene per trial."
|
||||
],
|
||||
"evaluator_command": [
|
||||
"python3",
|
||||
"/home/alex/pony/.hermes/autoresearch_evaluator.py"
|
||||
],
|
||||
"max_trials": 10,
|
||||
"max_seconds": 3600,
|
||||
"stop_after_no_improve": 3,
|
||||
"min_improvement": 0.0,
|
||||
"keep_on_improve": true,
|
||||
"revert_on_no_improve": true,
|
||||
"revert_on_failure": true,
|
||||
"allowlist_relative_paths": ["web/app/data/themes.py", "web/app/game/dice.py", "web/app/game/pony.py"],
|
||||
"tsv_log_path": "runs/experiments.tsv",
|
||||
"jsonl_log_path": "runs/experiments.jsonl",
|
||||
"command_timeout_seconds": 300
|
||||
}
|
||||
43
.hermes/autoresearch_evaluator.py
Normal file
43
.hermes/autoresearch_evaluator.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Evaluator for hermes-autoresearch: runs exhaustive evaluation and returns win rate as score.
|
||||
Lower deviation from 50% = better score.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
repo = os.environ.get("AR_REPO_PATH", "/home/alex/pony")
|
||||
|
||||
# Run exhaustive evaluation and capture output
|
||||
result = subprocess.run(
|
||||
["python3", "evaluate_game.py", "--exhaustive"],
|
||||
cwd=repo + "/web",
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120,
|
||||
)
|
||||
|
||||
output = result.stdout
|
||||
# Parse win rate from output: "Sejr: 16 (50%)"
|
||||
import re
|
||||
match = re.search(r'Sejr:\s+\d+\s+\((\d+)%\)', output)
|
||||
if not match:
|
||||
# Fallback: try to find win rate in other format
|
||||
match = re.search(r'win_rate["\s:]+([\d.]+)', output)
|
||||
|
||||
if match:
|
||||
win_rate = float(match.group(1))
|
||||
# Score: 100 - abs deviation from 50%. Closer to 50% = higher score.
|
||||
score = 100 - abs(win_rate - 50)
|
||||
else:
|
||||
score = 0.0
|
||||
win_rate = 0
|
||||
|
||||
print(json.dumps({
|
||||
"score": score,
|
||||
"accepted": True,
|
||||
"reason": f"win_rate={win_rate}%, deviation={abs(win_rate-50):.0f}pp from 50%",
|
||||
"metrics": {"win_rate": win_rate, "score": score},
|
||||
}))
|
||||
43
.hermes/autoresearch_proposal.py
Normal file
43
.hermes/autoresearch_proposal.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Proposal wrapper for hermes-autoresearch: calls `hermes chat -q` with the trial contract.
|
||||
The harness sets AR_TRIAL, AR_REPO_PATH, AR_PREVIOUS_SCORE.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import textwrap
|
||||
|
||||
trial = os.environ.get("AR_TRIAL", "0")
|
||||
repo = os.environ.get("AR_REPO_PATH", "/home/alex/pony")
|
||||
prev_score = os.environ.get("AR_PREVIOUS_SCORE", "")
|
||||
|
||||
# Build the prompt
|
||||
prompt = textwrap.dedent(f"""\
|
||||
You are a game balance engineer for My Little Pony TTRPG.
|
||||
|
||||
## Trial {trial}
|
||||
Previous best score (win rate %): {prev_score or "none"}
|
||||
|
||||
## Objective
|
||||
{sys.argv[1] if len(sys.argv) > 1 else "Improve game balance"}
|
||||
|
||||
## Rules
|
||||
- Edit ONLY /home/alex/pony/web/app/data/themes.py (or dice.py, pony.py)
|
||||
- Change ONE scene per trial: adjust 'svaer' (let/normal/svaert) or 'stat' (krop/sind/charme)
|
||||
- Do NOT commit or push — leave changes unstaged
|
||||
- Goal: overall win rate closer to 50% (target 40-60%)
|
||||
- Exit 0 on success, exit 1 if blocked
|
||||
|
||||
## Context
|
||||
- 8 themes, 5 scenes each, 4 pony types
|
||||
- Scenes use dice (svaer field) or non-dice (always pass with correct answer)
|
||||
- Only dice scenes affect win/loss
|
||||
- 'let' = easy (target 1-2), 'normal' = medium (target 3-4), 'svaert' = hard (target 5-6)
|
||||
""")
|
||||
|
||||
# Run hermes chat -q with the prompt
|
||||
agent_cmd = ["hermes", "chat", "-q"]
|
||||
result = subprocess.run(agent_cmd + [prompt], capture_output=True, text=True, timeout=300)
|
||||
sys.exit(result.returncode)
|
||||
Reference in New Issue
Block a user