Skip to content

Commit 4a9c585

Browse files
GiggleLiuclaude
andcommitted
Merge main (MinimumTardinessSequencing, pipeline refactor) and regenerate
Resolve reduction_graph.json conflicts, regenerate schemas, fix formatting after merge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 parents 354d140 + f81e52f commit 4a9c585

325 files changed

Lines changed: 11439 additions & 19061 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/final-review/SKILL.md

Lines changed: 127 additions & 78 deletions
Large diffs are not rendered by default.

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

Lines changed: 30 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -9,80 +9,50 @@ Resolve PR review comments, fix CI failures, and address codecov coverage gaps f
99

1010
## Step 1: Gather PR State
1111

12-
**IMPORTANT:** Do NOT use `gh api --jq` for extracting data — it uses a built-in jq that
13-
chokes on response bodies containing backslashes (common in Copilot code suggestions).
14-
Always pipe to `python3 -c` instead. (`gh pr view --jq` is fine — only `gh api --jq` is affected.)
12+
Step 1 should be a single report-generation step. Use the shared scripted helper to produce one skill-readable PR context packet. Do not rebuild this logic inline with `gh api | python3 -c` unless you are debugging the helper itself.
1513

1614
```bash
17-
# Get repo identifiers
18-
REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner) # e.g., "owner/repo"
15+
REPORT=$(python3 scripts/pipeline_pr.py context --current --format text)
16+
printf '%s\n' "$REPORT"
17+
```
1918

20-
# Get PR number
21-
PR=$(gh pr view --json number --jq .number)
19+
The report should already include:
20+
- repo, PR number, title, URL, head SHA
21+
- comment counts
22+
- CI summary
23+
- Codecov summary
24+
- linked issue context
2225

23-
# Get PR head SHA (on remote)
24-
HEAD_SHA=$(gh api repos/$REPO/pulls/$PR | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")
25-
```
26+
Use the values printed in that report for the rest of this skill. If you absolutely need raw structured data for a corner case, rerun the same command with `--format json`, but do not rebuild Step 1 manually.
2627

2728
### 1a. Fetch Review Comments
2829

2930
**Check ALL four sources.** User inline comments are the most commonly missed — do not skip any.
3031

31-
```bash
32-
# 1. Inline review comments on code lines (from ALL reviewers: users AND Copilot)
33-
gh api repos/$REPO/pulls/$PR/comments | python3 -c "
34-
import sys,json
35-
comments = json.load(sys.stdin)
36-
print(f'=== Inline comments: {len(comments)} ===')
37-
for c in comments:
38-
line = c.get('line') or c.get('original_line') or '?'
39-
print(f'[{c[\"user\"][\"login\"]}] {c[\"path\"]}:{line} — {c[\"body\"][:200]}')
40-
"
41-
42-
# 2. Review-level comments (top-level review body from formal reviews)
43-
gh api repos/$REPO/pulls/$PR/reviews | python3 -c "
44-
import sys,json
45-
reviews = json.load(sys.stdin)
46-
print(f'=== Reviews: {len(reviews)} ===')
47-
for r in reviews:
48-
if r.get('body'):
49-
print(f'[{r[\"user\"][\"login\"]}] {r[\"state\"]}: {r[\"body\"][:200]}')
50-
"
32+
Start from the report's `Comment Summary`. It should tell you whether any source is non-empty before you inspect raw threads.
5133

52-
# 3. Issue-level comments (general discussion)
53-
gh api repos/$REPO/issues/$PR/comments | python3 -c "
54-
import sys,json
55-
comments = [c for c in json.load(sys.stdin) if 'codecov' not in c['user']['login']]
56-
print(f'=== Issue comments: {len(comments)} ===')
57-
for c in comments:
58-
print(f'[{c[\"user\"][\"login\"]}] {c[\"body\"][:200]}')
59-
"
60-
```
61-
62-
**Verify counts:** If any source returns 0, confirm it's genuinely empty — don't assume no feedback exists.
34+
If you need the raw comment arrays for detailed triage, rerun `python3 scripts/pipeline_pr.py context --current --format json` and inspect:
35+
- `comments["inline_comments"]`
36+
- `comments["reviews"]`
37+
- `comments["human_issue_comments"]`
38+
- `comments["human_linked_issue_comments"]`
39+
- `comments["codecov_comments"]`
6340

6441
### 1b. Check CI Status
6542

66-
```bash
67-
# All check runs on the PR head
68-
gh api repos/$REPO/commits/$HEAD_SHA/check-runs | python3 -c "
69-
import sys,json
70-
for cr in json.load(sys.stdin)['check_runs']:
71-
print(f'{cr[\"name\"]}: {cr.get(\"conclusion\") or cr[\"status\"]}')
72-
"
73-
```
43+
Read the report's `CI Summary`. The structured JSON fallback includes:
44+
- `state``pending`, `failure`, or `success`
45+
- `runs` — normalized check-run details
46+
- `pending` / `failing` / `succeeding` counts
7447

7548
### 1c. Check Codecov Report
7649

77-
```bash
78-
# Codecov bot comment with coverage diff
79-
gh api repos/$REPO/issues/$PR/comments | python3 -c "
80-
import sys,json
81-
for c in json.load(sys.stdin):
82-
if c['user']['login'] == 'codecov[bot]':
83-
print(c['body'])
84-
"
85-
```
50+
Read the report's `Codecov` section. The structured JSON fallback includes:
51+
- `found` — whether a Codecov comment is present
52+
- `patch_coverage`
53+
- `project_coverage`
54+
- `filepaths` — deduplicated paths referenced by Codecov links
55+
- `body` — the raw latest Codecov comment body
8656

8757
## Step 2: Triage and Prioritize
8858

@@ -130,23 +100,10 @@ Copilot suggestions with `suggestion` blocks contain exact code. Evaluate each:
130100

131101
### 5a. Identify Uncovered Lines
132102

133-
From the codecov bot comment (fetched in Step 1c), extract:
103+
From the `CODECOV` JSON (fetched in Step 1c), extract:
134104
- Files with missing coverage
135105
- Patch coverage percentage
136-
- Specific uncovered lines (linked in the report)
137-
138-
For detailed line-by-line coverage, use the Codecov API:
139-
140-
```bash
141-
# Get file-level coverage for the PR
142-
gh api repos/$REPO/issues/$PR/comments | python3 -c "
143-
import sys,json,re
144-
for c in json.load(sys.stdin):
145-
if c['user']['login'] == 'codecov[bot]':
146-
for m in re.findall(r'filepath=([^&\"]+)', c['body']):
147-
print(m)
148-
"
149-
```
106+
- Specific uncovered files referenced in `filepaths`
150107

151108
Then read the source files and identify which new/changed lines lack test coverage.
152109

.claude/skills/issue-to-pr/SKILL.md

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,55 +18,59 @@ For Codex, open this `SKILL.md` directly and treat the slash-command forms above
1818

1919
```
2020
Receive issue number [+ --execute flag]
21-
-> Fetch issue with gh
22-
-> Verify Good label (from check-issue)
23-
-> If not Good: STOP
24-
-> If Good: research references, write plan, create PR
21+
-> Fetch structured issue preflight report
22+
-> Verify Good label and rule-model guards
23+
-> If guards fail: STOP
24+
-> If guards pass: research references, write plan, create or resume PR
2525
-> If --execute: run plan via subagent-driven-development, then review-implementation
2626
```
2727

2828
## Steps
2929

3030
### 1. Parse Input
3131

32-
Extract issue number and flags from arguments:
32+
Extract issue number, repo, and flags from arguments:
3333
- `123` -> issue #123, plan only
3434
- `123 --execute` -> issue #123, plan + execute
3535
- `https://github.com/owner/repo/issues/123` -> issue #123
3636
- `owner/repo#123` -> issue #123 in owner/repo
3737

38-
### 2. Fetch Issue
38+
Normalize to:
39+
- `ISSUE=<number>`
40+
- `REPO=<owner/repo>` (default `CodingThrust/problem-reductions`)
41+
- `EXECUTE=true|false`
42+
43+
### 2. Fetch Issue + Preflight Guards
3944

4045
```bash
41-
gh issue view <number> --json title,body,labels,assignees,comments
46+
ISSUE_JSON=$(python3 scripts/pipeline_checks.py issue-context \
47+
--repo "$REPO" \
48+
--issue "$ISSUE" \
49+
--format json)
4250
```
4351

44-
Present issue summary to user. **Also review all comments** — contributors and maintainers may have posted clarifications, corrections, additional context, or design decisions that refine or override parts of the original issue body. Incorporate relevant comment content when writing the plan.
52+
Treat `ISSUE_JSON` as the source of truth for the deterministic preflight data:
53+
- `title`, `body`, `labels`, and `comments` provide the issue summary and comment thread
54+
- `kind`, `source_problem`, and `target_problem` provide parsed issue metadata
55+
- `checks.good_label`, `checks.source_model`, and `checks.target_model` provide guard outcomes
56+
- `existing_prs`, `resume_pr`, and `action` tell you whether to resume an open PR instead of creating a new one
57+
58+
Present the issue summary to the user. **Also review all comments** — contributors and maintainers may have posted clarifications, corrections, additional context, or design decisions that refine or override parts of the original issue body. Incorporate relevant comment content when writing the plan.
4559

4660
### 3. Verify Issue Has Passed check-issue
4761

4862
The issue must have already passed the `check-issue` quality gate (Stage 1 validation). Do NOT re-validate the issue here.
4963

50-
**Gate condition:** The issue must have the `Good` label (added by `check-issue` when all checks pass).
51-
52-
```bash
53-
LABELS=$(gh issue view <number> --json labels --jq '[.labels[].name] | join(",")')
54-
```
55-
56-
- If `Good` is NOT in the labels → **STOP**: "Issue #N has not passed check-issue. Please run `/check-issue <N>` first."
57-
- If `Good` is present → continue to step 4.
64+
Use `ISSUE_JSON.checks.good_label`:
65+
- If it is `fail`**STOP**: "Issue #N has not passed check-issue. Please run `/check-issue <N>` first."
66+
- If it is `pass` → continue.
5867

5968
### 3.5. Model-Existence Guard (for `[Rule]` issues only)
6069

61-
For `[Rule]` issues, parse the source and target problem names from the title (e.g., `[Rule] BinPacking to ILP` → source=BinPacking, target=ILP). Verify that **both** models already exist in the codebase on `main`:
70+
For `[Rule]` issues, `ISSUE_JSON` already includes `source_problem`, `target_problem`, and the deterministic model-existence checks.
6271

63-
```bash
64-
grep -r "struct SourceName" src/models/
65-
grep -r "struct TargetName" src/models/
66-
```
67-
68-
- If **both** models exist → continue to step 4.
69-
- If either model is missing → **STOP**. Comment on the issue: "Blocked: model `<name>` does not exist in main yet. Please implement it first (or file a `[Model]` issue)."
72+
- If both `checks.source_model` and `checks.target_model` are `pass` → continue to step 4.
73+
- If either is `fail`**STOP**. Comment on the issue: "Blocked: model `<name>` does not exist in main yet. Please implement it first (or file a `[Model]` issue)."
7074

7175
**One item per PR:** Do NOT implement a missing model as part of a `[Rule]` PR. Each PR should contain exactly one model or one rule, never both. This avoids bloated PRs and repeated implementation when the model is needed by multiple rules.
7276

@@ -106,26 +110,23 @@ Include the concrete details from the issue (problem definition, reduction algor
106110

107111
### 6. Create PR (or Resume Existing)
108112

109-
**Check for existing PR first:**
110-
```bash
111-
EXISTING_PR=$(gh pr list --search "Fixes #<number>" --state open --json number,headRefName --jq '.[0].number // empty')
112-
```
113+
Use the `ISSUE_JSON.action` and `ISSUE_JSON.resume_pr` fields from Step 2.
113114

114-
**If a PR already exists** (`EXISTING_PR` is non-empty):
115-
- Switch to its branch: `git checkout <headRefName>`
116-
- Capture `PR=$EXISTING_PR`
115+
**If an open PR already exists** (`action == "resume-pr"`):
116+
- Switch to its branch: `git checkout <resume_pr.head_ref_name>`
117+
- Capture `PR=<resume_pr.number>`
117118
- Skip plan creation — jump directly to Step 7 (execute)
118119

119-
**If no existing PR** — create one with only the plan file:
120-
121-
**Pre-flight checks** (before creating the branch):
122-
1. Verify clean working tree: `git status --porcelain` must be empty. If not, STOP and ask user to stash or commit.
123-
2. Check if branch already exists: `git rev-parse --verify issue-<number>-<slug> 2>/dev/null`. If it exists, switch to it with `git checkout` (no `-b`) instead of creating a new one.
120+
**If no open PR exists** (`action == "create-pr"`) — create one with only the plan file:
124121

125122
```bash
126-
# Create branch (from main)
127-
git checkout main
128-
git rev-parse --verify issue-<number>-<slug> 2>/dev/null && git checkout issue-<number>-<slug> || git checkout -b issue-<number>-<slug>
123+
# Prepare or reuse the issue branch (this enforces a clean working tree)
124+
BRANCH_JSON=$(python3 scripts/pipeline_worktree.py prepare-issue-branch \
125+
--issue <number> \
126+
--slug <slug> \
127+
--base main \
128+
--format json)
129+
BRANCH=$(printf '%s\n' "$BRANCH_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['branch'])")
129130

130131
# Stage the plan file
131132
git add docs/plans/<plan-file>.md
@@ -134,17 +135,27 @@ git add docs/plans/<plan-file>.md
134135
git commit -m "Add plan for #<number>: <title>"
135136

136137
# Push
137-
git push -u origin issue-<number>-<slug>
138+
git push -u origin "$BRANCH"
138139

139-
# Create PR
140-
gh pr create --title "Fix #<number>: <title>" --body "
140+
# Create PR body
141+
PR_BODY_FILE=$(mktemp)
142+
cat > "$PR_BODY_FILE" <<'EOF'
141143
## Summary
142144
<Brief description>
143145
144-
Fixes #<number>"
146+
Fixes #<number>
147+
EOF
145148

146-
# Capture PR number
147-
PR=$(gh pr view --json number --jq .number)
149+
# Create PR and capture the created PR number
150+
PR_JSON=$(python3 scripts/pipeline_pr.py create \
151+
--repo "$REPO" \
152+
--title "Fix #<number>: <title>" \
153+
--body-file "$PR_BODY_FILE" \
154+
--base main \
155+
--head "$BRANCH" \
156+
--format json)
157+
PR=$(printf '%s\n' "$PR_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['pr_number'])")
158+
rm -f "$PR_BODY_FILE"
148159
```
149160

150161
### 7. Execute Plan (only with `--execute`)
@@ -194,7 +205,8 @@ Post an implementation summary comment on the PR **before** pushing. This commen
194205
- Note any open questions or trade-offs made
195206

196207
```bash
197-
gh pr comment $PR --body "$(cat <<'EOF'
208+
COMMENT_FILE=$(mktemp)
209+
cat > "$COMMENT_FILE" <<'EOF'
198210
## Implementation Summary
199211
200212
### Changes
@@ -206,7 +218,8 @@ gh pr comment $PR --body "$(cat <<'EOF'
206218
### Open Questions
207219
- [any trade-offs or items needing review — or "None"]
208220
EOF
209-
)"
221+
python3 scripts/pipeline_pr.py comment --repo "$REPO" --pr "$PR" --body-file "$COMMENT_FILE"
222+
rm -f "$COMMENT_FILE"
210223

211224
git push
212225
make copilot-review
@@ -261,7 +274,7 @@ Run /review-pipeline to process Copilot comments, fix CI, and run agentic tests.
261274
| Generic plan | Use specifics from the issue, mapped to add-model/add-rule steps |
262275
| Skipping CLI registration in plan | add-model still requires alias/create/example-db planning, but not manual CLI dispatch-table edits |
263276
| Not verifying facts from issue | Use WebSearch/WebFetch to cross-check claims |
264-
| Branch already exists on retry | Check with `git rev-parse --verify` before `git checkout -b` |
265-
| Dirty working tree | Verify `git status --porcelain` is empty before branching |
277+
| Branch already exists on retry | Use `pipeline_worktree.py prepare-issue-branch` — it will reuse the existing branch instead of failing on `git checkout -b` |
278+
| Dirty working tree | Use `pipeline_worktree.py prepare-issue-branch` — it stops before branching if the worktree is dirty |
266279
| Bundling model + rule in one PR | Each PR must contain exactly one model or one rule — STOP and block if model is missing (Step 3.5) |
267280
| Plan files left in PR | Delete plan files before final push (Step 7c) |

0 commit comments

Comments
 (0)