Skip to content

Commit d4b9b01

Browse files
committed
Improve PPL bugfix command: permission modes, parallel dispatch, file reorg
- Add --safe/--yolo permission mode flags (default: bypassPermissions) - Support multiple issue/PR references for parallel processing - Move harness files to .claude/harness/ directory - Add ppl-bugfix-followup.md for post-PR follow-up workflow - Add .claude/settings.json with pre-approved tool permissions - Add CLAUDE_GUIDE.md documenting all slash commands Signed-off-by: Heng Qian <qianheng@amazon.com>
1 parent a5fd530 commit d4b9b01

7 files changed

Lines changed: 212 additions & 109 deletions

File tree

.claude/commands/ppl-bugfix.md

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,44 @@ allowed-tools: Agent, Read, Bash(gh:*), Bash(git:*)
33
description: Run the PPL bugfix harness for a GitHub issue or follow up on an existing PR
44
---
55

6-
Fix a PPL bug or follow up on an existing PR using the harness in `ppl-bugfix-harness.md`.
6+
Fix a PPL bug or follow up on an existing PR using the harness in `.claude/harness/ppl-bugfix-harness.md`.
77

88
## Input
99

10-
- `/ppl-bugfix #1234` or `/ppl-bugfix 1234` — issue number
11-
- `/ppl-bugfix PR#5678` or `/ppl-bugfix pr 5678` — PR number
10+
Accepts one or more issue/PR references. Multiple references are processed in parallel (each gets its own subagent + worktree).
11+
12+
- `/ppl-bugfix #1234` — single issue
13+
- `/ppl-bugfix PR#5678` — single PR
14+
- `/ppl-bugfix #1234 #5678 PR#9012` — multiple in parallel
1215
- `/ppl-bugfix https://github.com/opensearch-project/sql/issues/1234` — URL
1316

17+
Optional mode flag (append to any of the above):
18+
- `--safe``acceptEdits` mode. Auto-approve file edits only, Bash commands require manual approval. (Most conservative)
19+
- `--yolo``bypassPermissions` mode. Fully trusted, no prompts. Subagent runs in an isolated worktree so this is safe. (Default)
20+
21+
Examples:
22+
- `/ppl-bugfix #1234` — single issue, defaults to yolo
23+
- `/ppl-bugfix #1234 #5678 --yolo` — two issues in parallel
24+
- `/ppl-bugfix PR#5293 PR#5300` — two PRs in parallel
25+
- `/ppl-bugfix #1234 PR#5678 --safe` — mix of issue and PR
26+
1427
If no argument given, ask for an issue or PR number.
1528

16-
## Step 1: Resolve Issue ↔ PR
29+
## Step 0: Resolve Permission Mode
30+
31+
Parse the mode flag from the input arguments:
32+
33+
| Flag | Mode |
34+
|------|------|
35+
| `--safe` | `acceptEdits` |
36+
| `--yolo` | `bypassPermissions` |
37+
| _(no flag)_ | `bypassPermissions` (default) |
38+
39+
Use the resolved mode as the `mode` parameter when dispatching the subagent in Step 2A/2B.
40+
41+
## Step 1: Resolve Each Reference
42+
43+
For each issue/PR reference in the input, resolve its state. Run these lookups in parallel when there are multiple references.
1744

1845
```bash
1946
# Issue → PR
@@ -29,64 +56,44 @@ gh pr view <pr_number> --json body | jq -r '.body' | grep -oP 'Resolves #\K[0-9]
2956
| Issue exists, open PR found | **Follow-up** (Step 2B) |
3057
| PR provided directly | **Follow-up** (Step 2B) |
3158

32-
## Step 2A: Initial Fix
59+
## Step 2: Dispatch Subagents
3360

34-
1. `gh issue view <issue_number>`
35-
2. `Read ppl-bugfix-harness.md`
36-
3. Dispatch subagent:
61+
Dispatch one subagent per reference. When there are multiple references, dispatch all subagents in a single message (parallel execution).
62+
63+
### 2A: Initial Fix
3764

3865
```
3966
Agent(
40-
mode: "acceptEdits",
67+
mode: "<resolved_mode>",
4168
isolation: "worktree",
4269
name: "bugfix-<issue_number>",
4370
description: "PPL bugfix #<issue_number>",
44-
prompt: "<FULL harness content> + <issue details>
71+
prompt: "Read .claude/harness/ppl-bugfix-harness.md and follow it to fix GitHub issue #<issue_number>.
4572
Follow Phase 0 through Phase 3 in order.
4673
Phase 0.3 defines TDD execution flow. Do NOT skip any phase.
4774
Post the Decision Log (Phase 3.4) before completing."
4875
)
4976
```
5077

51-
The `isolation: "worktree"` creates a temporary git worktree branched from the current HEAD. The agent works in a clean, isolated copy of the repo — no interference with the user's working directory. If the agent makes changes, the worktree path and branch are returned in the result.
52-
53-
4. Report back: classification, fix summary, PR URL, **worktree branch name**, items needing human attention.
54-
55-
## Step 2B: Follow-up
56-
57-
1. Load PR state:
58-
```bash
59-
gh pr view <pr_number> --json title,body,state,reviews,comments,statusCheckRollup,mergeable
60-
gh pr checks <pr_number>
61-
```
62-
63-
2. Categorize:
64-
65-
| Signal | Type |
66-
|--------|------|
67-
| `statusCheckRollup` has failures | CI failure |
68-
| `reviews` has CHANGES_REQUESTED | Review feedback |
69-
| `mergeable` is CONFLICTING | Merge conflict |
70-
| All pass + approved | Ready — run `gh pr ready` |
71-
72-
3. `Read ppl-bugfix-harness.md`
73-
4. Dispatch follow-up subagent:
78+
### 2B: Follow-up
7479

7580
```
7681
Agent(
77-
mode: "acceptEdits",
82+
mode: "<resolved_mode>",
7883
isolation: "worktree",
79-
name: "bugfix-<issue_number>-followup",
84+
name: "bugfix-<issue_number>",
8085
description: "PPL bugfix #<issue_number> followup",
81-
prompt: "<Phase 3.5 content from harness>
86+
prompt: "Read .claude/harness/ppl-bugfix-followup.md and follow it.
8287
PR: <pr_number> (<pr_url>), Issue: #<issue_number>
83-
Follow-up type: <CI failure / review feedback / merge conflict>
84-
Read the Decision Log PR comment FIRST before making any changes.
85-
Checkout the PR branch before starting: git checkout <pr_branch>"
88+
Follow-up type: <CI failure / review feedback / merge conflict>"
8689
)
8790
```
8891

89-
5. Report back: what was addressed, current PR state, whether another round is needed.
92+
## Step 3: Report Back
93+
94+
After all subagents complete, report a summary for each:
95+
- Classification, fix summary, PR URL, worktree path and branch, items needing human attention (2A)
96+
- What was addressed, current PR state, whether another round is needed (2B)
9097

9198
## Subagent Lifecycle
9299

@@ -106,6 +113,8 @@ Context is preserved across agents via:
106113

107114
## Rules
108115

109-
- Always inline harness content in the subagent promptsubagents cannot read skill files
116+
- Subagent reads `.claude/harness/ppl-bugfix-harness.md` and fetches issue/PR details itselfdo NOT inline content into the prompt
110117
- If bug is not reproducible (Phase 0.1), stop and report — do not proceed
111118
- Issue ↔ PR auto-resolution means the user never needs to track PR numbers manually
119+
- **Do NOT use `mode: "auto"` for subagents**`auto` mode does not work for subagents; Bash commands still require manual approval. Only `bypassPermissions` reliably skips permission checks.
120+
- **Always dispatch subagent** — even for trivial follow-ups (remove co-author, force push). Do NOT run commands directly in the main session; subagents with `bypassPermissions` skip permission prompts, the main session does not.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# PPL Bugfix Follow-up
2+
3+
---
4+
5+
## Reconstruct Context
6+
7+
The follow-up agent runs in a fresh worktree. First checkout the PR branch, then load state:
8+
9+
```bash
10+
# Checkout the PR branch in this worktree
11+
gh pr checkout <pr_number>
12+
13+
# Load PR state and Decision Log
14+
gh pr view <pr_number> --json title,body,state,reviews,comments,statusCheckRollup,mergeable
15+
gh pr checks <pr_number>
16+
# Read the Decision Log comment FIRST — contains rejected alternatives and pitfalls
17+
gh api repos/<owner>/<repo>/pulls/<pr_number>/comments
18+
```
19+
20+
## Handle Review Feedback
21+
22+
For each comment, **cross-check against the Decision Log first**:
23+
24+
| Type | Action |
25+
|------|--------|
26+
| Code change | If already rejected in Decision Log, reply with reasoning. Otherwise make the change, new commit, push |
27+
| Question | Reply with explanation — Decision Log often has the answer |
28+
| Nit | Fix if trivial |
29+
| Disagreement | Reply with Decision Log reasoning; if reviewer insists, escalate to user |
30+
31+
```bash
32+
git add <files> && git commit -s -m "Address review feedback: <description>"
33+
git push <your_fork_remote> <branch_name>
34+
```
35+
36+
## Clean Up Commit History
37+
38+
When you need to amend a commit (e.g. remove Co-Authored-By, reword message) and the branch has a merge commit on top, don't try `git reset --soft origin/main` — it will include unrelated changes if main has moved. Instead cherry-pick the fix onto latest main:
39+
40+
```bash
41+
git checkout -B clean-branch origin/main
42+
git cherry-pick <fix_commit_sha>
43+
git commit --amend -s -m "<updated message>"
44+
git push <your_fork_remote> clean-branch:<pr_branch> --force
45+
```
46+
47+
## Handle CI Failures
48+
49+
```bash
50+
gh pr checks <pr_number> # Identify failures
51+
gh run view <run_id> --log-failed # Read logs
52+
# Test failure → fix locally, push new commit
53+
# Spotless → ./gradlew spotlessApply, push
54+
# Flaky → gh run rerun <run_id> --failed
55+
```
56+
57+
## Handle Merge Conflicts
58+
59+
```bash
60+
git fetch origin && git merge origin/main # Resolve conflicts
61+
./gradlew spotlessApply && ./gradlew test && ./gradlew :integ-test:integTest # Re-verify
62+
git commit -s -m "Resolve merge conflicts with main"
63+
git push <your_fork_remote> <branch_name>
64+
```
65+
66+
## Mark Ready
67+
68+
```bash
69+
gh pr ready <pr_number>
70+
```
Lines changed: 10 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
# PPL Bugfix Harness
22

3-
> Systematic bugfix workflow distilled from 15+ historical commits. Invoke via `/ppl-bugfix #<issue_number>`.
4-
53
---
64

75
## Phase 0: Triage & Classification
86

7+
### 0.0 Load Issue Context
8+
9+
```bash
10+
gh issue view <issue_number> --repo opensearch-project/sql
11+
```
12+
13+
Read the issue title, description, and any reproduction steps before proceeding.
14+
915
### 0.1 Reproduce the Bug
1016

1117
```bash
@@ -221,10 +227,8 @@ teardown:
221227
222228
### 3.2 Commit & Push
223229
224-
The subagent runs in an isolated **git worktree** branched from HEAD. All changes are on a dedicated branch that does not affect the user's working directory.
225-
226230
```bash
227-
# Commit with DCO sign-off
231+
# Commit with DCO sign-off — do NOT add Co-Authored-By lines
228232
git add <changed_files>
229233
git commit -s -m "[BugFix] Fix <description> (#<issue_number>)"
230234
@@ -277,68 +281,6 @@ EOF
277281
278282
---
279283
280-
## Phase 3.5: Post-PR Follow-up
281-
282-
Runs as a **separate subagent** invocation — the original agent has completed. Invoke via `/ppl-bugfix #<issue>` or `/ppl-bugfix PR#<pr>` (auto-detects follow-up mode when a PR exists).
283-
284-
### 3.5.1 Reconstruct Context
285-
286-
The follow-up agent runs in a fresh worktree. First checkout the PR branch, then load state:
287-
288-
```bash
289-
# Checkout the PR branch in this worktree
290-
gh pr checkout <pr_number>
291-
292-
# Load PR state and Decision Log
293-
gh pr view <pr_number> --json title,body,state,reviews,comments,statusCheckRollup,mergeable
294-
gh pr checks <pr_number>
295-
# Read the Decision Log comment FIRST — contains rejected alternatives and pitfalls
296-
gh api repos/<owner>/<repo>/pulls/<pr_number>/comments
297-
```
298-
299-
### 3.5.2 Handle Review Feedback
300-
301-
For each comment, **cross-check against the Decision Log first**:
302-
303-
| Type | Action |
304-
|------|--------|
305-
| Code change | If already rejected in Decision Log, reply with reasoning. Otherwise make the change, new commit, push |
306-
| Question | Reply with explanation — Decision Log often has the answer |
307-
| Nit | Fix if trivial |
308-
| Disagreement | Reply with Decision Log reasoning; if reviewer insists, escalate to user |
309-
310-
```bash
311-
git add <files> && git commit -s -m "Address review feedback: <description>"
312-
git push <your_fork_remote> <branch_name>
313-
```
314-
315-
### 3.5.3 Handle CI Failures
316-
317-
```bash
318-
gh pr checks <pr_number> # Identify failures
319-
gh run view <run_id> --log-failed # Read logs
320-
# Test failure → fix locally, push new commit
321-
# Spotless → ./gradlew spotlessApply, push
322-
# Flaky → gh run rerun <run_id> --failed
323-
```
324-
325-
### 3.5.4 Handle Merge Conflicts
326-
327-
```bash
328-
git fetch origin && git merge origin/main # Resolve conflicts
329-
./gradlew spotlessApply && ./gradlew test && ./gradlew :integ-test:integTest # Re-verify
330-
git commit -s -m "Resolve merge conflicts with main"
331-
git push <your_fork_remote> <branch_name>
332-
```
333-
334-
### 3.5.5 Mark Ready
335-
336-
```bash
337-
gh pr ready <pr_number>
338-
```
339-
340-
---
341-
342284
## Phase 4: Retrospective
343285
344286
After each bugfix, check if the harness itself needs updating:
@@ -381,3 +323,4 @@ Regex/function extraction offset → Path B: ordinal vs named r
381323
| `734394d` | Grammar rule typo | Grammar ||
382324
| `246ed0d` | Float precision flaky test | Test Infra ||
383325
| `d56b8fa` | Wildcard index type conflict | Value Parsing | 3 UT + 1 IT + 1 YAML |
326+
| `5a78b78` | Boolean coercion from numeric in wildcard queries | Value Parsing | 3 UT + 1 IT + 1 YAML |

.claude/settings.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(./gradlew *)",
5+
"Bash(gh issue:*)",
6+
"Bash(gh pr:*)",
7+
"Bash(gh api:*)",
8+
"Bash(gh search:*)",
9+
"Bash(gh run:*)",
10+
"Bash(git add:*)",
11+
"Bash(git commit:*)",
12+
"Bash(git stash:*)",
13+
"Bash(git show:*)",
14+
"Bash(git diff:*)",
15+
"Bash(git status:*)",
16+
"Bash(git log:*)",
17+
"Bash(git branch:*)",
18+
"Bash(git remote:*)",
19+
"Bash(git fetch:*)",
20+
"Bash(git checkout:*)",
21+
"Bash(git push:*)",
22+
"Bash(git cherry-pick:*)",
23+
"Bash(git reset:*)"
24+
]
25+
}
26+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ http-client.env.json
5656
.claude/*
5757
!.claude/settings.json
5858
!.claude/commands/
59+
!.claude/harness/
5960
.claude/settings.local.json
6061
.clinerules
6162
memory-bank

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ plugin (OpenSearch plugin entry point, Guice DI wiring)
125125

126126
## Fixing PPL Bugs
127127

128-
Use the `/ppl-bugfix #<issue_number>` slash command to fix PPL bugs. It dispatches a subagent with scoped permissions that follows all phases in `ppl-bugfix-harness.md` — from Phase 0 (Triage & Classification) through Phase 4 (Retrospective & Improvement). The full harness content is inlined into the subagent prompt to guarantee compliance. If a user asks to fix a PPL bug without using the slash command, remind them to use `/ppl-bugfix` or invoke it on their behalf.
128+
Use the `/ppl-bugfix #<issue_number>` slash command to fix PPL bugs. It dispatches a subagent in an isolated worktree that reads `.claude/harness/ppl-bugfix-harness.md` and follows all phases — from Phase 0 (Triage & Classification) through Phase 4 (Retrospective & Improvement). If a user asks to fix a PPL bug without using the slash command, remind them to use `/ppl-bugfix` or invoke it on their behalf.
129129

130130
## Adding New PPL Commands
131131

0 commit comments

Comments
 (0)