Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Adopt the per-issue model-selection convention in a repo — tier every open issue, apply the model: labels, board field, and callouts behind an approval gate. Also runs in maintenance mode to sweep up unlabeled issues and label/field drift.
.claude/skills/joshukraine-model-triage/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 97% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 100% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 228% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 177% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 130% | 0% |
Roll the per-issue model-selection convention into a repository: tier each open issue, then apply the model: labels, the board's Model field, and any body callouts — all behind a single approval gate. The convention, its heuristic, and the manual runbook this encodes live in ~/.claude/docs/model-selection-strategy.md; the label vocabulary lives in ~/.claude/docs/label-taxonomy.md.
This is a rollout tool, not a routine one. Model labels are assigned at issue creation alongside the type label. Run this skill once when adopting the convention in a repo that already has open issues, and after that only in maintenance mode when drift has accumulated.
From the target repository's checkout — you need the issues _and_ the code, because tiering an issue means judging what a fix would actually touch. If you must run from elsewhere, every gh issue call needs --repo <owner>/<name>; without it the command silently targets whatever repo you are standing in.
--maintenance — sweep mode: tier only issues _missing_ a label, reconcile label ↔ board-field drift, and refresh stale label _descriptions_. Leaves existing label assignments alone unless an issue's scope has visibly changed.Assign a tier by asking what a _wrong answer_ costs and how far the reasoning reaches. Full treatment in the strategy doc; the working summary:
Lean one tier down for docs/tests, one tier up for anything touching data integrity.
Calibration: ComixDistro's settled pass was 4 Fable / 32 Opus / 25 Sonnet across 61 issues — roughly 6% flagship — but that pass was tiered under the older two-clause flagship bar. Under the tightened bar expect ~2–3%. Either way, a pass landing far above is not discriminating, it is just burning limit headroom. Check the two calibration references in the strategy doc — and the note on which rules they were measured under — before presenting.
Some issues have nothing to build directly, and a tier on them is noise:
qa reports — the tech issue derived via /qa-triage carries the tierCall these out explicitly as deliberate exclusions rather than silently skipping them; an unexplained gap looks identical to an oversight.
Establish that everything the apply step needs exists, and stop early if it doesn't:
gh auth status must list project in the token scopes. If it's missing, stop: the user must run gh auth refresh -s project interactively. You cannot grant it for them.gh project list --owner <OWNER>; capture the project number and node ID (PVT_…). If the repo has no board, the label pass can still proceed — say so and skip the field work rather than stopping.gh label list. Create any missing ones from the taxonomy, exactly as specified there:bash gh label create "model: fable" --color B60205 --description "Recommended model: Fable 5 (reserve for silent-data-corruption stakes)" gh label create "model: opus" --color FBCA04 --description "Recommended model: Opus 5 (well-scoped features, refactors)" gh label create "model: sonnet" --color 0E8A16 --description "Recommended model: Sonnet (docs, single tests, mechanical edits)"
Also check the descriptions of labels that already exist. A description names the model current _at the time the label was created_, so a repo adopted before a model release carries a stale one indefinitely — gh label create won't touch it and no other step will either. Compare against the strings above and repair any mismatch:
bash gh label list --json name,description --jq '.[] | select(.name | startswith("model: ")) | "\(.name)\t\(.description)"' gh label edit "model: opus" --description "Recommended model: Opus 5 (well-scoped features, refactors)"
Report each repair as drift fixed, not as a label created.
Model field exists — gh project field-list <N> --owner <OWNER> --format json. If absent, create it once:bash gh project field-create <N> --owner <OWNER> \ --name "Model" --data-type SINGLE_SELECT --single-select-options "Fable,Opus,Sonnet"
gh project item-list <N> --owner <OWNER> --limit 200 --format json. Diff against the open-issue list; an issue not on the board cannot receive a field value. Note the strays now so the apply step can gh project item-add them first. Trust item-list over any claim an issue body makes about its own board membership.Report the preflight result compactly: what existed, what you created, what needs adding to the board.
gh issue list --state open --limit 200 --json number,title,labels,body.--maintenance mode, narrow to issues with no model: label — plus any whose scope has visibly changed since labeling.Read each issue's body and, where scope is unclear, the code a fix would touch. For each, decide:
Note anything else the pass turns up — duplicates, already-shipped work, issues whose spec has drifted from the code. A careful read of every open issue surfaces this whether you want it or not, and it is worth more than the tiering.
Present the full mapping before touching anything:
textTiering — 23 issues (2 Fable / 12 Opus / 9 Sonnet) #58 Fable chord_only_line? has four dependents; a miss silently corrupts song files #49 Opus --transpose; test scaffold exists, contained. Watch: enharmonic spelling #50 Sonnet docs over a settled pipeline, no correctness stakes … Excluded (no tier, deliberate): #12 epic — children carry the tiers #77 qa report — derived tech issue carries the tier Proposed callouts (3): #49 "Opus, but escalate the enharmonic-spelling logic to Fable if it proves gnarly" … Also noticed: #61 appears to duplicate #44 #83 spec references a helper that no longer exists Board: 2 open issues are not board items (#71, #84) — will add before the field pass.
STOP for explicit approval. Nothing is labeled, no field is set, and no body is edited before the user says go. They may retier anything, drop callouts, or expand the exclusions. This gate is the whole safety model of the skill: it writes to every open issue in the repo, and a bad pass is tedious to unwind.
Only after approval, in this order:
gh project item-add <N> --owner <OWNER> --url <issue-url> for each, or their field values silently no-op.gh issue edit <n> --add-label "model: <tier>".gh project field-list … --format json) and the item IDs (gh project item-list … --format json), then per issue:bash gh project item-edit --id <ITEM_ID> --project-id <PROJECT_NODE_ID> \ --field-id <MODEL_FIELD_ID> --single-select-option-id <OPTION_ID>
bash gh issue view <n> --json body --jq .body > /tmp/body.md # build /tmp/head.md: the callout blockquote, a blank line, ---, a blank line cat /tmp/head.md /tmp/body.md > /tmp/final.md gh issue edit <n> --body-file /tmp/final.md
Callout template:
markdown > **🤖 Recommended model: <Model>.** <One sentence: why this tier, and the single watch-item or escalation trigger if any.>
bash gh issue list --state open --limit 200 --json number,labels --jq '[.[] | {n: .number, m: [.labels[].name | select(startswith("model"))]}] | map(select(.m | length != 1)) | map(.n)'
N Fable / N Opus / N Sonnet, flagship share) and how it compares to the calibration references.--body-file. Retyping loses content, and the loss is silent.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 4,091 | 8,307 | +103% | 1 | 1 | 0% | 557 | 3,421 | +514% | 0 | 0 | — |
case-02 | pass→pass | 8,476 | 3,965 | -53% | 1 | 1 | 0% | 1,470 | 3,304 | +125% | 0 | 0 | — |
case-03 | pass→pass | 10,260 | 3,087 | -70% | 1 | 1 | 0% | 1,686 | 3,234 | +92% | 0 | 0 | — |
case-04 | fail→pass | 12,627 | 3,850 | -70% | 1 | 1 | 0% | 1,701 | 3,347 | +97% | 0 | 0 | — |
case-05 | fail→pass | 10,094 | 3,962 | -61% | 1 | 1 | 0% | 1,671 | 3,337 | +100% | 0 | 0 | — |
case-06 | pass→pass | 4,608 | 2,561 | -44% | 1 | 1 | 0% | 743 | 3,140 | +323% | 0 | 0 | — |
case-07 | fail→fail | 8,663 | 4,662 | -46% | 1 | 1 | 0% | 1,329 | 3,494 | +163% | 0 | 0 | — |
case-08 | pass→pass | 3,799 | 2,677 | -30% | 1 | 1 | 0% | 516 | 3,151 | +511% | 0 | 0 | — |
case-09 | fail→pass | 6,398 | 3,492 | -45% | 1 | 1 | 0% | 1,020 | 3,343 | +228% | 0 | 0 | — |
case-10 | pass→pass | 10,497 | 4,870 | -54% | 1 | 1 | 0% | 1,726 | 3,630 | +110% | 0 | 0 | — |
case-11 | fail→pass | 8,024 | 3,828 | -52% | 1 | 1 | 0% | 1,207 | 3,349 | +177% | 0 | 0 | — |
case-12 | fail→pass | 9,014 | 3,030 | -66% | 1 | 1 | 0% | 1,377 | 3,166 | +130% | 0 | 0 | — |
case-13 | fail→pass | 13,291 | 4,349 | -67% | 1 | 1 | 0% | 1,983 | 3,377 | +70% | 0 | 0 | — |
case-14 | fail→pass | 10,141 | 2,887 | -72% | 1 | 1 | 0% | 1,410 | 3,236 | +130% | 0 | 0 | — |
case-15 | pass→pass | 12,157 | 4,490 | -63% | 1 | 1 | 0% | 2,065 | 3,526 | +71% | 0 | 0 | — |
case-16 | pass→pass | 4,308 | 10,100 | +134% | 1 | 1 | 0% | 667 | 3,431 | +414% | 0 | 0 | — |
case-17 | fail→pass | 12,240 | 1,858 | -85% | 1 | 1 | 0% | 2,035 | 3,032 | +49% | 0 | 0 | — |
case-18 | fail→pass | 6,037 | 3,316 | -45% | 1 | 1 | 0% | 945 | 3,212 | +240% | 0 | 0 | — |
case-19 | fail→pass | 14,683 | 12,806 | -13% | 1 | 1 | 0% | 2,618 | 5,183 | +98% | 0 | 0 | — |
case-20 | pass→pass | 23,390 | 10,751 | -54% | 1 | 1 | 0% | 2,285 | 4,844 | +112% | 0 | 0 | — |
case-21 | pass→pass | 14,721 | 9,739 | -34% | 1 | 1 | 0% | 2,233 | 4,251 | +90% | 0 | 0 | — |
case-22 | fail→fail | 7,956 | 2,720 | -66% | 1 | 1 | 0% | 1,174 | 3,114 | +165% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +45 percentage points is the difference between those two pass rates over the 21 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.