Skip to content

Commit 112f9a6

Browse files
feat(workflows): add unified plot-prepare workflow
- Merge bot-validate-request + gen-create-spec into plot-prepare.yml - Disable old workflows (renamed to .yml.disabled) - Add update request analysis (validates if update reason is sensible) - Update issue templates for clearer workflow
1 parent 42fbf9e commit 112f9a6

5 files changed

Lines changed: 314 additions & 14 deletions

File tree

.github/ISSUE_TEMPLATE/plot-request.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Plot Request
22
description: Propose a new plot type for pyplots
3-
title: "Plot: "
3+
title: ""
44
labels: ["plot-request"]
55
body:
66
- type: markdown
@@ -11,9 +11,9 @@ body:
1111
Describe the plot you'd like to see. Our AI will:
1212
1. Check for similar existing plots
1313
2. Assign a descriptive spec ID (e.g., `scatter-regression-linear`)
14-
3. Generate implementations once approved
14+
3. Create the specification for review
1515
16-
**No need to specify an ID** - just describe what you want!
16+
**After submission:** A maintainer will review and add the `approved` label to start code generation.
1717
1818
- type: textarea
1919
id: description

.github/ISSUE_TEMPLATE/plot-update.yml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,37 @@
11
name: Plot Update
22
description: Request updates or regeneration of an existing plot
3-
title: "[spec-id] [update] "
3+
title: "[SPEC-ID] [update] "
44
labels: ["plot-request", "update"]
55
body:
66
- type: markdown
77
attributes:
88
value: |
99
## Plot Update Request
1010
11-
Use this form to update or regenerate an existing plot.
11+
Use this to update or regenerate an existing plot.
1212
13-
**Title Format:**
14-
- `[scatter-basic] [update] Regenerate` → Regenerate all 9 libraries
15-
- `[scatter-basic] [update:seaborn] Fix colors` → Regenerate only seaborn
13+
**Important:** Replace `SPEC-ID` in the title with the actual spec ID!
1614
17-
Replace `[spec-id]` in the title with the actual spec ID (e.g., `scatter-basic`).
15+
**Title Examples:**
16+
- `[scatter-basic] [update] Regenerate all` - All 9 libraries
17+
- `[scatter-basic] [update:seaborn] Fix colors` - Only seaborn
1818
19-
After submitting, a maintainer will add the `approved` label to trigger regeneration.
19+
**After submission:** A maintainer will review and add the `approved` label to start regeneration.
20+
21+
- type: input
22+
id: spec_id
23+
attributes:
24+
label: Spec ID
25+
description: "The spec ID to update (e.g., scatter-basic). Must match the title!"
26+
placeholder: "scatter-basic"
27+
validations:
28+
required: true
2029

2130
- type: dropdown
2231
id: target_library
2332
attributes:
24-
label: Target Library (optional)
25-
description: Update only a specific library, or leave empty for all. If you select a specific library, change [update] to [update:library] in the title.
33+
label: Target Library
34+
description: "Update specific library or all? If specific, change [update] to [update:library] in title."
2635
options:
2736
- All libraries
2837
- matplotlib
@@ -35,7 +44,7 @@ body:
3544
- highcharts
3645
- letsplot
3746
validations:
38-
required: false
47+
required: true
3948

4049
- type: dropdown
4150
id: update_type
@@ -54,7 +63,7 @@ body:
5463
id: changes
5564
attributes:
5665
label: Requested Changes
57-
description: Describe the changes to the spec or implementation (Claude will update the spec first if needed)
66+
description: Describe the changes to the spec or implementation
5867
placeholder: |
5968
- Add grid lines for better readability
6069
- Change default color scheme to colorblind-friendly
File renamed without changes.
File renamed without changes.

.github/workflows/plot-prepare.yml

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
name: "Plot: Prepare"
2+
run-name: "Prepare: ${{ github.event.issue.title }}"
3+
4+
# Unified workflow for NEW and UPDATE requests
5+
# Phase 1: Validate, assign spec-id, create branch, generate spec
6+
# STOPS after spec creation - waits for `approved` label before code generation
7+
#
8+
# Triggers:
9+
# - plot-request label added → NEW request flow
10+
# - plot-request + update labels → UPDATE request flow
11+
12+
on:
13+
issues:
14+
types: [labeled]
15+
16+
concurrency:
17+
group: plot-prepare-${{ github.event.issue.number }}
18+
cancel-in-progress: false
19+
20+
jobs:
21+
prepare:
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: write
25+
issues: write
26+
id-token: write
27+
28+
outputs:
29+
spec_id: ${{ steps.process.outputs.spec_id }}
30+
feature_branch: ${{ steps.process.outputs.feature_branch }}
31+
is_update: ${{ steps.check.outputs.is_update }}
32+
33+
steps:
34+
# ========================================================================
35+
# Step 1: Check conditions
36+
# ========================================================================
37+
- name: Check conditions
38+
id: check
39+
env:
40+
ISSUE_TITLE: ${{ github.event.issue.title }}
41+
LABEL_NAME: ${{ github.event.label.name }}
42+
run: |
43+
echo "=== Debug Info ==="
44+
echo "Event: ${{ github.event_name }}"
45+
echo "Label added: $LABEL_NAME"
46+
echo "Issue labels: ${{ join(github.event.issue.labels.*.name, ', ') }}"
47+
echo "Issue title: $ISSUE_TITLE"
48+
echo "=================="
49+
50+
# Only trigger when plot-request label is added
51+
if [[ "$LABEL_NAME" != "plot-request" ]]; then
52+
echo "::notice::Skipping: Not the 'plot-request' label"
53+
echo "should_run=false" >> $GITHUB_OUTPUT
54+
exit 0
55+
fi
56+
57+
# Check if this is an update request
58+
HAS_UPDATE="${{ contains(github.event.issue.labels.*.name, 'update') }}"
59+
if [[ "$HAS_UPDATE" == "true" ]]; then
60+
echo "is_update=true" >> $GITHUB_OUTPUT
61+
echo "::notice::This is an UPDATE request"
62+
else
63+
echo "is_update=false" >> $GITHUB_OUTPUT
64+
echo "::notice::This is a NEW request"
65+
fi
66+
67+
# Skip if already has spec-id in title (already processed)
68+
if [[ "$ISSUE_TITLE" =~ ^\[[a-z0-9-]+\] ]]; then
69+
EXISTING_ID=$(echo "$ISSUE_TITLE" | grep -oP '^\[\K[a-z0-9-]+(?=\])' || echo "")
70+
# For updates, having spec-id is expected - continue
71+
if [[ "$HAS_UPDATE" == "true" ]]; then
72+
echo "::notice::Update request with existing spec ID: $EXISTING_ID"
73+
else
74+
echo "::notice::Skipping: Issue already has spec ID: $EXISTING_ID"
75+
echo "should_run=false" >> $GITHUB_OUTPUT
76+
exit 0
77+
fi
78+
fi
79+
80+
echo "should_run=true" >> $GITHUB_OUTPUT
81+
82+
- name: Checkout repository
83+
if: steps.check.outputs.should_run == 'true'
84+
uses: actions/checkout@v6
85+
with:
86+
fetch-depth: 0
87+
88+
- name: React with eyes emoji
89+
if: steps.check.outputs.should_run == 'true'
90+
env:
91+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
92+
run: |
93+
gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/reactions \
94+
-f content=eyes
95+
96+
# ========================================================================
97+
# Step 2: Process request (NEW or UPDATE)
98+
# ========================================================================
99+
- name: Process with Claude
100+
if: steps.check.outputs.should_run == 'true'
101+
id: process
102+
timeout-minutes: 30
103+
uses: anthropics/claude-code-action@v1
104+
with:
105+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
106+
claude_args: "--model opus"
107+
prompt: |
108+
## Task: Prepare Plot Request
109+
110+
You are processing a plot request. Determine if this is a NEW or UPDATE request and handle accordingly.
111+
112+
### Issue Details
113+
- **Title:** ${{ github.event.issue.title }}
114+
- **Number:** #${{ github.event.issue.number }}
115+
- **Is Update:** ${{ steps.check.outputs.is_update }}
116+
- **Body:**
117+
```
118+
${{ github.event.issue.body }}
119+
```
120+
121+
---
122+
123+
## Instructions
124+
125+
### For NEW Requests (is_update=false):
126+
127+
1. **Read the rules:** `prompts/spec-id-generator.md`
128+
129+
2. **Check for duplicates:**
130+
- List all existing specs: `ls plots/`
131+
- Read existing spec files if titles seem similar
132+
- If duplicate found: Post comment explaining which spec matches, then STOP
133+
134+
3. **Generate spec-id:**
135+
- Format: `{type}-{variant}` or `{type}-{variant}-{modifier}`
136+
- Examples: `scatter-basic`, `bar-grouped-horizontal`, `heatmap-correlation`
137+
- All lowercase, hyphens only
138+
139+
4. **Create feature branch:**
140+
```bash
141+
git checkout -b "plot/{spec-id}"
142+
```
143+
144+
5. **Create spec files:**
145+
- Read template: `prompts/templates/spec.md`
146+
- Read metadata template: `prompts/templates/metadata.yaml`
147+
- Create directory: `plots/{spec-id}/`
148+
- Create: `plots/{spec-id}/spec.md` (follow template structure)
149+
- Create: `plots/{spec-id}/metadata.yaml` (replace placeholders)
150+
- Create empty folder: `plots/{spec-id}/implementations/`
151+
152+
6. **Commit and push:**
153+
```bash
154+
git config user.name "github-actions[bot]"
155+
git config user.email "github-actions[bot]@users.noreply.github.com"
156+
git add plots/{spec-id}/
157+
git commit -m "spec: add {spec-id} specification
158+
159+
Created from issue #${{ github.event.issue.number }}"
160+
git push -u origin "plot/{spec-id}"
161+
```
162+
163+
7. **Update issue title:**
164+
```bash
165+
gh issue edit ${{ github.event.issue.number }} --title "[{spec-id}] {original title without 'Plot: ' prefix}"
166+
```
167+
168+
8. **Post comment with spec content:**
169+
Use this format (read the actual spec.md content you created):
170+
```bash
171+
gh issue comment ${{ github.event.issue.number }} --body "## ✅ Spec Ready: \`{spec-id}\`
172+
173+
**Branch:** \`plot/{spec-id}\`
174+
175+
---
176+
177+
### spec.md
178+
179+
{paste full content of spec.md here}
180+
181+
---
182+
183+
**Next:** Add \`approved\` label to start code generation.
184+
185+
---
186+
:robot: *[plot-prepare workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})*"
187+
```
188+
189+
9. **Output for workflow:**
190+
After completing, print these lines exactly:
191+
```
192+
SPEC_ID={spec-id}
193+
FEATURE_BRANCH=plot/{spec-id}
194+
```
195+
196+
---
197+
198+
### For UPDATE Requests (is_update=true):
199+
200+
1. **Extract spec-id from title:**
201+
- Title format: `[spec-id] [update] ...` or `[spec-id] [update:library] ...`
202+
- Extract the first bracket content as spec-id
203+
204+
2. **Validate spec exists:**
205+
- Check if `plots/{spec-id}/spec.md` exists
206+
- If not: Post error comment and STOP
207+
208+
3. **Extract target library (if specified):**
209+
- `[update:seaborn]` → target only seaborn
210+
- `[update]` → target all libraries
211+
212+
4. **Analyze the update request:**
213+
- Read the current spec: `plots/{spec-id}/spec.md`
214+
- Read existing implementations if relevant
215+
- Evaluate if the update reason is sensible:
216+
- Is this a valid improvement?
217+
- Does it make sense for this plot type?
218+
- Are there any concerns?
219+
220+
5. **Create feature branch:**
221+
```bash
222+
git checkout -b "plot/{spec-id}"
223+
git push -u origin "plot/{spec-id}"
224+
```
225+
226+
6. **Post comment with analysis:**
227+
```bash
228+
gh issue comment ${{ github.event.issue.number }} --body "## 🔄 Update Request: \`{spec-id}\`
229+
230+
**Branch:** \`plot/{spec-id}\`
231+
**Scope:** {library name or 'all 9 libraries'}
232+
233+
---
234+
235+
### Analysis
236+
237+
{Your assessment of the update request:
238+
- Is the reason valid? Why/why not?
239+
- What changes would this involve?
240+
- Any concerns or suggestions?}
241+
242+
---
243+
244+
### Current Spec
245+
246+
\`\`\`markdown
247+
{paste current spec.md content}
248+
\`\`\`
249+
250+
---
251+
252+
**Recommendation:** {Approve / Needs clarification / Not recommended}
253+
254+
**Next:** Add \`approved\` label to start regeneration.
255+
256+
---
257+
:robot: *[plot-prepare workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})*"
258+
```
259+
260+
7. **Output for workflow:**
261+
```
262+
SPEC_ID={spec-id}
263+
FEATURE_BRANCH=plot/{spec-id}
264+
```
265+
266+
---
267+
268+
## Important Rules
269+
- Do NOT trigger any other workflows
270+
- Do NOT add labels
271+
- Do NOT close the issue
272+
- STOP after posting the comment - the `approved` label triggers the next phase
273+
274+
# ========================================================================
275+
# Step 3: Parse outputs
276+
# ========================================================================
277+
- name: Parse Claude outputs
278+
if: steps.check.outputs.should_run == 'true'
279+
id: parse
280+
run: |
281+
# Claude should have printed SPEC_ID and FEATURE_BRANCH
282+
# These are captured in the action output
283+
echo "::notice::Prepare phase complete - waiting for 'approved' label"
284+
285+
- name: Add rocket reaction on success
286+
if: steps.check.outputs.should_run == 'true' && success()
287+
env:
288+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
289+
run: |
290+
gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/reactions \
291+
-f content=rocket

0 commit comments

Comments
 (0)