From dromsak-skills
Carve findings from the current conversation into well-shaped GitHub issues. Batches by module by default — one issue per module carrying ALL that module's findings (worker context-loading dominates cost, so N findings per file-read beats N file-reads). Generates title + acceptance-criteria body, classifies complexity (needs-sonnet vs needs-opus), wires same-surface `## Blocked by` markers automatically, and tags `ready-for-agent`. Companion to `/afk-army`, which then drains the resulting queue.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dromsak-skills:afk-issuesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`/afk-issues [opus|sonnet] [labels...]` — carve the findings the user just walked through into GitHub issues.
/afk-issues [opus|sonnet] [labels...] — carve the findings the user just walked through into GitHub issues.
The natural input is the current conversation: the user has been doing UAT, code review, grilling, or an /architect audit, has surfaced findings, and now wants them filed at agent-shaped granularity. The skill reads the recent conversation context, identifies each distinct finding, groups findings by module, and emits one issue per module group (see Batching below) — one issue per finding only when findings don't share a module.
The skill files issues against the repo you invoked it in — derived from the current directory's git remote. No gh repo set-default required (that's a separate, optional config; gh already resolves the repo from the cwd remote). Resolve it once at pre-flight and pass it explicitly to every gh call:
REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null)
If REPO is empty — not inside a git repo, or the remote isn't a GitHub repo gh can resolve (e.g. several remotes and no default to disambiguate) — bail with a clear message and ask the user to run the skill from inside the target repo (or set a default). Don't guess an owner/repo.
opus / sonnet — force every issue to that complexity class regardless of heuristic. Default: per-issue classification.labels... — extra labels to apply to every issue (e.g. polish, priority:high). Always applied IN ADDITION to the auto-assigned complexity label + ready-for-agent.ready-for-agent + complexity label per issue.Examples:
/afk-issues → file the conversation's findings, auto-classify each, no extra labels./afk-issues sonnet → file all findings as needs-sonnet even if the heuristic would lean opus./afk-issues opus polish → file as needs-opus, also tag polish.gh auth status — verify the user is logged in with a token that can create issues + apply labels. Bail with a clear message if not.REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null). This is whatever repo the skill was invoked in; no default-repo config needed. If empty, bail (not in a git repo, or unresolvable remote). Pass --repo "$REPO" to every gh command below.Before posting, verify the repo has the canonical label vocabulary. Missing labels are the most common source of silent failure for /afk-army workers.
required="ready-for-agent needs-sonnet needs-opus agent-working awaiting-merge polish"
for l in $required; do
gh label list --repo "$REPO" --search "$l" --json name --jq '.[].name' | grep -qx "$l" || \
echo "MISSING: $l"
done
If any are missing, offer to create them with gh label create <name> and short descriptions, then continue.
This is the token- and wall-clock lever; everything else is formatting. An /afk-army worker's cost is dominated by context loading — CLAUDE.md, conventions, reading the module — not by the diff it writes. One worker that reads patch_handler.rs once and fixes its five findings costs barely more than a worker that fixes one. So:
## Blocked by pointing at it. Never fold an extraction into one of its consumer batches./afk-army's merge-train sees near-zero conflicts.When the findings come from a bulk source with a written artifact (an /architect audit report, a long review doc), do not duplicate finding prose into issue bodies:
Read it in their worktree. If it isn't committed, stop and commit it (or have the user do so) before filing.**<finding-id>** — <one-line summary> (report § / file:line), plus a References entry naming the report path. The one-liners keep the issue skimmable on GitHub; the report carries the full problem/fix detail.A module batch is still one agent sitting. The "too big" markers below apply to scope breadth, not AC count — a batch of 12 mechanical riders in one module is fine; two unrelated surfaces in one issue is not. Split a batch at natural submodule seams when it exceeds ~15 findings, mixes opus-grade findings with mechanical riders such that the whole issue would classify opus for mostly-sonnet work (split by grade), or couples to another module's in-flight extraction (split + ## Blocked by).
Every issue body MUST follow this template — /afk-army workers parse it for AC and file references:
## What's broken
<2–6 sentences, concrete repro details, copy actual DOM/SQL/HTTP excerpts where helpful. Quote the user's reported symptom verbatim if they framed it precisely.>
Spotted in **<context>** (e.g. a UAT journey, a code review pass, a bug report).
## Approach
<2–5 sentences or a numbered list. Name the likely files. Don't prescribe the diff — describe the change.>
## Acceptance criteria
- [ ] <Concrete behavioural assertion 1>
- [ ] <…>
- [ ] <Last item is usually a regression-prevention or test-coverage item>
## References
- View / module: `<path>` (best guess; don't make up file paths)
- Repro URL: `<path>` (if web UI)
- Related docs / decisions as relevant
<verb>(<scope>): <short crisp summary> — match existing repo convention. Examples:
bug(dashboard): Last-updated column is missing the data-updated-at ISO 8601 attributepolish(orders): drop the Status column, fold the state into the row badgefeat(account): revoke active sessions and force re-login on password changeUse bug for breakage, polish for affordance/copy, feat for new capability, refactor for cleanup. Scope is the surface (one or two hyphenated words naming the affected module/page/feature) — sample what's already in git log --oneline -50 and match the style.
Aim for an issue a single agent worker can complete in a 30–90 minute run (verify gate included). Markers that the issue is TOO BIG:
If a finding is too big, split it: file 2–3 issues with explicit ## Blocked by markers chaining them in order.
Auto-assign one of needs-sonnet (default) or needs-opus per issue.
needs-opus heuristic — file as opus when the issue body contains any of:needs-sonnet heuristic — file as sonnet when:hx-post from X to Y")data-* attribute, swapping a column reference)When in doubt, prefer sonnet. Sonnet handles all of the above competently; Opus is the escalation path, not the default.
If args force a class (/afk-issues opus), skip the heuristic.
Before posting, harvest file path references from each issue body (look in ## Approach and ## References for backtick paths matching a code/config file extension). If two or more issues reference the same file, the lower-priority ones get a ## Blocked by #<oldest> block appended pointing at the first one in their group.
The mechanism stops /afk-army workers from racing schema/template drift when sibling issues touch the same surface.
# After all issues are drafted in /tmp/afk-issues-<N>.md files
declare -A surface_owner
for f in /tmp/afk-issues-*.md; do
n="${f##*/afk-issues-}"; n="${n%.md}"
# Adjust the extension list to match the languages in the target repo
paths=$(grep -oE '`[a-zA-Z0-9_./-]+\.(rs|js|ts|tsx|jsx|py|go|java|rb|php|sql|yaml|yml|toml|json|md|html|css|j2|hbs)`' "$f" | tr -d '`' | sort -u)
for p in $paths; do
if [[ -n "${surface_owner[$p]}" ]]; then
printf '\n\n## Blocked by\n\nSame-surface conflict with #%s (`%s`). Will pick up automatically once #%s lands and main settles.\n' "${surface_owner[$p]}" "$p" "${surface_owner[$p]}" >> "$f"
break
else
surface_owner[$p]=$n
fi
done
done
#<oldest> here means "the issue I'm about to file first" — the array tracks order of carve, not GitHub numbering (since we don't know the issue numbers until gh issue create returns them). After creation, the ## Blocked by markers need to be rewritten with the real issue numbers — see "Posting" below.
/tmp/afk-issues-<seq>.md (seq = 01, 02, ...).<seq> as the placeholder.gh issue create --repo "$REPO" --title "<title>" --body-file /tmp/afk-issues-<seq>.md --label ready-for-agent --label <complexity-label> [--label <extras>]. Capture the returned URL (and parse the issue number from it).Same-surface conflict with #<seq> references in the bodies to their real GitHub numbers, then gh issue edit <blocked-number> --repo "$REPO" --body-file <updated-file>. (Two passes is cleaner than racing the issue numbers during creation.)#935 [sonnet] dashboard: missing data-updated-at attribute
#936 [sonnet] dashboard: "just now" shown for future timestamps ⏸ blocked by #935
#937 [sonnet] search: category filter uses the wrong slug
#938 [sonnet] checkout: only 2/16 promo codes apply
#939 [sonnet] search: "No results" shown while results exist ⏸ blocked by #937
#940 [sonnet] onboarding: verify-email link returns 404
#941 [sonnet] orders: status filter renders empty
#942 [sonnet] notifications: weekly digest not sent
Filed 8 issues. 6 ready, 2 same-surface-deferred.
Run `/afk-army` to drain — no args: worker models come from the per-issue labels, and the Workflow runtime owns parallelism.
needs-sonnet and needs-opus. Pick one.needs-opus to a polish/template-edit issue just because the broader area is complex. Classify on the change, not the surface./afk-issues reclassify — walk all open ready-for-agent issues that lack a complexity label, run the heuristic on each, and apply needs-sonnet or needs-opus. Useful after this skill is introduced to backfill the existing backlog. Doesn't touch issues that already have a complexity label.
REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner)
gh issue list --repo "$REPO" --label ready-for-agent --limit 100 --json number,labels,body \
| jq -r '.[] | select((.labels | map(.name) | contains(["needs-sonnet"]) or contains(["needs-opus"])) | not) | "\(.number)\t\(.body | gsub("\n"; " ") | .[0:200])"' \
| while IFS=$'\t' read -r num body; do
# apply heuristic, then:
gh issue edit $num --repo "$REPO" --add-label needs-sonnet
done
Print the reclassification table at the end.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub dromsak/skills --plugin dromsak-skills