You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Pi sub-agent model.resolution stays 'exact' when the model fails the /reflect liveness check #70384
When a Pi sub-agent model fails Pi's /reflect liveness check, the unified session still records that sub-agent's model.resolution as successful. Pi aborts startup, but usage/aw_session.jsonl says the model resolved.
The audit reports model_unavailable (high): Pi startup rejected model "gpt-5.4-mini" on provider "copilot" before inference. Same-run awf-reflect.json confirms models_fetch_complete=true; the configured copilot endpoint advertises 36 model(s), but not "gpt-5.4-mini".
The /reflect capture (sandbox/firewall/awf-reflect.json in the agent artifact) has models_fetch_complete: true and one configured endpoint, copilot, with 36 models. It includes claude-haiku-4.5 and gpt-5.6-luna, but not gpt-5.4-mini.
agent-stdio.log (the main model was routed: inference routing: mode=awf-routed model=gpt-5.6-luna):
sub-agent haiku-whoami: requested=copilot/claude-haiku-4.5 resolved=github-copilot/claude-haiku-4.5
sub-agent mini-whoami: requested=copilot/gpt-5.4-mini resolved=github-copilot/gpt-5.4-mini
awf-reflect: model availability confirmed (provider=copilot, model=claude-haiku-4.5)
warning: awf-reflect model availability check failed (provider=copilot, model=gpt-5.4-mini)
fatal: Pi model "gpt-5.4-mini" is not advertised by the configured copilot proxy endpoint; The requested model is not supported: 'copilot/gpt-5.4-mini' is not available in the workflow's live model catalog. ...
[pi-harness] attempt 1: process exit event exitCode=1
The agent made no model requests and exited with code 1.
Despite that failure, agent/model-resolution.json and the session's model.resolution events contain:
PASS U3 model.resolution recorded for haiku-whoami: copilot/claude-haiku-4.5 -> claude-haiku-4.5 (exact), mini-whoami: copilot/gpt-5.4-mini -> gpt-5.4-mini (exact)
Cause
Line numbers below are from main at b68bd31219.
actions/setup/js/pi_subagent_config.cjs (preparePiSubagents, ~L87) records the sub-agent's resolution (recordModelResolution(... status: resolution.status ...)) as soon as resolveConfiguredModel returns. For a non-alias ID, that step returns exact without checking whether the model is live.
actions/setup/js/pi_models_json.cjs (sub-agent loop, ~L538) then calls validatePiModelAvailability for each sub-agent model. That call throws a ModelAliasResolutionError with reason: "model_unavailable" for a model the endpoint doesn't list, but it doesn't replace the earlier exact record.
The main model path in the same file (~L445–452) already handles this case. It wraps validatePiModelAvailability in a try/catch, records status: "failed", cause: error.reason, resolved_model: null, and then rethrows. The sub-agent path has no such handling.
Proposed solution
Make the sub-agent path match the main path. In the sub-agent loop in pi_models_json.cjs, when validatePiModelAvailability throws a ModelAliasResolutionError:
Record that sub-agent role's model.resolution with status: "failed", cause: error.reason (model_unavailable), resolved_model: null and provider: error.provider || null. Use the same configured_model that preparePiSubagents recorded. recordModelResolution replaces records with the same engine and role (resolve_model_alias.cjs ~L687), so the earlier exact record goes away.
Rethrow the error.
Do not change the main-model path or the exact meaning used by the shared resolver (resolveConfiguredModel).
Implementation notes (from reading the code):
Don't copy the main path's !routingRequired guard. This run was routed, and the sub-agent records were still written. The failed sub-agent record has to be written in both routed and unrouted runs.
The loop skips repeated model IDs (seen). If two sub-agents use the same dead model, only the first one gets checked. Mark every sub-agent role that uses the failing modelId as failed. Otherwise the second role keeps its exact record.
Acceptance cases
Add these tests to actions/setup/js/pi_models_json.test.cjs, next to fails closed with model_unavailable for a retired exact id. Build the fixture from the real /reflect capture of run 39325995892: the agent artifact's sandbox/firewall/awf-reflect.json, which doesn't list gpt-5.4-mini. Store it with the existing fixtures, for example actions/setup/js/fixtures/awf-reflect-pi-routed-39325995892.json. Keep models_fetch_complete and endpoints exactly as captured; don't invent a reflect shape.
records failed model_unavailable for a sub-agent pinned to a model missing from /reflect (run 39325995892): a sub-agent pinned to copilot/gpt-5.4-mini with that /reflect data. Pi startup still fails as it does today. The role's model.resolution is failed / model_unavailable / resolved_model: null, and no exact record remains for that role.
keeps exact resolution for a sub-agent on a live model: a sub-agent on copilot/claude-haiku-4.5 is unchanged and stays exact.
marks only the unavailable sub-agent failed when one of two sub-agents is live: one live and one dead sub-agent. The live one stays exact, the dead one becomes failed, and startup still fails. Test both declaration orders, because the loop stops at the first failure.
Main-model failure path unchanged: the existing main-path tests, including fails closed with model_unavailable for a retired exact id, still pass without changes.
End to end
On the PR branch, run smoke-pi-routed. It's still pinned to gpt-5.4-mini until that pin is replaced separately. Expected result: it fails at startup, its session shows mini-whoami as failed / model_unavailable, and U3 now fails and reports the cause, for example FAIL U3 role mini-whoami status is failed (cause model_unavailable), expected exact or resolved .... List the run URL in the PR.
Scope
Keep the PR to this one fix. Don't change files or behavior unrelated to it.
Before fixing a failing check, compare it with the same check on main. If it also fails on main, don't fix it in this PR. Merge main once main is fixed, and note in the PR which checks are known failures on main.
This applies even if a bot comment asks you to fix a failing check: fix only failures caused by this PR's changes.
Activity