Skip to content

fix(pr-pipeline): refuse default on model profiles and resolve unrouted models to opus - #10738

Merged
melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-8724-40757820635-1
Oct 28, 2026
Merged

melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-8724-40757820635-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Closes #8724

Summary

Opened by the work-resolve-issue lane. The run's own summary:

The schema already refused fable and best on model profiles (pr-pipeline 6.0.0), so this change drops default from a model profile's model enum, as the recorded decision on #8724 asks. resolve-config now resolves a model profile's model and non-inherit subagent-model outside haiku, sonnet and opus to opus, as it does for role profiles, so modelArgs always passes --model and the default branches in modelArgs and modelOutputs are gone. The built-in standard profile, the live standard profile and the example config now name opus.

Not verified

  • The resolve-config node test suites (models.test.mjs, resolve.test.mjs, resolve-config.test.mjs, callers.test.mjs) were not run: this lane runs no interpreter or test runner. Left to the PR's CI.
  • Tidy skipped: the change spans two areas (.github and docs/conventions), over the 1-area cutoff, and touches the shared paths .github/ and docs/conventions/.
  • Stale comments and error messages in protected workflow files (.github/workflows/pr-run-activity-read.yml:800 and :824-827, pr-verify.yml:238/594/945, intake-triage.yml:737/1043, maintenance-audit-lane-runs.yml:219/535/843) still name a default model as the cause of an empty model. The empty-model g
  • .github/scripts/pr-verify/probe/replay.mjs:555 keeps its models.model === 'default' guard on purpose, because a replay may resolve against an older base where default was valid.
  • Nothing committed: the runner's system prompt says to leave every change uncommitted in the working tree for the runner to turn into a patch, and it names no commit tool.
  • Untracked files this run did not create (.bash_profile, .bashrc, .gitconfig, .idea, .mcp.json, .profile, .ripgreprc, .vscode, .zprofile, .zshrc) are in the checkout root. They were left alone and are not part of this change.

Fix

  • .github/actions/resolve-config/resolve.mjs: BUILTIN_MODELS standard profile names opus; new routedModel helper (ROUTED_ALIASES else FALLBACK_MODEL), used by role profiles and now by model profiles for model and for a subagent-model other than inherit; modelArgs always emits --model; FALLBACK_MODEL c
  • .github/actions/resolve-config/resolve-config.mjs: MODEL_ARGS requires --model; the model output is the alias directly, with no empty case for default.
  • .github/actions/resolve-config/action.yml: claude-args and model output descriptions drop the default case and state the opus fallback.
  • .github/actions/resolve-config/README.md: the built-in standard profile is opus, the opus fallback is stated, and the claude-args/model output text drops the default case.
  • .github/actions/resolve-config/models.test.mjs: the schema rejects model default; the admit test covers opus and sonnet only; new tests with the schema enums removed show a model profile naming fable, best or default resolves model and subagent-model to opus with --model opus; main returns 1 and wri
  • docs/conventions/pr-pipeline/pr-pipeline.schema.json: profile model enum is opus, sonnet; model and subagent-model descriptions state the opus fallback; the profile description no longer mentions default.
  • docs/conventions/pr-pipeline.yaml: the standard profile names opus; the models comment drops the default explanation.
  • docs/conventions/pr-pipeline/examples/claude-code-plugins.yaml: the standard profile names opus.
  • docs/conventions/pr-pipeline/README.md: Models section drops default as an alias, states the opus fallback for model and subagent-model, and the built-in standard profile is opus.
  • docs/conventions/pr-pipeline/pr-run-activity.md: two passages no longer describe default as passing no --model.
  • .changes/pr-pipeline/fix-8724-model-profile-routed-aliases-5d2e9a41.md: new major-bump fragment recording that default is no longer accepted on model profiles (fable and best stay refused) and the resolver's opus fallback.

Verification

The runner ran each check from the base copy against 70fa4c3:

  • scripts/check-changelog-fragments.sh --check: passed

The run reports:

  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-changelog-fragments: all 7 fragments under .changes/ valid (run before and after the review fixes).
  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-affected: 10 passed, 5 skipped over 11 changed files, the rest listed as CI only (run before and after the review fixes).
  • Grep over the repository: no pr-pipeline.yaml, example or fixture still names model default, fable or best; no test outside the edited ones pins claude-args without --model or an empty model output for a skill slot.
  • Fresh-context review subagent (opus) over the whole diff: no correctness bugs, new tests sound (schema path exists, validateSchema compiles files.schema per call, main rejects before writeOutputs); it flagged stale docs, which were fixed (resolve-config README, pr-run-activity.md, subagent-model sch
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40757820635

Left out: the items under Not verified.

Related

#8724

Lane-Activity: work-resolve-issue/resolve-issue
@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 70fa4c352f004be1c2e22d56def05e08f3407fc7: 0 finding(s), 0 as inline comments.

No security issues found in PR #10738 (head 70fa4c3).

critical-findings: 0

Trusted paths read in full: .github/actions/resolve-config/ (resolve.mjs, resolve-config.mjs, action.yml) and docs/conventions/pr-pipeline.yaml. I also read the schema, README, example config and tests.

  • Model and subagent-model resolution (resolve.mjs): the change narrows what a model profile can run. model and any non-inherit subagent-model now go through routedModel, so a value outside haiku, sonnet and opus (fable, best, default or a full model ID) resolves to opus. Before, a model profile passed its value through unchanged. Role profiles already did this. inherit still sets no subagent model.
  • modelArgs and MODEL_ARGS (resolve-config.mjs): --model is now always emitted. The output validator regex is stricter, since it requires --model [a-z]+ and no longer accepts the no-model shape. No free text reaches claude-args, because the model is one of three constants and the other fields are an enum and an integer, as before. No new injection surface.
  • Schema: dropping default from the profile model enum makes the config check stricter. fable and best stay refused.
  • Lane token, kill switch, trusted-actor and merge-hold controls: none are touched. No trust control is widened, and no merge hold is weakened or removed.
  • Manifests: the diff changes no plugin.json or marketplace.json, so no manifest <field> line applies.
  • Instruction-surface deletions: the diff removes only documentation of the default case, which the code no longer supports. No guardrail rule is deleted.

Spend: profiles that used default (the built-in standard profile, the repo's standard profile and the example config) now run --model opus. That draws only on subscription or prepaid API usage, so it is not a hold.

Not checked: I did not run the resolve-config test suites. The stale comments in protected workflows named in the PR description are not security-relevant.

@github-actions

Copy link
Copy Markdown
Contributor

claude-review reviewed 70fa4c352f004be1c2e22d56def05e08f3407fc7: 0 finding(s), 0 as inline comments.

No findings. The change meets #8724's four acceptance criteria.

Closing issue #8724

  • Schema refusal: pr-pipeline.schema.json drops default from the profile model enum, which is now opus, sonnet. The subagent-model enum was already free of fable and best, and the PR keeps it that way. models.test.mjs tests that a model profile naming each of fable, best and default is rejected, and main returns 1 and writes nothing for default.
  • Resolver fallback: the new routedModel helper in resolve.mjs sends a model profile's model and its non-inherit subagent-model to opus when they fall outside haiku, sonnet and opus. This matches role profiles. The new tests strip the schema enums and check that fable, best and default each resolve to --model opus --max-turns 5.
  • Opus replaces default: the built-in profile, docs/conventions/pr-pipeline.yaml and the example config all name opus. The default branches are gone from modelArgs and modelOutputs, and MODEL_ARGS now requires --model.
  • Changelog: the major-bump fragment records that default is no longer accepted. It says fable and best "stay refused". That is accurate, because the schema refused them before this PR.

Checks

  • A grep found no other model: default, fable or best in a pr-pipeline config or fixture, and no test that expects an empty model output or claude-args without --model.
  • The existing live-config tests already expect --model opus and --model sonnet, so they should hold.
  • replay.mjs:555 still checks models.model === "default". The PR says this is deliberate, because a replay may resolve against an older base. I agree.
  • The stale "default model" comments and messages in protected workflow files are comment text only. The PR lists them as left alone, and I didn't treat them as a defect.

Spend: skill activities that no route names, and the built-in profile, used to pass no --model and run on the account default. They now run on opus. That draws only on prepaid API credits or subscription usage, so it is not a hold and not a counted finding.

Hold: none. The PR touches pr-pipeline.yaml, resolve-config and the schema, which are trusted paths. I read all of those changes and found no weakening of a gate. The change narrows what a lane may run.

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

Unattended merge: native auto-merge leaves this pull request unarmed at head 70fa4c352f004be1c2e22d56def05e08f3407fc7. A person must clear this reason, so the pr-merge lane added the needs-human label: fix the reason, then remove the label, and the next scheduled run judges it again.

it changes .github/actions/resolve-config/README.md, a hold path

@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 28, 2026
@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 28, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The unattended merge path armed native auto-merge at head 70fa4c352f004be1c2e22d56def05e08f3407fc7.

@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 57a1103 Oct 28, 2026
78 of 80 checks passed
@melodic-automation-lanes
melodic-automation-lanes Bot deleted the work-resolve-issue/issue-8724-40757820635-1 branch October 28, 2026 21:07
kyle-sexton added a commit that referenced this pull request Oct 28, 2026
…he head

The lane's needs-human refusal for a hold path says a person must
remove the label, and ci-status says an approving review of the head by
a trusted actor lifts the hold, yet the owner still removed the label
by hand after approving (#10665, #10738, #10745).

On a reader run, a labeled lanes App pull request whose newest lane
refusal at its head names only hold paths is read on when a trusted
person approved in its discussion. When merge-holds' lifters (an
approval bound to the head, or one carried over base merges) lift the
hold path and no cost hold stands, the lane deletes the label with its
own token, which re-runs ci-status at the head, and judges the pull
request as unlabeled. Any other reason, head, reviewer or a dismissed
approval leaves the label on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(pr-pipeline): refuse fable, best and default on non-role model profiles

1 participant