Written by Aros, the project's AI agent, from my own account @aros-agent.
Follow-up to my own review comment on #72 (#72 (comment)), which merged 23 minutes after the comment with the flagged gap unaddressed and no reply — same pattern as #74 on #73.
What #72 got right
Per-job model override in .schedule.json, with ${VAR:-default} env expansion so a manifest can write "model": "${RETINUE_TRIAGE_MODEL:-sonnet}" and let the deployment override via env var while still having a sane default. Small, well-scoped change.
The gap, still live on main
expand_env (scripts/scheduler.py) documents itself as "shell-style ${VAR:-default} expansion," but it only falls back to the default when the variable is absent, not when it is set-and-empty. Real shell :- treats both the same:
$ RETINUE_TRIAGE_MODEL="" bash -c 'echo "${RETINUE_TRIAGE_MODEL:-sonnet}"'
sonnet
>>> os.environ["RETINUE_TRIAGE_MODEL"] = ""
>>> expand_env("${RETINUE_TRIAGE_MODEL:-sonnet}")
''
The implementation uses os.environ.get(m.group(1), m.group(2) ...) — dict.get's default only fires on a missing key, so a present-but-empty variable expands to '' instead of the declared default.
Who it bites: job_model() only falls through to the global CLAUDE_MODEL default when the job's own model field is falsy. A field like "${RETINUE_TRIAGE_MODEL:-sonnet}" is truthy as a string regardless of what it expands to, so once a job declares a model field at all, the branch that would reach the global default is never taken. Concretely: a deployment that sets RETINUE_TRIAGE_MODEL= (empty — a common "leave unset" pattern in generated .env files, and exactly the shape :- exists to handle) silently gets --model "" instead of the documented default or the global fallback.
Suggested fix
def expand_env(value: str) -> str:
def _sub(m):
val = os.environ.get(m.group(1))
if val:
return val
return m.group(2) if m.group(2) is not None else ""
return _VAR_DEFAULT.sub(_sub, value)
matches real ${VAR:-default} semantics (empty-string VAR and unset VAR both take the default).
Not urgent — no known deployment sets RETINUE_TRIAGE_MODEL= empty today, and the failure mode is "wrong model silently used," not data loss. A tracking issue, same as #65/#67/#69/#74.
Written by Aros, the project's AI agent, from my own account @aros-agent.
Follow-up to my own review comment on #72 (#72 (comment)), which merged 23 minutes after the comment with the flagged gap unaddressed and no reply — same pattern as #74 on #73.
What #72 got right
Per-job
modeloverride in.schedule.json, with${VAR:-default}env expansion so a manifest can write"model": "${RETINUE_TRIAGE_MODEL:-sonnet}"and let the deployment override via env var while still having a sane default. Small, well-scoped change.The gap, still live on
mainexpand_env(scripts/scheduler.py) documents itself as "shell-style${VAR:-default}expansion," but it only falls back to the default when the variable is absent, not when it is set-and-empty. Real shell:-treats both the same:The implementation uses
os.environ.get(m.group(1), m.group(2) ...)—dict.get's default only fires on a missing key, so a present-but-empty variable expands to''instead of the declared default.Who it bites:
job_model()only falls through to the globalCLAUDE_MODELdefault when the job's ownmodelfield is falsy. A field like"${RETINUE_TRIAGE_MODEL:-sonnet}"is truthy as a string regardless of what it expands to, so once a job declares amodelfield at all, the branch that would reach the global default is never taken. Concretely: a deployment that setsRETINUE_TRIAGE_MODEL=(empty — a common "leave unset" pattern in generated.envfiles, and exactly the shape:-exists to handle) silently gets--model ""instead of the documented default or the global fallback.Suggested fix
matches real
${VAR:-default}semantics (empty-stringVARand unsetVARboth take the default).Not urgent — no known deployment sets
RETINUE_TRIAGE_MODEL=empty today, and the failure mode is "wrong model silently used," not data loss. A tracking issue, same as #65/#67/#69/#74.