| name | write-issue |
| description | Write a well-structured GitHub issue for ZeeKayDa.Auth — decides between an ADR issue and an implementation issue, applies the issue templates, hierarchy, and labels, and links sub-issues to their epic. Use when fleshing out a new idea, filing a bug, creating design or implementation issues, or triaging incoming issues. |
| argument-hint | ["idea or issue description"] |
| allowed-tools | ["Bash(gh *)"] |
Write a GitHub Issue
This skill turns ideas, bug reports, and tasks into complete, actionable GitHub issues. It runs in the main session on purpose: issue writing depends on the conversation that led up to it.
This project's owner is learning OSS best practices — explain the reasoning behind process choices, don't just produce artifacts.
Step 1 — Decide the issue type
Does this work need an ADR? An ADR is warranted for non-obvious decisions with lasting consequences: new abstractions, storage contracts, public API shape, security-sensitive designs, or anything where "why did we choose this?" will matter in 6 months.
Routine work does not need an ADR: adding a property to an existing model, fixing a bug, implementing something fully prescribed by the spec, or adding tests.
- ADR needed → write an ADR issue (design phase). Never write the implementation issues yet — they come after the ADR PR merges.
- No ADR needed → write an implementation issue directly.
- Uncertain → ask the user before deciding.
Never write an ADR issue until the problem is fully understood — ask clarifying questions first.
Step 2 — Identify or create the parent epic
Every type:design and type:task issue must be a sub-issue of a type:epic. If no epic exists for the feature area, create one first (title prefix: Epic: ). Epics are permanent coordination points, closed only when all sub-issues are closed — confirm with the user before closing one.
Step 3 — Write the issue
ADR issues (type:design)
Frame the problem, not the solution:
- Concise title in imperative sentence case ("Design client registration model") — no implementation details, no label-like prefixes
- Problem statement — what gap is being addressed, why it needs an ADR
- Known constraints — spec requirements, backward compatibility, security constraints
- Spec references — exact spec sections the design must satisfy
- Open design questions — the decisions the ADR must resolve (the architect's agenda)
- Sign-off criteria — what the ADR must answer; the issue closes when the ADR PR merges
- Security flag — note if tokens/crypto/protocol flows are involved; security must sign off on the ADR PR
Quality bar: "Does this give the architect a clear agenda and unambiguous sign-off criteria?"
Labels: type:design, relevant area:*, priority:*
Implementation issues (type:task)
Written only after the ADR PR merges (for ADR-path work):
- Concise title in imperative sentence case — no
feat:/fix: prefixes, no type:*/area:*/priority:* tokens (classification belongs in labels)
- Context — why this is needed; link the accepted ADR
- Scope — what is in and explicitly out of scope
- Acceptance criteria — concrete, testable conditions derived from the ADR, not speculative
- Security considerations — tag
area:security where relevant
- Spec alignment — cite the exact spec section being implemented (e.g. "per RFC 7636 §4.3"); flag conflicts with the spec before writing the issue
- Docs requirement — tag
area:docs if public-facing
- References — ADR link, RFC sections, related issues
- End with: "The docs agent must be involved — documentation is required for all public-facing changes"
Quality bar: "Could a developer implement this with no further questions?"
Labels: type:task (or other type:*), relevant area:*, priority:*
Label taxonomy
area:core, area:aspnetcore, area:analyzers, area:docs, area:ci, area:security, area:extensibility
type:epic, type:task, type:bug, type:feature, type:design, type:refactor, type:test, type:docs, type:chore
priority:critical, priority:high, priority:medium, priority:low
status:idea (unscoped future work, hidden from active view), status:needs-repro, status:ready
There is deliberately no status:blocked label — blocked state is tracked with GitHub's native blocked-by relations (see Step 4), which resolve automatically when the blocking issue closes.
good first issue, help wanted, wontfix, duplicate, question
Active work query: is:open -label:status:idea
Step 4 — Link the sub-issue to its epic
Always use the native GitHub sub-issues API — never a text "Sub-issues" list in the epic body, never Sub-issue of #N lines in child bodies:
gh api graphql -f query='{ repository(owner: "OWNER", name: "REPO") { issue(number: N) { databaseId } } }'
gh api -X POST /repos/OWNER/REPO/issues/PARENT_NUMBER/sub_issues --field sub_issue_id=DATABASE_ID
Do this immediately after creating any issue that belongs to an epic. Sub-issue ordering reflects execution sequence — design before tasks, foundational tasks before dependent ones.
Blocked issues
When an issue cannot start until another issue closes, record it with GitHub's native blocked-by relation — never a status:blocked label, never only body prose:
gh api -X POST /repos/OWNER/REPO/issues/BLOCKED_NUMBER/dependencies/blocked_by -F issue_id=DATABASE_ID
The relation shows on both issues and resolves automatically when the blocker closes. A short body note explaining why it is blocked is still good practice; the relation is the machine-readable state.
Triaging incoming issues
- Apply the correct labels; identify duplicates and close with a link to the canonical issue
- Ask for reproduction steps on bug reports before accepting them
- Close stale issues with empathy — thank the reporter
- Security reports: escalate immediately to the private security advisory process — never a public issue