Repository navigation
Resolve Copilot sub-agent models in the harness (CLI and SDK) and fail closed - #70389
Conversation
Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
|
🔬 Test Quality Sentinel is analyzing test quality on this pull request... |
|
✅ PR Code Quality Reviewer completed the code quality review. Warning threat detection engine error What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details.
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ Warning threat detection engine error What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details.
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. Warning threat detection engine error What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details. 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.
|
|
✅ 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.
|
There was a problem hiding this comment.
Warning
threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.
What happened
The threat detection engine failed to produce results.
Review the workflow run logs for details.
Request changes
The preflight introduces two correctness regressions: CLI discovery is broader than the actual custom-agent loader and can reject unrelated .md files, and model resolution runs before the noop short-circuit, so completed/no-op workflows can fail on an agent model they would never use. Both should be fixed before merge.
Findings
- Restrict CLI discovery to
.agent.mdfiles, matching the SDK loader. - Move CLI sub-agent resolution after the noop safe-output check.
The advisory first-pass reviewer did not return parseable findings; this review is based on independent inspection of the changed lines.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · 4.17 AIC · ⊞ 1.6K
Comment /review to run again
There was a problem hiding this comment.
Warning
threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.
What happened
The threat detection engine failed to produce results.
Review the workflow run logs for details.
Skills-Based Review 🧠
Applied /codebase-design and /tdd to the new sub-agent model resolution logic. The overall approach (collect all failures before throwing, fail-closed instead of silent fallback) is solid and well-tested with ~15 new test cases, but two issues should be addressed before merge.
📋 Key Themes & Highlights
Key Findings
- Inconsistent agent-file filter (
/codebase-design):listCopilotAgentFiles(CLI mode,copilot_harness.cjs:677) matches any*.md, whileloadCopilotSDKCustomAgents(SDK mode) and the docs both treat*.agent.mdas the canonical extension. This repo's own.github/agents/directory already contains non-agent.mdfiles (developer.instructions.md,agentic-workflows.md) that would be swept up by the CLI-mode path but ignored by SDK mode — a real behavioral divergence introduced by this PR. - Untested fail-closed branch (
/tdd):hideTrackedAgentFileRewrite's failure path (git command errors) drives the restore-and-exit(1) safety guarantee inapplyCopilotCLISubagentModels, but only the success path is covered by tests ("case 6, CLI, tracked file"). Given this is explicitly called out in the PR description as a safety guarantee, the failure branch deserves direct coverage.
Positive Highlights
- ✅
resolveCopilotSubagentModelscorrectly collects every failing sub-agent'smodel.resolutionrecord before throwing the first failure — matches the PR's stated goal of full diagnostics on fail-closed exit. - ✅ The SDK-mode throw-on-unresolvable-model change is properly caught by
runWithCopilotSDK's existing try/catch and converted toexitCode: 1, verified against the new test's expectations. - ✅ Strong test coverage overall: alias resolution, dead models, refresh behavior, SDK qualification, and git skip-worktree protection are all exercised.
- ✅ Docs (
engines.md) accurately describe the new fail-closed behavior.
Inline comments posted on both findings with suggested fixes.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 174.3 AIC · ⊞ 10.2K
Comment /matt to run again
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved correctness defects affect model selection, startup validation, and preservation of repository changes.
9 open issues
Replace complete multiline YAML model scalar · New Preserve inherited model sentinel semantics · New Preserve provider scope during model qualification · New Record qualification exceptions as resolution failures · New Refresh SDK provider configuration after catalogue updates · New Discover agents from the effective engine working directory · New Preserve tracked agent edits after skip-worktree use · New Distinguish Git tracking failures from untracked files · New Verify skip-worktree was successfully applied · New
What changed in this PR
Moves Copilot sub-agent model resolution into the gh-aw harness, enabling startup validation and recorded model decisions in CLI and SDK modes.
Changes:
- Resolves aliases and checks live model availability, including routed runs.
- Rewrites CLI model fields and passes resolved SDK models without silent fallback.
- Adds catalogue fixtures, regression coverage, and documentation.
| File | Description |
|---|---|
| docs/src/content/docs/reference/engines.md | Documents resolution and fail-closed behavior. |
| actions/setup/js/fixtures/awf-reflect-copilot-sub-agents-39304573724.json | Adds recorded model catalogue. |
| actions/setup/js/fixtures/awf-config-models-copilot-sub-agents-39304573724.json | Adds recorded alias configuration. |
| actions/setup/js/copilot_sdk_session.test.cjs | Supplies harness-resolved test models. |
| actions/setup/js/copilot_sdk_session.cjs | Consumes resolved models and removes fallback. |
| actions/setup/js/copilot_sdk_driver.test.cjs | Tests resolved models and startup rejection. |
| actions/setup/js/copilot_sdk_driver.cjs | Documents the model-handoff environment variable. |
| actions/setup/js/copilot_harness.test.cjs | Covers resolution, rewriting, and startup behavior. |
| actions/setup/js/copilot_harness.cjs | Implements sub-agent validation and model handoff. |
Review effort: Max
|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef state: a78ac41f377c4917ec6ac2c621f496cdb22cd3fb707d550007467f7a31bd0d12
|
…ub-agent-models Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Review of
|
…ub-agent-models Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
…te CLI personal-agent copies Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Addressed in b9f7f48 (after
New tests use the run 39304573724 fixtures:
Checks run: The end-to-end check that Copilot CLI 1.0.98 under AWF loads the personal copy instead of the repository file still needs a maintainer to dispatch a CLI smoke run on this branch. |
Verified at
|


gh-aw resolves the main
model:, but not Copilot sub-agent models. An alias or a retired id (gpt-5.4-mini) can silently run on the main model in SDK mode. In CLI mode, AWF rewrites it at request time or the request fails mid-run. Nothing records which model the sub-agent was meant to use.This PR makes gh-aw resolve sub-agent models before Copilot starts, record the result, and fail closed when a model can't be resolved.
Resolution (
copilot_harness.cjs)resolveCopilotSubagentModels. For each sub-agent that declaresmodel:, it callsresolveEngineModelwithengine: copilot,role: <agent name>, Copilot provider scope, the AWFapiProxy.modelsalias map, andnormalizeForCopilotCLI./reflectcatalogue, the same check the main SDK model uses. One/reflectrefresh is shared across all sub-agents.## agent:blocks and.github/agents/*.agent.md.model.resolutionrecord. When several sub-agents share a dead model, each gets its ownfailedrecord.status: failed, the cause (model_unavailableor the resolver's cause) andresolved_model: null.ModelAliasResolutionErrormessage, and the harness exits 1 before Copilot starts.model:. The sub-agent inherits the main model, as before, and gets no record.CLI mode
$GITHUB_WORKSPACE/.github/agents/<file>asmodel: "<id>". Only that line changes, and only when the resolved id differs from the declared one.git update-index --skip-worktree, so the rewrite can't reach the agent's commits orcreate-pull-request/push-to-pull-request-branchpatches.SDK mode
qualifyModelForMultiProvider). For example,smallbecomescopilot-<wire>/claude-haiku-5.5.GH_AW_COPILOT_SDK_SUBAGENT_MODELS, a JSON map keyed by agent name.copilot_sdk_session.cjs:small/medium/large→ session-model mapping.subagent.model_unavailabledriver event. Go audit still reads that event from older runs.mediumis not an alias in gh-aw or AWF, so it is treated as a literal model id and fails unless that model is live.Unchanged
applyCopilotModelAliasResolutionandresolveCopilotSDKMultiProvider.fallback-modelsandallowed-models.extract_inline_sub_agents.cjsand experiment interpolation.Behaviour changes for reviewers
These SDK sub-agents ran on the main model. They now run on the alias's model, as resolved against the catalogue of run 39304573724:
model:copilot/gpt-5Now fail at startup with
model_unavailable. These sub-agents are pinned to the deadgpt-5.4-mini; the pins are tracked in #70367:run-analyzermini-whoamimini54-whoamismoke-copilot / #70387. Until #70387 lands,
file-summarizerstill declares the unexpanded${{ experiments.subagent_model }}. It now fails at startup instead of failing mid-run with HTTP 400.Follow-up. Claude and Codex sub-agents have the same gap: gh-aw doesn't resolve their models. They need a separate issue.
Tests and fixtures
fixtures/awf-reflect-copilot-sub-agents-39304573724.json: 38 Copilot models, nogpt-5.4-minifixtures/awf-config-models-copilot-sub-agents-39304573724.json: the run'sapiProxy.modelsskip-worktreeprotection.Needs maintainer dispatch on this branch
The agent can't trigger workflow runs, so these smokes haven't run yet:
smoke-copilot-sub-agentsandsmoke-copilot-sdk-routed-claude: expected to fail at startup withmodel_unavailable.resolvedorexactsub-agent records.