| name | autospec-classify |
| description | Use when the user wants to retro-apply autospec's Phase 3.5 model-fit rubric to already-existing auto-implement issues — walks open issues in the current GitHub repo, classifies each with ctx:* / reasoning:* labels, and inserts a |
autospec-classify (harness-neutral)
Standalone retro-labeler. Walk every open auto-implement issue in the current
GitHub repo (excluding type:tracker-labeled issues), apply the Phase 3.5
model-fit rubric, and write a ## Model fit block into the issue body. Default
mode is labels-only; the --apply-boards flag opts into board assignment from
~/.autospec/project-map.yml.
Manage your own context — never exceed 60%. Delegate to subagents whenever your harness supports it.
Self-update mode
If the feature-request argument matches the regex ^\s*update\s*$ (case-insensitive, whitespace-padded), this skill enters self-update mode and does not run the normal pipeline:
- Detect harness by checking which install path exists for this skill:
- Claude Code:
~/.claude/skills/autospec-classify/SKILL.md
- OpenCode:
~/.config/opencode/agent/autospec-classify.md
- Codex CLI:
~/.codex/prompts/autospec-classify.md
- Re-install the full autospec suite from
main by piping the canonical installer:
curl -fsSL https://raw.githubusercontent.com/berlinguyinca/autospec/main/bootstrap.sh | bash -s -- --skill all --harness all --update
Run this one-liner once; it refreshes all autospec skills across all harnesses.
- Show the diff between the prior installed file(s) and the freshly fetched copy (e.g.
diff <(cat <prior>) <(curl -fsSL ...SKILL.md) or the equivalent recorded by the installer).
- Stop. Do not enter Phase 0 / Phase 1 / any pipeline phase. Print the upgrade summary and return to the user.
If no install path is detected, print Self-update: no installed copy of autospec-classify found; run install.sh first. and exit.
Invocation
/autospec-classify [--issues N,N,N] [--label <label>] [--apply-boards] [--dry-run]
--issues N,N,N — restrict to a comma-separated list of issue numbers (default:
every open issue in the current repo).
--label <label> — restrict to issues carrying a specific label
(default: auto-implement).
--apply-boards — also assign issues to GitHub Projects per
~/.autospec/project-map.yml. If the file is missing on first run, auto-init
writes a starter file keyed on the repo's labels with null project numbers
and exits with Wrote ~/.autospec/project-map.yml. Edit project numbers (currently null) and re-run.. Without --apply-boards the project-map is
not consulted.
--dry-run — print proposed labels, model-fit blocks, and board assignments
without calling gh issue edit or gh project item-add.
The skill exits non-zero if gh auth status fails or the current cwd is not a
GitHub-tracked repo.
Required capabilities & harness adapter
This workflow assumes a small set of capabilities. Map each one to your harness's actual tool. If a capability is missing, use the listed fallback.
| Capability | Claude Code | OpenCode | Codex CLI | Fallback if missing |
|---|
| Read-only codebase research | Agent (subagent_type=Explore) | task agent in read-only mode | apply_patch read-only / shell grep | Do the search in-thread with rg/grep |
| Foreground delegation | Agent (subagent_type=general-purpose) | nested task agent, await output | spawn nested CLI session | Do the work in-thread (more context cost) |
| Ask the user a question | AskUserQuestion | inline prompt | inline prompt | Ask in the response and wait for the next turn |
| Subagent model tier | Tier A: opus + ultrathink; Tier B: sonnet + medium thinking | Tier A: top task model + high reasoning; Tier B: smaller-tier task + medium reasoning | Tier A: top GPT + reasoning_effort=high; Tier B: gpt-5.1-codex-spark + reasoning_effort=medium | Honor the per-phase tier mapping in AGENTS.md; retry the same subagent UP on unavailability |
Persistent project notes: write durable preferences to AGENTS.md in the repo root — this is the de-facto standard recognized by Claude Code (also reads CLAUDE.md), OpenCode, and Codex. If your harness has its own private memory (e.g. Claude Code's ~/.claude/.../memory/), mirror the same content there. Per AGENTS.md, subagent dispatches use a two-tier policy: Tier A (top model + extended thinking) for spec work and Tier B (cheaper model + medium thinking) for implementation work. This skill's per-issue classification is deterministic-first: the deterministic rubric runs with no LLM call, and only ambiguous issues escalate to a single Tier-B LLM tie-breaker — never Tier A. The orchestrator keeps the user's invoked model. Fall back UP the tier on quota/capacity or other unavailability by retrying the same subagent with the stronger tier while preserving parent context.
Harness detection (run once at skill start, before Phase 0)
Detect your harness by checking available tools before any phase:
-
Claude Code — the Agent tool with a subagent_type parameter is available.
TIER_A = opus + ultrathink (model ID: claude-opus-4-7)
TIER_B = sonnet (model ID: claude-sonnet-4-6)
-
OpenCode — a task tool with model/tier configuration is available (no subagent_type).
TIER_A = top-tier task model + high reasoning
TIER_B = smaller-tier task model + medium reasoning
-
Codex CLI — neither Agent nor a configurable task tool is available; apply_patch is the primary edit tool.
TIER_A = current top GPT model + reasoning_effort=high
TIER_B = gpt-5.1-codex-spark + reasoning_effort=medium
Fallback rule: If TIER_B is not available in your harness (model unknown, quota/capacity failure, authorization failure, or tool call returns an error for that model), silently retry the same subagent dispatch with TIER_A. Preserve the parent context on retry; for Codex native subagents, fork/inherit the current conversation context and use the latest top GPT model instead of moving the work into the main session. Never ask the user.
Hold TIER_A and TIER_B for the entire skill run. Every "Tier A" and "Tier B" reference below resolves to these harness-specific values.
Relevant memory injection (run-start, once)
Before executing the main pipeline phases, call the injector to surface relevant saved lessons:
bash "${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/inject-relevant-memory.sh" \
--context "<skill-relevant keywords from request/issue/spec>" \
--top-k 5
Prepend the output block (if non-empty) to your working context. This surfaces lessons like
feedback_bash_return_trap_leak.md that prevent re-occurrence of known pitfalls.
Pre-flight
- Verify
gh auth status is authenticated.
- Capture
{repo} from gh repo view --json nameWithOwner -q .nameWithOwner.
- Resolve the candidate set — walk both
auto-implement AND
needs-classify issues (per spec §5.3, listener-filed issues land
labeled needs-classify and /autospec-classify is the entry point
that transitions them onto the implementation queue):
gh issue list --repo {repo} --label <label> --state open --limit 500 --json number,title,labels,body,url
for the value of --label (default auto-implement).
- Additionally,
gh issue list --repo {repo} --label needs-classify --state open --limit 500 --json number,title,labels,body,url.
- Merge both result sets, deduplicating by issue number (an issue may
carry both labels during a partial transition).
- Filter out any issue whose labels include
type:tracker.
- Apply the
--issues filter if provided.
Issue intent safety gate
The classifier may persist model-fit and quality metadata, but it must never
author an automatic safety decision. After the final body is persisted, the
Rust queue command is the only authority for an admission pass, ambiguity, or
block.
Label transition for needs-classify issues
For every issue in the candidate set whose labels include needs-classify, run
the Rust admission only after Steps 2–6 of the per-issue procedure have
persisted the final body. First make the issue an interim queue candidate, then
review that exact issue:
gh issue edit <N> --add-label auto-implement --remove-label needs-classify --repo {repo}
"${AUTOSPEC_BIN:-autospec}" queue review-safety --repo {repo} --limit 1 --issue <N>
Read the command's JSON totals. Only pass: 1 admits this invocation. Any
other result is already recorded by Rust and must be skipped without a prompt,
shell, or semantic reviewer changing labels, comments, or issue body. Issues
already carrying auto-implement are re-classified in place, then receive the
same exact review after their final body is persisted.
Rubric
ctx:* — context-window axis
Pick the smallest tier that holds the staged context (issue body + every file
listed under ## Files to read first + the relevant spec sections).
| Label | Approx. token ceiling | Trigger |
|---|
ctx:32k | ~32k tokens of staged context | One canonical table or one shell script; ≤3 files in Files to read first; spec anchors are short. |
ctx:64k | ~64k tokens | Multi-file change; 4-7 files staged; one trio + one installer; medium spec sections (~1-3 KB). |
ctx:120k | ~120k tokens | Cross-skill or cross-package; 8+ files; long spec excerpts; deep call graphs. |
If unsure between two tiers, prefer the larger tier.
reasoning:* — reasoning-depth axis
Pick the depth required to derive the implementation, not just transcribe it.
| Label | Trigger |
|---|
reasoning:shallow | Mechanical: copy-and-rename, regex-replace, README transcription, runbook authoring. Verbs in the issue: copy, rename, transcribe, list. |
reasoning:medium | Template-following with judgment calls: synthesize a new SKILL.md by mirroring an existing one, modify a script with new flags, write tests for a documented contract. Verbs: mirror, adapt, integrate, wire. |
reasoning:deep | Novel design choices: pick a new abstraction, resolve a contradiction in the spec, reconcile cross-cutting concerns. Verbs: design, reconcile, resolve, redesign. |
Default for issues that lack any of these signals: ctx:64k, reasoning:medium.
Per-issue procedure
Model tier: deterministic-first; TIER_B on ambiguity (never TIER_A).
Classification runs the deterministic
rubric (${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/classify-model-fit.sh — file counts, verb keywords, per
tracker #421) FIRST, with no LLM dispatch for issues it can score
confidently. Only issues the rubric flags as ambiguous (confidence below
LLM_ESCALATION_THRESHOLD, default 0.3) escalate to a single TIER_B LLM
tie-breaker — never TIER_A. Sibling normalization stays deterministic. Set
AUTOSPEC_REVIEWER_TIER=opus only governs the run-trio reviewer, not this
classifier; the classifier's LLM tie-breaker is always TIER_B.
For each candidate issue:
-
Sanity check. Body must contain both ## Files to read first and
## Implementation scope. If either is missing:
- Add label
needs-autospec-template (idempotent, gh label create --force
once at the top of the run).
- Skip — do not modify body, do not assign a model-fit class.
-
Classify (deterministic-first). Run the deterministic rubric first
(${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/classify-model-fit.sh <body-file>): it assigns one ctx:* and one
reasoning:* label from file counts and verb keywords with zero LLM cost.
Only when the rubric reports deterministic:false (confidence below
LLM_ESCALATION_THRESHOLD) escalate that single ambiguous issue to one
TIER_B LLM tie-breaker; otherwise take the deterministic result as final.
Print the rationale (and whether it was deterministic or escalated) in the
dry-run preview.
-
Apply labels.
gh label create ctx:32k --color c5def5 --force (and ctx:64k, ctx:120k).
gh label create reasoning:shallow --color c2e0c6 --force
(and reasoning:medium, reasoning:deep).
gh label create needs-quality-bar --color fbca04 --force --repo {repo} (once at run start, idempotent).
gh issue edit <N> --add-label "ctx:<tier>,reasoning:<depth>" --repo {repo}.
- Skip in
--dry-run.
-
Patch body. Insert a ## Model fit block immediately before the first
## Dependencies line (or, if absent, at end of body). Block format:
## Model fit
- **ctx:** `ctx:<tier>` — <1-line rationale>.
- **reasoning:** `reasoning:<depth>` — <1-line rationale>.
<!-- autospec-classify:begin -->
*Auto-classified by `/autospec-classify` on YYYY-MM-DD.*
<!-- autospec-classify:end -->
Idempotency: if a ## Model fit block already exists (delimited by the
<!-- autospec-classify:begin --> / <!-- autospec-classify:end -->
markers), replace it in place. Never stack duplicate blocks.
Apply via gh issue edit <N> --body-file <tmp>.
-
Board assignment (only if --apply-boards):
- Read
~/.autospec/project-map.yml. If the file is missing, auto-init it
(see below) and exit so the user can fill in project numbers.
- File schema:
multi_match: union
mappings:
ctx:32k: <project_number>
ctx:64k: <project_number>
ctx:120k: <project_number>
reasoning:shallow: <project_number>
reasoning:medium: <project_number>
reasoning:deep: <project_number>
<any-other-label>: <project_number>
- Reader procedure. For each label L on the issue, look up
mappings[L]. Skip null / missing entries. With multi_match: union
(default), assign the issue to every matching project number; with
multi_match: first, assign only to the first match in label-order.
For each chosen <P>:
gh project item-add <P> --owner <owner> --url <issue-url>. The
command is idempotent so re-running this skill does not duplicate
project items.
- Auto-init when the file is missing. Probe
gh project list --owner <owner> --format json to confirm the user
can author projects. Probe
gh label list --repo {repo} --json name -q '.[].name' to enumerate
the repo's labels. Write a starter file with every label as a
mappings: key and null project numbers, plus multi_match: union
at the top. Print:
Wrote ~/.autospec/project-map.yml. Edit project numbers (currently null) and re-run.
Then exit non-zero (this is a hard stop unique to
--apply-boards; without the flag the run continues normally).
- Skip in
--dry-run.
-
Quality audit. After patching the ## Model fit block:
- Pull body:
gh issue view <N> --repo {repo} --json body -q .body > /tmp/audit-<N>.md
- Run:
bash "${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/lint-issue.sh" /tmp/audit-<N>.md
- On non-zero exit (lint fails):
- Do NOT remove
auto-implement label. Operator decides whether to proceed.
- Skip in
--dry-run.
-
Rust safety admission. After every model-fit and quality-body write has
completed, admit the exact issue with the command in
Label transition for needs-classify issues.
For an issue already carrying auto-implement, do not change ordinary
labels first; invoke the same exact command. Only a JSON pass: 1 result is
eligible for later implementation work.
Sibling normalization (forward reference)
When 5+ sibling issues share a structural criterion (e.g. all are
"per-source-table writers"), harmonize their ctx:* and reasoning:* labels so
the operator can run a single profile across the whole group. The full
sibling-normalization prompt is part of Phase 3.5 (PR B1, issue #14); when it
lands, this skill calls into it. Until then, classify each sibling
independently.
Run-end summary
Print:
autospec-classify run summary on {repo}
- classified: N
- skipped (needs-autospec-template): M
- ctx:32k=A ctx:64k=B ctx:120k=C
- reasoning:shallow=X reasoning:medium=Y reasoning:deep=Z
- boards assigned: <K> (or "skipped — --apply-boards not set" / "skipped — no project-map.yml")
Hard rules
- Never modify the issue title.
- Never remove existing labels — only add
ctx:*, reasoning:*,
needs-autospec-template.
- Never call
gh issue edit in --dry-run mode.
- Always idempotent — running twice on the same issue results in no diff after
the second run (same labels, same
## Model fit block).
gh CLI only; no direct GraphQL.