launch: per-phase model override (.loop-model[-adv]-<pid>)

Lets a single phase pin a different model, read fresh each role_model call so
a phase transition flips it automatically with no watchdog bounce. Operator
wants builder on opus for the complex dstamp phase, reverting to sonnet from
mailu on: .loop-model-dstamp=opus while base .loop-model stays sonnet.
This commit is contained in:
autonomic-bot
2026-06-11 16:15:18 +00:00
parent 5c260d225c
commit 211b4e231c

View File

@ -66,7 +66,16 @@ LOOP_MODEL = os.environ.get("LOOP_MODEL") or _read_file_default(_MODEL_FILE,
ADV_MODEL = os.environ.get("ADV_MODEL") or _read_file_default(_ADV_MODEL_FILE, "")
def role_model(role):
return ADV_MODEL if (role == "adversary" and ADV_MODEL) else LOOP_MODEL
# Per-phase override wins: a file LOG_DIR/.loop-model-<pid> (builder/shared) or
# .loop-model-adv-<pid> (adversary) pins a model for just that phase. Read fresh on
# every call (cur_idx → PHASE_IDX_FILE), so a phase transition flips the model
# automatically — e.g. opus for a hard phase, sonnet after — with no watchdog bounce.
pid = phase_id(cur_idx())
if role == "adversary":
ov = _read_file_default(os.path.join(LOG_DIR, f".loop-model-adv-{pid}"), "")
return ov or ADV_MODEL or LOOP_MODEL
ov = _read_file_default(os.path.join(LOG_DIR, f".loop-model-{pid}"), "")
return ov or LOOP_MODEL
REMOTE_CONTROL = os.environ.get("REMOTE_CONTROL", "1") == "1"
CLAUDE_BIN = os.environ.get("CLAUDE_BIN", "claude")