import subprocess
from ouija_workflow import Workflow, State
class Running(State):
def handle_init(self, ctx, params):
i = ctx.data.get("iteration", 0)
max_i = ctx.params.get("max_iterations", 50)
if i >= max_i:
return self.transition_to(
Done, f"Max iterations ({max_i}) reached. Best: {ctx.data.get('best_score')}"
)
parts = [f"## Iteration {i + 1}/{max_i}"]
if ctx.data.get("best_score") is not None:
parts.append(f"Best so far: {ctx.data['best_score']} ({ctx.data['best_desc']})")
parts.append(
"\nMake ONE change, measure, then call "
"ouija.workflow('result', {score: <number>, description: '<what you changed>'})."
)
return self.respond("\n".join(parts))
def handle_result(self, ctx, params):
if "score" not in params or "description" not in params:
return self.respond("Error: result requires {score: <number>, description: '<text>'}.")
score = float(params["score"])
desc = str(params["description"])
ctx.data["iteration"] = ctx.data.get("iteration", 0) + 1
i = ctx.data["iteration"]
max_i = ctx.params.get("max_iterations", 50)
improved = ctx.data.get("best_score") is None or score > ctx.data["best_score"]
if improved:
old_best = ctx.data.get("best_score")
ctx.data["best_score"] = score
ctx.data["best_desc"] = desc
subprocess.run(["git", "add", "-A"], capture_output=True)
subprocess.run(
["git", "commit", "-m", f"iter {i}: {desc} ({score})"],
capture_output=True,
)
msg = f"## Iteration {i}: improved\nScore: {score}."
if old_best is None:
msg += " Baseline recorded."
else:
msg += f" Beat previous best of {old_best}."
else:
subprocess.run(["git", "checkout", "."], capture_output=True)
subprocess.run(["git", "clean", "-fd"], capture_output=True)
msg = (
f"## Iteration {i}: regressed\n"
f"Score {score} < best {ctx.data['best_score']}. Changes reverted."
)
remaining = max_i - i
if remaining <= 0:
return self.transition_to(Done, msg)
msg += f"\n\n{remaining} remaining. Call ouija.workflow('init')."
return self.respond(msg)
class Done(State):
terminal = True
def on_enter(self, ctx):
return "Call ouija.send(done=true)."
Workflow(
initial=Running,
states=[Running, Done],
instructions=(
"You are running an optimization loop. "
"ouija.workflow('init') gets your task. "
"ouija.workflow('result', {score, description}) reports each attempt. "
"One change per iteration. Never skip measuring."
),
max_calls=120,
).run()