Skip to content

Commit b2dec43

Browse files
committed
feat(workflows): add duplicate detection and update documentation
## Duplicate Detection (Medium Priority Fix) Added automatic duplicate detection in spec-create.yml: - Validates that specification directory was actually created - Checks Claude's comment for duplicate indicators - Auto-closes issue with 'duplicate' label if duplicate detected - Removes 'spec-request' label to prevent confusion - Provides clear error message if creation failed for other reasons This prevents duplicate issues from staying open with stale labels. ## Documentation Updates (CLAUDE.md) Updated workflow documentation to reflect recent improvements: 1. **Supporting Workflows** - Added sync-labels.yml to the list - Documents automatic label synchronization after manual merges 2. **Workflow Data Flow** - Enhanced Flow A (spec creation) - Added duplicate detection validation step - Shows when issues are auto-closed for duplicates 3. **Workflow Data Flow** - Enhanced Flow B (implementation) - Documents atomic commits (implementation + metadata together) - Shows PR completeness validation in impl-merge.yml - Prevents partial merges with missing implementation files 4. **Decoupled Architecture** - Added benefits - Labels auto-synced after manual PR merges - Spec merge operations serialized to prevent race conditions All workflow improvements from #3228 are now fully documented. Related: #3228
1 parent edc2ac7 commit b2dec43

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

.github/workflows/spec-create.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,41 @@ jobs:
275275
env:
276276
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
277277

278+
- name: Validate specification was created (not duplicate)
279+
if: steps.check.outputs.should_run == 'true'
280+
env:
281+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
282+
SPEC_ID: ${{ steps.extract.outputs.specification_id }}
283+
ISSUE_NUM: ${{ github.event.issue.number }}
284+
run: |
285+
# Check if specification directory was actually created
286+
if [ ! -d "plots/${SPEC_ID}" ]; then
287+
echo "::warning::Specification directory not created - likely a duplicate"
288+
289+
# Get Claude's comment to find duplicate info
290+
COMMENT=$(gh issue view "$ISSUE_NUM" --json comments -q '.comments[-1].body' 2>/dev/null || echo "")
291+
292+
if echo "$COMMENT" | grep -qi "duplicate\|exists\|already"; then
293+
echo "::notice::Claude detected duplicate - closing issue"
294+
295+
gh label create "duplicate" --color "cfd3d7" \
296+
--description "Duplicate specification" 2>/dev/null || true
297+
298+
gh issue edit "$ISSUE_NUM" --remove-label "spec-request" 2>/dev/null || true
299+
gh issue edit "$ISSUE_NUM" --add-label "duplicate" 2>/dev/null || true
300+
gh issue close "$ISSUE_NUM" --comment "**Duplicate detected:** Claude's analysis indicates this specification already exists. See previous comment for details."
301+
302+
exit 0 # Not an error, just a duplicate
303+
fi
304+
305+
# If not a duplicate, something else failed
306+
echo "::error::Specification creation failed for unknown reason"
307+
gh issue comment "$ISSUE_NUM" --body "**Error:** Specification creation failed. Please check the [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details."
308+
exit 1
309+
fi
310+
311+
echo "::notice::Specification directory created successfully"
312+
278313
- name: Create Pull Request
279314
if: steps.check.outputs.should_run == 'true'
280315
id: pr

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ spec-create.yml
637637
├── Creates branch: specification/{specification-id}
638638
├── Creates: plots/{specification-id}/specification.md
639639
├── Creates: plots/{specification-id}/specification.yaml
640+
├── Validates: checks for duplicates (closes issue if duplicate detected)
640641
├── Creates PR: specification/{specification-id} → main
641642
└── Posts: spec analysis comment (waits for approval)
642643
@@ -658,6 +659,7 @@ impl-generate.yml
658659
├── Creates branch: implementation/{specification-id}/{library}
659660
├── Generates implementation code
660661
├── Tests with MPLBACKEND=Agg
662+
├── Commits implementation + metadata atomically (prevents partial PRs)
661663
├── Uploads preview to GCS staging
662664
├── Creates PR: implementation/{specification-id}/{library} → main
663665
└── Triggers impl-review.yml
@@ -669,6 +671,7 @@ impl-review.yml
669671
├── Adds labels: quality:XX, ai-approved OR ai-rejected
670672
671673
├── If APPROVED → triggers impl-merge.yml
674+
│ ├── Validates PR completeness (blocks merge if implementation file missing)
672675
│ ├── Squash-merges PR to main
673676
│ ├── Creates metadata/{library}.yaml
674677
│ ├── Promotes GCS: staging → production
@@ -711,6 +714,7 @@ Issue ready for maintainer review
711714
| **ci-lint.yml** | Ruff linting on PR |
712715
| **ci-unittest.yml** | Unit tests on PR |
713716
| **sync-postgres.yml** | Syncs plots/ to database on push to main |
717+
| **sync-labels.yml** | Auto-syncs labels after manual PR merges (spec-ready, impl:*:done) |
714718
715719
### Decoupled Architecture
716720
@@ -723,6 +727,7 @@ The new architecture separates specification and implementation processes:
723727
- **No merge conflicts** - Per-library metadata files
724728
- **Flexible triggers** - Labels for single, dispatch for bulk
725729
- **PostgreSQL synced on every merge to main**
730+
- **Labels auto-synced** - Manual PR merges automatically update issue labels
726731
727732
**Branch naming:**
728733
- `specification/{specification-id}` - New specification PRs
@@ -731,6 +736,7 @@ The new architecture separates specification and implementation processes:
731736
**Concurrency:**
732737
- Global limit: max 3 implementation workflows simultaneously
733738
- `bulk-generate.yml` uses `max-parallel: 3` in matrix strategy
739+
- Spec merge operations are serialized (one at a time) to prevent race conditions
734740
735741
## GitHub Issue Labels
736742

0 commit comments

Comments
 (0)