Skip to content

Commit af7b8f7

Browse files
e5lclaude
andauthored
Add fix-bug Claude Code skill for automated bug fixing workflow (#5386)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 17f9fda commit af7b8f7

File tree

1 file changed

+270
-0
lines changed

1 file changed

+270
-0
lines changed

.claude/skills/fix-bug/SKILL.md

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
---
2+
name: fix-bug
3+
description: "End-to-end bug fix workflow for the Ktor project. Accepts a GitHub issue (#NUMBER), YouTrack issue (KTOR-NUMBER), or YouTrack URL (https://youtrack.jetbrains.com/issue/KTOR-NUMBER). Fetches the issue, creates a failing reproducer test, commits on a new branch, implements the fix, validates, and opens a PR. Use this skill whenever the user wants to fix a bug from an issue tracker, mentions a KTOR issue number, or references a GitHub issue to fix."
4+
user_invocable: true
5+
---
6+
7+
# Fix Bug Skill
8+
9+
Automates the full bug-fix lifecycle for the Ktor project: understand issue, reproduce, fix, validate, and open a PR.
10+
11+
## Input Parsing
12+
13+
The user provides one of:
14+
- `#123` — GitHub issue in `ktorio/ktor`
15+
- `KTOR-9352` — YouTrack issue ID
16+
- `https://youtrack.jetbrains.com/issue/KTOR-9352` or `https://youtrack.jetbrains.com/issue/KTOR-9352/some-slug` — YouTrack URL
17+
18+
Parse the input to determine the source:
19+
20+
1. **GitHub**: Extract the number, fetch via `gh issue view NUMBER --repo ktorio/ktor`
21+
2. **YouTrack ID** (pattern `KTOR-\d+`): Fetch via the YouTrack MCP (see below)
22+
3. **YouTrack URL**: Extract the `KTOR-XXXX` ID from the URL, then fetch via the YouTrack MCP (see below)
23+
24+
### Fetching YouTrack Issues
25+
26+
Use the YouTrack MCP tools to fetch issue details. Call `mcp__youtrack__get_issue` with the issue ID (e.g., `KTOR-9352`).
27+
28+
If the YouTrack MCP server is not configured (tool calls fail), instruct the user to set it up:
29+
30+
```bash
31+
claude mcp add --header "Authorization: Bearer <token>" --transport http youtrack https://youtrack.jetbrains.com/mcp
32+
```
33+
34+
The permanent token can be created in JetBrains Hub account security settings (linked from YouTrack profile).
35+
36+
From the issue, extract:
37+
- **Title and description** of the bug
38+
- **Steps to reproduce** (if provided)
39+
- **Expected vs actual behavior**
40+
- **Affected module(s)** — identify which Ktor Gradle module is relevant
41+
- **Issue comments** — read through comments as they might contain useful information (reproduction details, workarounds, related context)
42+
- **Issue ID** for branch naming and commit messages (e.g., `KTOR-9352` or `#123`)
43+
44+
## Step 1: Assign Issue and Set In Progress
45+
46+
For **YouTrack issues only**, update the issue status to reflect that work is starting:
47+
48+
1. Call `mcp__youtrack__get_current_user` to get the current user's login.
49+
2. Call `mcp__youtrack__change_issue_assignee` to assign the issue to the current user.
50+
3. Call `mcp__youtrack__update_issue` with `customFields: {"State": "In Progress"}` to mark work as started.
51+
52+
If any of these calls fail because the YouTrack MCP is not configured, inform the user how to set it up (see "Fetching YouTrack Issues" section above) and continue with the rest of the workflow — issue tracking updates are not blocking.
53+
54+
Skip this step for GitHub-only issues.
55+
56+
## Step 2: Understand the Codebase Context
57+
58+
Before creating a branch, understand the affected area:
59+
- Identify the Gradle module from the issue description or affected APIs
60+
- Read existing tests in that module to understand test patterns and conventions
61+
- Identify whether this needs a unit test or integration test based on the bug nature
62+
- Remember: this project uses a **flattened Gradle structure** (e.g., `ktor-client/ktor-client-curl``:ktor-client-curl`)
63+
64+
Use the Explore agent or direct file reads to understand:
65+
- The relevant source code where the bug likely lives
66+
- Existing test infrastructure (test utilities, base classes, server setup patterns)
67+
- How similar tests are structured in the same module
68+
69+
## Step 3: Create branch
70+
71+
Determine the base branch:
72+
- Use `release/3.x` for bug fixes that do **not** introduce new public APIs (patch release)
73+
- Use `main` for fixes that require new public APIs or are targeted at the next minor release
74+
75+
```bash
76+
git checkout <base-branch> && git pull && git checkout -b claude/<issue-id>-<short-description>
77+
```
78+
79+
Branch naming rules:
80+
- For YouTrack issues: `claude/KTOR-9352-short-description`
81+
- For GitHub issues: `claude/123-short-description`
82+
- The short description is 3 words max, lowercase, hyphenated, derived from the issue title
83+
84+
## Step 4: Write a Failing Reproducer Test
85+
86+
Write a test that demonstrates the bug as described in the issue. The goal is:
87+
- **Minimal**: Only test the specific buggy behavior, nothing extra
88+
- **Clear**: Test name in backticks should describe the bug (e.g., `` `KTOR-9352 request with empty body causes NPE` ``)
89+
- **Failing**: The test MUST fail on the current codebase to confirm the bug exists
90+
91+
Place the test appropriately:
92+
- Near existing tests for the same module/feature
93+
- If no test suite exists for this area, create a new test class following the module's conventions
94+
- For integration tests, place near other integration tests in the module
95+
- For unit tests, place near other unit tests
96+
- If the bug is platform-specific, place the test in the corresponding platform source set (e.g., `jvm/test`, `posix/test`)
97+
- If the bug affects common/shared code, place the test in `common/test` so it runs on all platforms
98+
99+
After writing the test, run it to confirm it fails:
100+
```bash
101+
./gradlew :module-name:jvmTest --tests "fully.qualified.TestClassName.methodName"
102+
```
103+
104+
If the test is in `common/test` or touches multiplatform code, also run on other affected platforms:
105+
```bash
106+
./gradlew :module-name:allTests
107+
```
108+
109+
If the test passes (bug is already fixed or test doesn't reproduce correctly):
110+
- Re-read the issue carefully
111+
- Adjust the test to more precisely match the reported scenario
112+
- If the bug truly cannot be reproduced, inform the user and stop
113+
114+
## Step 5: Commit the Reproducer
115+
116+
Stage and commit the failing test:
117+
```bash
118+
git add <test-file>
119+
git commit -m "<ISSUE-ID> Add failing test for <short bug description>
120+
121+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
122+
```
123+
124+
For GitHub issues, use `#NUMBER` in the commit message. For YouTrack, use `KTOR-XXXX`.
125+
126+
## Step 6: Plan and Implement the Fix
127+
128+
Analyze the bug based on what you learned from the issue and the reproducer test:
129+
- Trace the code path that leads to the failure
130+
- Identify the root cause
131+
- Plan the minimal fix
132+
133+
Implement the fix directly — do not present the plan to the user for approval. Keep changes minimal and focused:
134+
- Fix only the bug, do not refactor surrounding code
135+
- Do not add features beyond what's needed
136+
- Preserve existing comments and code style
137+
138+
## Step 7: Validate the Fix
139+
140+
Run the reproducer test to confirm it passes:
141+
```bash
142+
./gradlew :module-name:jvmTest --tests "fully.qualified.TestClassName.methodName"
143+
```
144+
145+
Then run the full test suite for the affected module. Choose the scope based on where the changes are:
146+
147+
- **JVM-only changes** (test and fix both in `jvm/`):
148+
```bash
149+
./gradlew :module-name:jvmTest
150+
```
151+
- **Common/multiplatform changes** (test or fix in `common/`, or the bug affects multiple platforms):
152+
```bash
153+
./gradlew :module-name:allTests
154+
```
155+
156+
If any tests fail, investigate and fix. Do not skip or disable tests.
157+
158+
## Step 8: Format and Lint
159+
160+
```bash
161+
./gradlew :module-name:formatKotlin :module-name:lintKotlin
162+
```
163+
164+
Fix any lint issues before proceeding.
165+
166+
## Step 9: ABI Validation
167+
168+
If the fix changed any `public` or `protected` API (new methods, changed signatures, etc.):
169+
```bash
170+
./gradlew :module-name:checkLegacyAbi
171+
```
172+
173+
If it fails, update the ABI dumps:
174+
```bash
175+
./gradlew :module-name:updateLegacyAbi
176+
```
177+
178+
Stage the updated `.api` files along with the fix.
179+
180+
If no public API changed, skip this step.
181+
182+
## Step 10: Commit the Fix
183+
184+
```bash
185+
git add <changed-files>
186+
git commit -m "<ISSUE-ID> <Imperative description of the fix>
187+
188+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>"
189+
```
190+
191+
## Step 11: Push and Create PR
192+
193+
Push the branch and create a PR:
194+
195+
```bash
196+
git push -u origin claude/<issue-id>-<short-description>
197+
```
198+
199+
Create the PR targeting the base branch chosen in Step 3 (`main` or `release/3.x`):
200+
```bash
201+
gh pr create --title "<ISSUE-ID> <Short fix description>" --body "$(cat <<'EOF'
202+
## Summary
203+
- Fixes <link-to-issue>
204+
- <1-2 bullet points describing the root cause and fix>
205+
206+
Closes <issue-reference>
207+
208+
## Test plan
209+
- Added failing reproducer test that validates the fix
210+
- All existing tests in the module continue to pass
211+
212+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
213+
EOF
214+
)"
215+
```
216+
217+
The `Closes` line auto-closes the issue when the PR is merged **for GitHub issues only**:
218+
- For GitHub issues: `Closes #NUMBER`
219+
- For YouTrack issues: include `KTOR-XXXX` as a plain cross-reference (GitHub will not close YouTrack tickets automatically)
220+
221+
Report the PR URL to the user when done.
222+
223+
After the PR is created, for **YouTrack issues only**, update the issue state:
224+
225+
Call `mcp__youtrack__update_issue` with `customFields: {"State": "Ready for Review"}` to signal the fix is ready for code review.
226+
227+
If the YT MCP call fails, skip silently — the status update is not blocking.
228+
229+
## Step 12: Documentation Issue (if needed)
230+
231+
Assess whether the fix changes behavior that users rely on or that is described in the Ktor documentation. A documentation update is needed when:
232+
- A public API signature changed (new parameter, changed default, new overload)
233+
- Behavior that users observe changed (different error message, different default, different timing)
234+
- A workaround that users might have adopted is no longer necessary
235+
- A new feature or configuration option was added as part of the fix
236+
237+
If none of the above apply (e.g., an internal-only fix, a crash fix with no API change), skip this step.
238+
239+
When documentation is needed, create a GitHub issue in the `ktorio/ktor-documentation` repository:
240+
241+
````bash
242+
gh issue create --repo ktorio/ktor-documentation \
243+
--title "Document behavior change: <ISSUE-ID> <short description>" \
244+
--body "$(cat <<'EOF'
245+
## Context
246+
247+
PR: <link-to-the-PR-created-in-step-11>
248+
Issue: <link-to-the-original-issue>
249+
250+
## What changed
251+
252+
<1-3 sentences explaining what behavior changed and why>
253+
254+
## What should be documented
255+
256+
<Describe specifically what a technical writer should add or update in the docs.
257+
Include the affected API, module, and any relevant configuration options.>
258+
259+
## Suggested code snippet
260+
261+
```kotlin
262+
// Include a short usage example if relevant, showing the correct new usage
263+
```
264+
265+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
266+
EOF
267+
)"
268+
````
269+
270+
Report the documentation issue URL to the user alongside the PR URL.

0 commit comments

Comments
 (0)