Add /write-issue skill for interactive Gitea issue creation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
163
.claude/commands/write-issue.md
Normal file
163
.claude/commands/write-issue.md
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
description: Interactive interview to create a well-structured Gitea issue with business-level acceptance criteria.
|
||||
---
|
||||
|
||||
## User Input
|
||||
|
||||
```text
|
||||
$ARGUMENTS
|
||||
```
|
||||
|
||||
You **MUST** consider the user input before proceeding (if not empty).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Verify the `GITEA_TOKEN_ISSUES` environment variable is set:
|
||||
|
||||
```bash
|
||||
test -n "$GITEA_TOKEN_ISSUES" && echo "TOKEN_OK" || echo "TOKEN_MISSING"
|
||||
```
|
||||
|
||||
If missing, tell the user to set it:
|
||||
```
|
||||
export GITEA_TOKEN_ISSUES="your-gitea-personal-access-token"
|
||||
```
|
||||
Then abort.
|
||||
|
||||
2. Parse the git remote to extract the Gitea base URL, owner, and repo:
|
||||
|
||||
```bash
|
||||
git config --get remote.origin.url
|
||||
```
|
||||
|
||||
Expected format: `ssh://git@<host>:<port>/<owner>/<repo>.git` or `https://<host>/<owner>/<repo>.git`
|
||||
|
||||
Extract:
|
||||
- `GITEA_HOST` — the hostname (e.g. `git.bahamut.nitrix.one`)
|
||||
- `GITEA_PORT` — the port if present in SSH URL (for API, always use HTTPS on default port)
|
||||
- `OWNER` — the repo owner/org
|
||||
- `REPO` — the repo name (strip `.git` suffix)
|
||||
- `API_BASE` — `https://<GITEA_HOST>/api/v1`
|
||||
|
||||
Verify the remote is reachable:
|
||||
```bash
|
||||
curl -sf -H "Authorization: token $GITEA_TOKEN_ISSUES" "$API_BASE/repos/$OWNER/$REPO" | head -c 200
|
||||
```
|
||||
|
||||
If this fails, abort with an error explaining the API is unreachable.
|
||||
|
||||
## Interview Flow
|
||||
|
||||
### Step 1 — What's the feature?
|
||||
|
||||
If `$ARGUMENTS` is not empty, use it as the initial feature description and skip asking.
|
||||
|
||||
Otherwise, ask the user: **"What feature or change do you want to build?"**
|
||||
|
||||
Accept a free-form description (1-3 sentences is fine).
|
||||
|
||||
### Step 2 — Contextual business questions
|
||||
|
||||
Analyze the feature description and identify what's ambiguous or underspecified **for this specific feature**. Generate 1-3 targeted questions that would materially improve the issue.
|
||||
|
||||
Rules:
|
||||
- Questions MUST be derived from the specific feature description, not from a generic checklist.
|
||||
- Only ask questions whose answers change the scope, behavior, or acceptance criteria.
|
||||
- If the feature is straightforward and well-described, skip this step entirely.
|
||||
- Present one question at a time using the AskUserQuestion tool.
|
||||
- For each question, provide 2-4 concrete options plus the ability to give a custom answer.
|
||||
- After each answer, decide if you need another question or have enough clarity.
|
||||
|
||||
Examples of good contextual questions:
|
||||
- For a "color overhaul" feature: "Are you targeting specific components or a global palette change?"
|
||||
- For a "bulk import" feature: "Should the user see progress during import or just a final result?"
|
||||
- For an "initiative tiebreaker" feature: "Should ties be broken by DEX score, manual choice, or random roll?"
|
||||
|
||||
Examples of bad questions (never ask these):
|
||||
- Generic: "Who is the target user?"
|
||||
- Obvious: "Should errors be handled?"
|
||||
- Implementation: "What database should we use?"
|
||||
|
||||
### Step 3 — Acceptance criteria
|
||||
|
||||
Based on the description and clarifications, draft 3-8 business-level acceptance criteria. These should describe **what the user can do or see**, not how the system implements it.
|
||||
|
||||
Present the draft to the user and ask if they want to add, remove, or change any.
|
||||
|
||||
Good: "User can load all sources with a single click"
|
||||
Bad: "System fires concurrent fetch requests to IndexedDB"
|
||||
|
||||
### Step 4 — Labels and milestone (optional)
|
||||
|
||||
Fetch available labels and milestones from the Gitea API:
|
||||
|
||||
```bash
|
||||
curl -sf -H "Authorization: token $GITEA_TOKEN_ISSUES" "$API_BASE/repos/$OWNER/$REPO/labels"
|
||||
curl -sf -H "Authorization: token $GITEA_TOKEN_ISSUES" "$API_BASE/repos/$OWNER/$REPO/milestones"
|
||||
```
|
||||
|
||||
If labels/milestones exist, present them to the user and ask which (if any) to apply. If none exist or the API returns empty, skip this step.
|
||||
|
||||
### Step 5 — Branch linking
|
||||
|
||||
Check if we're on a feature branch:
|
||||
|
||||
```bash
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
If the current branch is not `main` (and looks like a feature branch, e.g. `NNN-feature-name`), offer to include it in the issue body as a linked branch.
|
||||
|
||||
### Step 6 — Preview and create
|
||||
|
||||
Compose the issue body using this template:
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
<2-3 sentence description synthesized from the interview>
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] <criterion 1>
|
||||
- [ ] <criterion 2>
|
||||
- [ ] <criterion 3>
|
||||
...
|
||||
|
||||
## Branch
|
||||
|
||||
`<branch-name>` *(if linked in step 5)*
|
||||
```
|
||||
|
||||
Show the full preview (title + body) to the user and ask for confirmation.
|
||||
|
||||
On confirmation, create the issue:
|
||||
|
||||
```bash
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN_ISSUES" \
|
||||
-H "Content-Type: application/json" \
|
||||
"$API_BASE/repos/$OWNER/$REPO/issues" \
|
||||
-d @- <<'PAYLOAD'
|
||||
{
|
||||
"title": "<issue title>",
|
||||
"body": "<issue body>",
|
||||
"labels": [<label IDs if selected>],
|
||||
"milestone": <milestone ID if selected or null>
|
||||
}
|
||||
PAYLOAD
|
||||
```
|
||||
|
||||
Parse the response and report:
|
||||
- Issue number and URL (`https://<GITEA_HOST>/<OWNER>/<REPO>/issues/<number>`)
|
||||
- Suggest next step: `/issue-to-spec <number>` to start speccing
|
||||
|
||||
## Behavior Rules
|
||||
|
||||
- Keep the title short — under 70 characters.
|
||||
- Acceptance criteria must be business-level, not implementation details.
|
||||
- Never create an issue without user confirmation of the preview.
|
||||
- If any API call fails, show the error and suggest the user check their token permissions.
|
||||
- Use `curl` for all API calls — do not rely on `gh` CLI.
|
||||
- Always use HEREDOC for the JSON payload to handle special characters in the body.
|
||||
- Escape double quotes and newlines properly in the JSON body.
|
||||
Reference in New Issue
Block a user