Skip to content

feat(workflows): add issue lifecycle with update mechanism#98

Merged
MarkusNeusinger merged 4 commits intomainfrom
refactor/rename-sub-issue-label
Dec 1, 2025
Merged

feat(workflows): add issue lifecycle with update mechanism#98
MarkusNeusinger merged 4 commits intomainfrom
refactor/rename-sub-issue-label

Conversation

@MarkusNeusinger
Copy link
Copy Markdown
Owner

Summary

  • Rename label sub-issueplot-request:impl for clarity
  • Add update mechanism via [update] and [update:library] title syntax
  • Add targeted library regeneration (skip unaffected libraries)
  • Add new labels: test, update, completed
  • Document lifecycle and update workflow

Changes

New Update Syntax

  • [update] scatter-basic → Regenerate all 8 libraries
  • [update:seaborn] scatter-basic → Regenerate only seaborn
  • Issue body can contain spec changes (Claude updates spec first)

Issue Lifecycle

[open] plot-request → approved → in-progress → completed [closed]

New Labels

  • test - Test issues excluded from production searches
  • update - Update request for existing spec
  • completed - All implementations merged

Files Changed

  • .github/workflows/gen-new-plot.yml - Update detection + targeted generation
  • .github/workflows/bot-sync-status.yml - Label rename
  • .github/ISSUE_TEMPLATE/plot-update.yml - New syntax + library dropdown
  • CLAUDE.md - Labels + lifecycle documentation
  • docs/workflow.md - Labels + update workflow documentation

Test plan

  • Create [update] line-basic issue and verify only generation jobs run
  • Create [update:matplotlib] line-basic and verify only matplotlib job runs
  • Verify test label excludes issues from is:issue label:plot-request -label:test search

…abels

- Rename label sub-issue to plot-request:impl for clarity
- Add update mechanism via [update] and [update:library] title syntax
- Add targeted library regeneration (skip unaffected libraries)
- Add new labels: test, update (completed already existed)
- Update plot-update.yml template with new syntax and library dropdown
- Document lifecycle and update workflow in CLAUDE.md and docs/workflow.md
- Tag existing test issues (#33-37, #52, #75, #77-84) with test label
Copilot AI review requested due to automatic review settings December 1, 2025 21:09
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 1, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an update mechanism for existing plot specifications and renames the sub-issue label to plot-request:impl for improved clarity. The update mechanism allows users to regenerate all implementations or target specific libraries using special issue title syntax ([update] or [update:library]). The implementation includes targeted library regeneration that conditionally runs generation jobs based on the specified library, along with comprehensive documentation of the new workflow and issue lifecycle.

  • New update syntax: [update] spec-id for all libraries or [update:library] spec-id for targeted regeneration
  • Label rename from sub-issue to plot-request:impl for library implementation tracking
  • New labels added: test, update, completed with documented lifecycle states
  • Conditional job execution to skip unaffected libraries during targeted updates

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.github/workflows/gen-new-plot.yml Adds update detection regex, spec ID extraction for updates, library targeting conditions for generation jobs, and label rename to plot-request:impl
.github/workflows/bot-sync-status.yml Updates label check from sub-issue to plot-request:impl for consistency
.github/ISSUE_TEMPLATE/plot-update.yml Complete template restructure with update-focused title format, library dropdown, and simplified change request fields
docs/workflow.md Documents new label (plot-request:impl, completed, update, test) and adds update workflow section with examples
CLAUDE.md Updates workflow status labels section and adds comprehensive update mechanism documentation with issue lifecycle diagrams
Comments suppressed due to low confidence (1)

.github/workflows/gen-new-plot.yml:213

  • The create-sub-issues job creates sub-issues for ALL libraries regardless of whether target_library is specified. When a user creates an issue with [update:seaborn] scatter-basic, this will create 8 sub-issues but only run generation for seaborn, leaving 7 orphaned sub-issues in "generating" state.

Suggestion: Modify the loop to only create a sub-issue when target_library is empty OR matches the current library:

for LIBRARY in ${{ env.LIBRARIES }}; do
  TARGET="${{ needs.check-conditions.outputs.target_library }}"
  
  # Skip if targeting specific library and this isn't it
  if [ -n "$TARGET" ] && [ "$TARGET" != "$LIBRARY" ]; then
    continue
  fi
  
  echo "Creating sub-issue for $LIBRARY..."
  # ... rest of the code
done
      - name: Create sub-issues for each library
        id: create
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          SPEC_ID="${{ needs.check-conditions.outputs.spec_id }}"
          PARENT_NUM="${{ github.event.issue.number }}"
          PARENT_NODE_ID=$(gh api repos/${{ github.repository }}/issues/$PARENT_NUM --jq '.node_id')

          for LIBRARY in ${{ env.LIBRARIES }}; do
            echo "Creating sub-issue for $LIBRARY..."

            # Check if sub-issue already exists
            EXISTING=$(gh issue list --label "library:$LIBRARY" --search "[$SPEC_ID] in:title" --json number -q '.[0].number' 2>/dev/null || echo "")

            if [ -n "$EXISTING" ]; then
              echo "${LIBRARY}_issue=$EXISTING" >> $GITHUB_OUTPUT
              echo "::notice::Sub-issue for $LIBRARY already exists: #$EXISTING"
              continue
            fi

            # Create sub-issue
            SUB_BODY="## [$SPEC_ID] $LIBRARY Implementation

          **Parent Issue:** #$PARENT_NUM
          **Spec:** \`specs/$SPEC_ID.md\`
          **Library:** $LIBRARY

          ---

          ### Attempt History

          _Attempts will be documented below as comments._
          "

            SUB_ISSUE=$(gh issue create \
              --title "[$SPEC_ID] $LIBRARY implementation" \
              --body "$SUB_BODY" \
              --label "library:$LIBRARY,plot-request:impl,generating")

            SUB_NUM=$(echo "$SUB_ISSUE" | grep -oP '\d+$')
            SUB_NODE_ID=$(gh api repos/${{ github.repository }}/issues/$SUB_NUM --jq '.node_id')

            # Link as sub-issue using GitHub's sub-issues API
            gh api graphql -f query='
              mutation($parent: ID!, $child: ID!) {
                addSubIssue(input: {issueId: $parent, subIssueId: $child}) {
                  issue { id }
                }
              }' -f parent="$PARENT_NODE_ID" -f child="$SUB_NODE_ID" 2>/dev/null || echo "Note: Sub-issue linking not available"

            echo "${LIBRARY}_issue=$SUB_NUM" >> $GITHUB_OUTPUT
            echo "::notice::Created sub-issue for $LIBRARY: #$SUB_NUM"
          done

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Comment thread CLAUDE.md Outdated
Comment thread .github/workflows/gen-new-plot.yml
Comment thread .github/ISSUE_TEMPLATE/plot-update.yml
label: Spec ID
description: "The spec ID of the plot to update (e.g., bar-basic)"
placeholder: "bar-basic"
description: "The spec ID of the plot to update (will be appended to title)"
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description states "will be appended to title" but GitHub issue templates don't automatically append form field values to the title. Users must manually type the spec ID into the title after the [update] prefix.

Suggestion: Update the description to be clearer:

description: "The spec ID of the plot to update (must be manually added to the title above)"
Suggested change
description: "The spec ID of the plot to update (will be appended to title)"
description: "The spec ID of the plot to update (must be manually added to the title above)"

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings December 1, 2025 21:16
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@MarkusNeusinger MarkusNeusinger merged commit 891065d into main Dec 1, 2025
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the refactor/rename-sub-issue-label branch December 1, 2025 21:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (2)

.github/workflows/gen-new-plot.yml:213

  • The create-sub-issues job doesn't respect the target_library output and will create sub-issues for all 8 libraries even when [update:library] syntax is used. This means that if a user specifies [update:matplotlib] scatter-basic, sub-issues will be created for all libraries (seaborn, plotly, etc.), but only the matplotlib generation job will run.

Consider adding a condition to skip creating sub-issues for libraries that aren't targeted, or filter the loop in the "Create sub-issues for each library" step to only process the target library when specified.

            -f content=eyes

      - name: Add in-progress label
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh issue edit ${{ github.event.issue.number }} --add-label "in-progress"

      - name: Create sub-issues for each library
        id: create
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          SPEC_ID="${{ needs.check-conditions.outputs.spec_id }}"
          PARENT_NUM="${{ github.event.issue.number }}"
          PARENT_NODE_ID=$(gh api repos/${{ github.repository }}/issues/$PARENT_NUM --jq '.node_id')

          for LIBRARY in ${{ env.LIBRARIES }}; do
            echo "Creating sub-issue for $LIBRARY..."

            # Check if sub-issue already exists
            EXISTING=$(gh issue list --label "library:$LIBRARY" --search "[$SPEC_ID] in:title" --json number -q '.[0].number' 2>/dev/null || echo "")

            if [ -n "$EXISTING" ]; then
              echo "${LIBRARY}_issue=$EXISTING" >> $GITHUB_OUTPUT
              echo "::notice::Sub-issue for $LIBRARY already exists: #$EXISTING"
              continue
            fi

            # Create sub-issue
            SUB_BODY="## [$SPEC_ID] $LIBRARY Implementation

          **Parent Issue:** #$PARENT_NUM
          **Spec:** \`specs/$SPEC_ID.md\`
          **Library:** $LIBRARY

          ---

          ### Attempt History

          _Attempts will be documented below as comments._
          "

            SUB_ISSUE=$(gh issue create \
              --title "[$SPEC_ID] $LIBRARY implementation" \
              --body "$SUB_BODY" \
              --label "library:$LIBRARY,plot-request:impl,generating")

            SUB_NUM=$(echo "$SUB_ISSUE" | grep -oP '\d+$')
            SUB_NODE_ID=$(gh api repos/${{ github.repository }}/issues/$SUB_NUM --jq '.node_id')

            # Link as sub-issue using GitHub's sub-issues API
            gh api graphql -f query='
              mutation($parent: ID!, $child: ID!) {

.github/workflows/gen-new-plot.yml:223

  • [nitpick] In GitHub Actions, an empty string '' is falsy in conditional expressions. The condition checks if target_library == '' which will be true when no library is specified. However, when checking for a specific library match, you're comparing against the library name string directly.

This logic is correct, but consider using a more explicit check for clarity:

(needs.check-conditions.outputs.target_library == '' || needs.check-conditions.outputs.target_library == 'matplotlib')

The current implementation works, but it's worth documenting that empty string is used to represent "all libraries" rather than using a special value like "all".

            echo "::notice::Created sub-issue for $LIBRARY: #$SUB_NUM"
          done

  # ============================================================================

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

if echo "$ISSUE_TITLE" | grep -qiP '^\[update(:[a-z]+)?\]'; then
IS_UPDATE="true"
# Extract target library if specified (e.g., [update:seaborn])
TARGET_LIBRARY=$(echo "$ISSUE_TITLE" | grep -oiP '^\[update:\K[a-z]+(?=\])' | tr '[:upper:]' '[:lower:]' || echo "")
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern allows only lowercase letters [a-z]+ but library names in the codebase use lowercase only. However, the issue template dropdown includes library names like "matplotlib", "seaborn", etc., which users could manually type with different cases. While there's a tr '[:upper:]' '[:lower:]' to handle this, the regex should be more permissive to match the input before normalization.

Consider changing the pattern to: '^\[update:\K[a-zA-Z]+(?=\])' to accept any case, since you're already normalizing with tr '[:upper:]' '[:lower:]'.

Suggested change
TARGET_LIBRARY=$(echo "$ISSUE_TITLE" | grep -oiP '^\[update:\K[a-z]+(?=\])' | tr '[:upper:]' '[:lower:]' || echo "")
TARGET_LIBRARY=$(echo "$ISSUE_TITLE" | grep -oiP '^\[update:\K[a-zA-Z]+(?=\])' | tr '[:upper:]' '[:lower:]' || echo "")

Copilot uses AI. Check for mistakes.
Comment thread docs/workflow.md

To update or regenerate an existing plot:

1. Create issue with title: `[update] {spec-id}` (all libraries) or `[update:seaborn] {spec-id}` (single library)
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistency in example syntax: the documentation shows [update:library] but the example uses [update:seaborn] with a specific library name. While this works, it would be clearer to show the general pattern first, then the specific example.

Consider: [update:{library}] for the pattern, followed by the concrete example [update:seaborn].

Suggested change
1. Create issue with title: `[update] {spec-id}` (all libraries) or `[update:seaborn] {spec-id}` (single library)
1. Create issue with title: `[update] {spec-id}` (all libraries) or `[update:{library}] {spec-id}` (single library, e.g. `[update:seaborn] heatmap-correlation`)

Copilot uses AI. Check for mistakes.
IS_UPDATE="false"
TARGET_LIBRARY=""

if echo "$ISSUE_TITLE" | grep -qiP '^\[update(:[a-z]+)?\]'; then
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern '^\[update(:[a-z]+)?\]' should be more permissive to match any case in the library name since the code already normalizes the extracted library with tr '[:upper:]' '[:lower:]' on line 75.

Consider changing to: '^\[update(:[a-zA-Z]+)?\]' to accept mixed-case library names before normalization.

Suggested change
if echo "$ISSUE_TITLE" | grep -qiP '^\[update(:[a-z]+)?\]'; then
if echo "$ISSUE_TITLE" | grep -qiP '^\[update(:[a-zA-Z]+)?\]'; then

Copilot uses AI. Check for mistakes.
Comment thread CLAUDE.md
**Sub-Issue Lifecycle:**
```
[open] generating → testing → reviewing → merged [closed]
→ not-feasible [closed]
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The Sub-Issue Lifecycle documentation shows the transition to not-feasible but doesn't show the intermediate retry states (with ai-rejected label). According to the workflow files in the codebase, the actual flow includes retry attempts with ai-rejected before reaching not-feasible after 3 failures.

Consider updating to show:

[open] generating → testing → reviewing → merged [closed]
                                        → ai-rejected (retry) → ...
                                        → not-feasible [closed] (after 3 attempts)
Suggested change
not-feasible [closed]
ai-rejected (retry) → ...
→ not-feasible [closed] (after 3 attempts)

Copilot uses AI. Check for mistakes.
**Sub-Issue Lifecycle:**
```
[open] generating → testing → reviewing → merged [closed]
→ not-feasible [closed]
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The Sub-Issue Lifecycle documentation shows the transition to not-feasible but doesn't show the intermediate retry states (with ai-rejected label). According to the workflow files in the codebase, the actual flow includes retry attempts with ai-rejected before reaching not-feasible after 3 failures.

Consider updating to show:

[open] generating → testing → reviewing → merged [closed]
                                        → ai-rejected (retry) → ...
                                        → not-feasible [closed] (after 3 attempts)
Suggested change
not-feasible [closed]
ai-rejected (retry) → ...
→ not-feasible [closed] (after 3 attempts)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants