Repository navigation
Fix empty configured_model for routed and fallback Copilot CLI runs, and isolate selection-persistence errors in the post-step - #69966
Conversation
…stence errors Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
|
✅ Ponytail Reviewer completed successfully! Ponytail ReviewerOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality SentinelOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. Design Decision Gate 🏗️Outcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
Comment MemoryPeek at saved memory (pr-code-quality-reviewer)Note This comment is managed by comment memory.Expand the saved memory block to view or edit the persistent context for this thread.
|
There was a problem hiding this comment.
Request changes
This fixes the empty-model case, but it also rewrites every routed CLI run to look like an auto request, which corrupts requested-model attribution for explicitly configured runs.
The blocking theme from this review
actions/setup/js/copilot_harness.cjs: routed runs now always persistconfigured_model: "auto", even when the workflow explicitly setCOPILOT_MODELor an alias before routing. That changes the meaning of the evidence record, leaks intorequested_model/ unified-session metadata, and is not covered by the new tests.
This was a static review of the diff and nearby source only; I did not execute the code or tests.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 106.4 AIC · ⌖ 5.88 AIC · ⊞ 12.7K
Comment /review to run again
There was a problem hiding this comment.
🟡 Changes recommended
The new session regression test fails when checkout paths contain spaces or non-ASCII characters.
1 open issue
What changed in this PR
Addresses #69965 by preserving Copilot CLI model metadata and preventing selection-persistence errors from skipping runner-side accounting.
Changes:
- Capture configured models after routing or fallback, before alias resolution.
- Isolate persistence errors from routing attribution and token accounting.
- Add regression tests, recorded-run fixtures, and a patch changeset.
| File | Description |
|---|---|
actions/setup/js/unified_session.test.cjs |
Tests runner metadata normalization. |
actions/setup/js/parse_token_usage.test.cjs |
Tests accounting despite invalid selection records. |
actions/setup/js/parse_token_usage.cjs |
Separates selection-persistence errors from accounting. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/token-usage.jsonl |
Supplies recorded token usage. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/model-routing.jsonl |
Supplies routing and request evidence. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/copilot-model-selection.json |
Reproduces the empty configured model. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/awf-routing-outcome.json |
Supplies the selected route. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/awf-reflect.json |
Supplies provider and routing metadata. |
actions/setup/js/fixtures/copilot-routed-run-39147795806/aw_info.json |
Supplies initial workflow metadata. |
actions/setup/js/copilot_harness.test.cjs |
Tests routed, fallback, explicit, and SDK startup. |
actions/setup/js/copilot_harness.cjs |
Preserves requested model identifiers. |
.changeset/fix-copilot-cli-model-selection-persistence.md |
Documents the patch release. |
Review effort: Max
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs and /tdd (via pr-triage: change_type=bug_fix). No blocking issues found.
📋 Key Themes & Highlights
Root cause fix
selectionConfiguredModelincopilot_harness.cjscorrectly captures the request identifier (autofor routed runs, the resolved fallback value, or the explicit model) after routing/fallback decide it, rather than readingCOPILOT_MODELtoo early. This directly fixes the emptyconfigured_modelthat brokepersistCopilotModelSelectionvalidation downstream.configuredCopilotModel(pre-routing) is intentionally left untouched for the unrelatedapplyCopilotWireAPIandrecordModelEndpointMismatchcall sites — those predate this PR and are out of scope, so the two separate model variables are not a naming inconsistency.
Error isolation in the post-step
parse_token_usage.cjsnow isolatespersistCopilotModelSelection()in its owntry/catch, so a bad selection record (empty/malformed/invalid) no longer skipsmodel_routing, the token-usage summary,agent_usage.json, outputs, orpersistAgentAwInfoCopy()in thefinallyblock. Verified the earlyreturnpaths (no usage data, checkpoint found) still runfinally, so the deferredselectionErroris always reported viacore.setFailedusing the existingERR_PARSE:convention.- Validation itself is not loosened — invalid selection data is still rejected and never written to
aw_info.json.
Test coverage (/tdd)
copilot_harness.test.cjsspawns the real harness against a stub CLI with a patched/reflect, covering routed, fallback-only, explicit-model, and SDK-mode (no record) cases — genuine black-box coverage rather than mocking internals.parse_token_usage.test.cjsusestest.eachover three failure modes (real empty record, empty file, malformed JSON) and asserts routing/usage/outputs still complete, plus a positive case with a corrected selection.unified_session.test.cjsadds an end-to-end check thatworkflow.infosurfacesmodelRoutingandmodelSelectioncorrectly from the runner snapshot.- All fixtures are real, unmodified records (JSON reformatted only) from the failing run (39147795806), which keeps the tests honest about the actual bug shape rather than synthetic data.
Positive highlights
- ✅ Root cause addressed (timing of model capture), not just the downstream symptom
- ✅ Clear code comments explaining why
selectionConfiguredModelexists - ✅ Error isolation preserves existing
continue-on-errorsemantics and error-code conventions - ✅ Changeset accurately describes the user-visible behavior change
No actionable issues identified in the changed lines. Approving.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 137.8 AIC · ⌖ 14.9 AIC · ⊞ 10.1K
Comment /matt to run again
Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
The requested change was answered with no code change needed: routed workflows never get COPILOT_MODEL (addCopilotModelEnv returns early with engine.model-routing), so configured_model "auto" is the actual routed request, as #69965 specifies (see the resolved thread). The Copilot reviewer's fixture-path finding was fixed in 0b50b48. Verified at c564f55: JS tests pass, and all four routed smokes passed R1-R4 on this branch.

Routed Copilot CLI runs, and runs where only the environment fallback supplies the model, wrote a model-selection log with
configured_model: "". The harness capturedCOPILOT_MODELbefore routing or fallback had set it. On the runner,persistCopilotModelSelectioncorrectly rejects that record, but it threw inside the sametryas routing attribution and token accounting. That skippedmodel_routing, the token-usage summary,agent_usage.jsonand the outputs, which caused the R1 smoke failures. SDK mode never creates this record, so it was unaffected.Harness (
copilot_harness.cjs)The configured model passed to
createCopilotModelObserveris now set after routing and fallback are known:configured_modelresolved_model/effective_modelautoCOPILOT_MODELunset)GH_AW_MODEL_FALLBACKvaluemodel:or aliasCOPILOT_MODELis not re-read after resolution, so the requested and resolved names stay separate.applyCopilotWireAPI, endpoint-mismatch records and SDK mode are untouched.Post-step (
parse_token_usage.cjs)persistCopilotModelSelectionnow has its own error boundary. Routing attribution, the token summary and aggregate, outputs, andpersistAgentAwInfoCopyalways run.ERR_PARSE: Cannot record Copilot model selection: …throughcore.setFailed, after that work is done. The step iscontinue-on-error, so this does not fail the job.Fixtures (
actions/setup/js/fixtures/copilot-routed-run-39147795806/)agentartifact of run 39147795806:copilot-model-selection.json(with the real emptyconfigured_model),aw_info.json,awf-routing-outcome.json,model-routing.jsonlandtoken-usage.jsonl. JSON files are Prettier-formatted only.awf-reflect.jsonis trimmed to the copilot endpoint and theroutingselection. Unconfigured provider endpoints and unrelated top-level fields are omitted.Tests
copilot_harness.test.cjs: runs the real harness startup with a stand-in CLI, and stubs/reflectthrough a--requirepreload that patchesfetchAWFReflect. Cases:COPILOT_MODELunset producesconfigured_model: "auto", and persisting it succeeds;parse_token_usage.test.cjs: "records routing and usage when Copilot model selection persistence fails", run with the real empty record, an empty file and malformed JSON. It checks the error message,model_routingin all threeaw_info.jsoncopies, the summary,agent_usage.json, the outputs, and thatmodel_selectionis absent. A second test checks that a corrected selection is saved.unified_session.test.cjs: runs the post-step on the fixtures, then checks that theworkflow.infoevent fromruntime/aw_info.jsonhasmodelRoutingandmodelSelectionwithgpt-5.6-luna.Notes for reviewers
copilot_model_selection.test.cjsstill cover it.smoke-copilot-routed,-routed-claude,-routed-steeringandsmoke-copilot-sdk-routedrun on this branch. The PR also needs thesmoke-routinglabel.TestSessionParserSourcesIncludeLocalDependencies(CGO "Unit tests (S-Z and other)") already fails onmain.