feat(bmm): Add provider-agnostic DevOps integration for GitHub and Azure DevOps

Implement comprehensive DevOps integration supporting both GitHub Issues and
Azure DevOps across the full BMM workflow lifecycle.

## New Features

### Sprint Planning (sprint-planning)
- Create GitHub milestones or Azure DevOps iterations for sprint tracking
- Create epic-level issues/work items with proper labels/tags
- Store tracking references in sprint-status.yaml

### Story Creation (create-story)
- Link stories to milestones/iterations when creating tracking items
- Establish parent-child relationships between epics and stories
- Support GitHub milestone assignment and Azure DevOps iteration paths

### Story Implementation (dev-story)
- Auto-link PRs to issues using 'Closes #X' syntax for GitHub
- Link PRs to work items using --work-items flag for Azure DevOps
- Provider-aware branch naming convention (story/{{story_key}})

### Code Review (code-review)
- Post review comments to GitHub issues or Azure DevOps work items
- Provider-aware PR merge with squash strategy
- Automatic issue/work item closure on merge

### Correct Course (correct-course)
- Sync mid-sprint changes to external tracking systems
- Create/update/remove tracking items based on change proposals
- Support add, modify, and descope operations

### Retrospective (retrospective)
- Create retrospective issues/work items with action items
- Auto-close epic issues/work items when all stories complete
- Link retrospective records to parent epic

### Configuration & Documentation
- New devops-providers.yaml with CLI command reference for both providers
- Enhanced sprint-status-template.yaml with provider configuration docs
- Support for file-system, github-issues, and azure-devops tracking systems

## Files Changed
- src/modules/bmm/data/devops-providers.yaml (new)
- src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md
- src/modules/bmm/workflows/4-- Post review comment-planning/sprint-status-template.yaml
- src/modules/bmm/workflows/4-implementation/create-story/instructions.xml
- src/modules/bmm/workflows/4-implementation/dev-story/instructions.xml
- src/modules/bmm/workflows/4-implementation/code-review/instructions.xml
- src/modules/bmm/workflows/4-implementation/correct-course/instructions.md
- src/modules/bmm/workflows/4-implementation/retrospective/instructions.md
This commit is contained in:
Sjoerd Bozon 2025-12-28 18:47:27 +01:00
parent b509fb9a1e
commit 37b8e83029
8 changed files with 609 additions and 2 deletions

View File

@ -0,0 +1,151 @@
# DevOps Provider Configuration
# Central reference for provider-specific CLI commands
# Supports GitHub and Azure DevOps as tracking systems
providers:
github-issues:
description: "GitHub Issues and Pull Requests via gh CLI"
cli: "gh"
# Branch operations (same across providers - use git directly)
branch:
create: "git checkout -b {{branch_name}}"
delete: "git branch -d {{branch_name}}"
switch: "git checkout {{branch_name}}"
# Milestone/Sprint operations
milestone:
create: |
gh api repos/{owner}/{repo}/milestones -f title="{{milestone_title}}" -f description="{{milestone_description}}" -f due_on="{{due_date}}"
list: |
gh api repos/{owner}/{repo}/milestones --jq '.[].title'
get_number: |
gh api repos/{owner}/{repo}/milestones --jq '.[] | select(.title=="{{milestone_title}}") | .number'
# Epic operations (using labels for epics in GitHub)
epic:
create: |
gh issue create --title "Epic {{epic_num}}: {{epic_title}}" --body "{{epic_description}}" --label "epic,{{project_key}}"
close: |
gh issue close {{epic_issue_number}}
list: |
gh issue list --label "epic" --state open
# Issue/Work Item operations
issue:
create: |
gh issue create --title "{{story_key}}: {{title}}" --body "$(cat {{story_file}})" --label "story,sprint" --milestone "{{milestone_title}}"
create_no_milestone: |
gh issue create --title "{{story_key}}: {{title}}" --body "$(cat {{story_file}})" --label "story,sprint"
close: |
gh issue close {{issue_number}}
update: |
gh issue edit {{issue_number}} --body "{{body}}"
add_to_milestone: |
gh issue edit {{issue_number}} --milestone "{{milestone_title}}"
list: |
gh issue list --label "sprint" --state open
# Pull Request operations
pr:
create: |
gh pr create --title "{{story_key}}: {{title}}" --body "{{body}}" --base main
create_with_closes: |
gh pr create --title "{{story_key}}: {{title}}" --body "{{body}}\n\nCloses #{{issue_number}}" --base main
comment: |
gh pr comment {{branch_name}} --body "{{comment_body}}"
merge: |
gh pr merge {{branch_name}} --squash --delete-branch
close: |
gh pr close {{branch_name}}
list: |
gh pr list --state open
# Sprint status field mappings
status_fields:
tracking_system: "github-issues"
repo: "owner/repo-name"
tracking_ref: "issue_number"
milestone: "Sprint X"
azure-devops:
description: "Azure DevOps Work Items and Pull Requests via az CLI"
cli: "az"
# Branch operations (same across providers - use git directly)
branch:
create: "git checkout -b {{branch_name}}"
delete: "git branch -d {{branch_name}}"
switch: "git checkout {{branch_name}}"
# Iteration/Sprint operations
iteration:
create: |
az boards iteration project create --name "{{iteration_name}}" --path "\\{{project}}\\Iteration" --start-date "{{start_date}}" --finish-date "{{end_date}}" --org {{org_url}} --project {{project}}
list: |
az boards iteration project list --org {{org_url}} --project {{project}}
get_path: |
az boards iteration project list --org {{org_url}} --project {{project}} --query "[?name=='{{iteration_name}}'].path" -o tsv
# Epic operations
epic:
create: |
az boards work-item create --title "Epic {{epic_num}}: {{epic_title}}" --type "Epic" --description "{{epic_description}}" --org {{org_url}} --project {{project}}
close: |
az boards work-item update --id {{epic_work_item_id}} --state Closed --org {{org_url}}
list: |
az boards query --wiql "SELECT [System.Id], [System.Title] FROM workitems WHERE [System.WorkItemType] = 'Epic' AND [System.State] <> 'Closed'" --org {{org_url}} --project {{project}}
# Work Item operations
issue:
create: |
az boards work-item create --title "{{story_key}}: {{title}}" --type "User Story" --description "{{description}}" --iteration "{{iteration_path}}" --org {{org_url}} --project {{project}}
create_no_iteration: |
az boards work-item create --title "{{story_key}}: {{title}}" --type "User Story" --description "{{description}}" --org {{org_url}} --project {{project}}
close: |
az boards work-item update --id {{work_item_id}} --state Closed --org {{org_url}}
update: |
az boards work-item update --id {{work_item_id}} --description "{{description}}" --org {{org_url}}
add_to_iteration: |
az boards work-item update --id {{work_item_id}} --iteration "{{iteration_path}}" --org {{org_url}}
link_to_parent: |
az boards work-item relation add --id {{work_item_id}} --relation-type "System.LinkTypes.Hierarchy-Reverse" --target-id {{parent_id}} --org {{org_url}}
list: |
az boards query --wiql "SELECT [System.Id], [System.Title] FROM workitems WHERE [System.WorkItemType] = 'User Story' AND [System.State] = 'Active'" --org {{org_url}} --project {{project}}
# Pull Request operations
pr:
create: |
az repos pr create --title "{{story_key}}: {{title}}" --description "{{description}}" --source-branch {{branch_name}} --target-branch main --org {{org_url}} --project {{project}}
create_with_work_item: |
az repos pr create --title "{{story_key}}: {{title}}" --description "{{description}}" --source-branch {{branch_name}} --target-branch main --work-items {{work_item_id}} --org {{org_url}} --project {{project}}
comment: |
az repos pr update --id {{pr_id}} --description "{{description}}" --org {{org_url}}
merge: |
az repos pr update --id {{pr_id}} --status completed --org {{org_url}}
close: |
az repos pr update --id {{pr_id}} --status abandoned --org {{org_url}}
list: |
az repos pr list --status active --org {{org_url}} --project {{project}}
# Sprint status field mappings
status_fields:
tracking_system: "azure-devops"
org_url: "https://dev.azure.com/your-org"
project: "YourProjectName"
tracking_ref: "work_item_id"
iteration: "Sprint X"
# Workflow behavior matrix reference:
# | Workflow | Step | GitHub | Azure DevOps |
# |----------------|---------------------|-------------------------------------|-------------------------------------------------|
# | sprint-planning| Create milestone | gh api .../milestones | az boards iteration project create |
# | sprint-planning| Create epic items | gh issue create --label epic | az boards work-item create --type Epic |
# | create-story | Create tracking | gh issue create --milestone | az boards work-item create --iteration |
# | dev-story | Create branch | git checkout -b | git checkout -b |
# | dev-story | Create PR | gh pr create (with Closes #X) | az repos pr create --work-items |
# | code-review | Post findings | gh pr comment | az repos pr update |
# | code-review | Merge PR | gh pr merge --squash | az repos pr update --status completed |
# | code-review | Close item | gh issue close | az boards work-item update --state Closed |
# | correct-course | Add/update items | gh issue create/edit | az boards work-item create/update |
# | retrospective | Create retro item | gh issue create --label retro | az boards work-item create --type Task |

View File

@ -178,12 +178,95 @@
</check>
<action>Save story file</action>
<!-- Determine sprint tracking status -->
<!-- Determine sprint tracking status and provider -->
<check if="{sprint_status} file exists">
<action>Set {{current_sprint_status}} = "enabled"</action>
<action>Load {{sprint_status}} and extract tracking_system configuration</action>
<action>Set {{tracking_system}} from sprint-status.yaml (default: github-issues)</action>
</check>
<check if="{sprint_status} file does NOT exist">
<action>Set {{current_sprint_status}} = "no-sprint-tracking"</action>
<action>Set {{tracking_system}} = "none"</action>
</check>
<!-- Post review findings to PR (provider-aware) -->
<check if="{{tracking_system}} == 'github-issues'">
<action>Format review findings as markdown comment:
## 🔍 Code Review Results
**Reviewer:** AI Code Reviewer
**Status:** {{new_status == 'done' ? 'Approved ✅' : 'Changes Requested 🔄'}}
### Findings Summary
- High: {{high_count}}
- Medium: {{medium_count}}
- Low: {{low_count}}
### AC Validation
{{ac_validation_results}}
### Issues Fixed
{{fixed_issues_summary}}
</action>
<action>Run: gh pr comment story/{{story_key}} --body "{{review_comment}}"</action>
<output>📝 Review findings posted to GitHub PR</output>
</check>
<check if="{{tracking_system}} == 'azure-devops'">
<action>Extract org_url and project from sprint-status.yaml</action>
<action>Extract pr_id from sprint-status.yaml or discover from branch</action>
<action>Format review findings as PR description update:
## 🔍 Code Review Complete
**Reviewer:** AI Code Reviewer
**Status:** {{new_status == 'done' ? 'Approved ✅' : 'Changes Requested 🔄'}}
### Findings Summary
- High: {{high_count}}
- Medium: {{medium_count}}
- Low: {{low_count}}
### AC Validation
{{ac_validation_results}}
### Issues Fixed
{{fixed_issues_summary}}
</action>
<action>Run: az repos pr update --id {{pr_id}} --description "{{review_description}}" --org {{org_url}}</action>
<output>📝 Review findings posted to Azure DevOps PR</output>
</check>
<!-- Merge PR and close tracking item if approved (provider-aware) -->
<check if="{{new_status}} == 'done'">
<!-- GitHub merge and close -->
<check if="{{tracking_system}} == 'github-issues'">
<action>Run: gh pr merge story/{{story_key}} --squash --delete-branch</action>
<output>✅ GitHub PR merged with squash</output>
<action>Extract issue_number from sprint-status.yaml tracking_ref for this story</action>
<check if="issue_number exists">
<action>Run: gh issue close {{issue_number}}</action>
<output>✅ GitHub Issue #{{issue_number}} closed</output>
</check>
<action>Run: git checkout main</action>
<action>Run: git pull origin main</action>
</check>
<!-- Azure DevOps merge and close -->
<check if="{{tracking_system}} == 'azure-devops'">
<action>Extract org_url and project from sprint-status.yaml</action>
<action>Extract pr_id from sprint-status.yaml or discover from branch</action>
<action>Run: az repos pr update --id {{pr_id}} --status completed --org {{org_url}}</action>
<output>✅ Azure DevOps PR completed</output>
<action>Extract work_item_id from sprint-status.yaml tracking_ref for this story</action>
<check if="work_item_id exists">
<action>Run: az boards work-item update --id {{work_item_id}} --state Closed --org {{org_url}}</action>
<output>✅ Azure DevOps Work Item #{{work_item_id}} closed</output>
</check>
<action>Run: git checkout main</action>
<action>Run: git pull origin main</action>
</check>
<check if="{{tracking_system}} == 'none'">
<output> No tracking system configured - manual PR merge required</output>
</check>
</check>
<!-- Sync sprint-status.yaml when story status changes (only if sprint tracking enabled) -->

View File

@ -186,6 +186,87 @@
</step>
<step n="5.5" goal="Sync changes to external tracking system">
<critical>Update external tracking system with approved changes</critical>
<action>Load {sprint_status} and extract tracking_system configuration</action>
<action>Set {{tracking_system}} from sprint-status.yaml (default: file-system)</action>
<check if="tracking_system == 'file-system' OR tracking_system not configured">
<output> Using file-system tracking only - no external DevOps sync needed</output>
<action>Skip external tracking updates</action>
</check>
<!-- GitHub Issues Sync -->
<check if="tracking_system == 'github-issues'">
<action>Extract repo and milestone from sprint-status.yaml</action>
<!-- For new stories added -->
<check if="new stories added in change proposal">
<action>For each new story:</action>
<action>Run: gh issue create --title "{{story_key}}: {{story_title}}" --body "{{story_description}}\n\n**Added via correct-course workflow**" --label "story,sprint,mid-sprint-add" --milestone "{{milestone}}"</action>
<action>Capture issue number and update sprint-status.yaml tracking_ref</action>
<output>✅ GitHub Issue created for new story: #{{issue_number}}</output>
</check>
<!-- For modified stories -->
<check if="existing stories modified in change proposal">
<action>For each modified story:</action>
<action>Extract issue_number from sprint-status.yaml tracking_ref</action>
<action>Run: gh issue edit {{issue_number}} --body "{{updated_body}}\n\n**Modified via correct-course: {{change_reason}}**"</action>
<action>Run: gh issue comment {{issue_number}} --body "📝 **Story Updated via Correct-Course**\n\nChange Reason: {{change_reason}}\nModified Sections: {{modified_sections}}"</action>
<output>✅ GitHub Issue #{{issue_number}} updated</output>
</check>
<!-- For removed/descoped stories -->
<check if="stories removed or descoped in change proposal">
<action>For each removed story:</action>
<action>Extract issue_number from sprint-status.yaml tracking_ref</action>
<action>Run: gh issue close {{issue_number}} --reason "not planned" --comment "Story descoped via correct-course workflow. Reason: {{descope_reason}}"</action>
<output>✅ GitHub Issue #{{issue_number}} closed (descoped)</output>
</check>
</check>
<!-- Azure DevOps Sync -->
<check if="tracking_system == 'azure-devops'">
<action>Extract org_url, project, and iteration from sprint-status.yaml</action>
<!-- For new stories added -->
<check if="new stories added in change proposal">
<action>For each new story:</action>
<action>Run: az boards work-item create --title "{{story_key}}: {{story_title}}" --type "User Story" --description "{{story_description}}\n\n**Added via correct-course workflow**" --iteration "{{iteration_path}}" --org {{org_url}} --project {{project}}</action>
<action>Capture work_item_id and update sprint-status.yaml tracking_ref</action>
<action>Add tag: az boards work-item update --id {{work_item_id}} --fields "System.Tags=mid-sprint-add" --org {{org_url}}</action>
<output>✅ Azure DevOps Work Item created for new story: #{{work_item_id}}</output>
</check>
<!-- For modified stories -->
<check if="existing stories modified in change proposal">
<action>For each modified story:</action>
<action>Extract work_item_id from sprint-status.yaml tracking_ref</action>
<action>Run: az boards work-item update --id {{work_item_id}} --description "{{updated_description}}\n\n**Modified via correct-course: {{change_reason}}**" --org {{org_url}}</action>
<action>Add history comment via discussion field update</action>
<output>✅ Azure DevOps Work Item #{{work_item_id}} updated</output>
</check>
<!-- For removed/descoped stories -->
<check if="stories removed or descoped in change proposal">
<action>For each removed story:</action>
<action>Extract work_item_id from sprint-status.yaml tracking_ref</action>
<action>Run: az boards work-item update --id {{work_item_id}} --state "Removed" --org {{org_url}}</action>
<action>Add reason to description</action>
<output>✅ Azure DevOps Work Item #{{work_item_id}} marked as Removed</output>
</check>
</check>
<output>
**External Tracking Sync Complete:**
- New items created: {{new_count}}
- Items updated: {{updated_count}}
- Items closed/removed: {{removed_count}}
</output>
</step>
<step n="6" goal="Workflow Completion">
<action>Summarize workflow execution:</action>
- Issue addressed: {{change_trigger}}

View File

@ -341,4 +341,77 @@
</output>
</step>
<step n="7" goal="Create tracking item in external system">
<critical>Create issue/work item in the configured tracking system after story file is created</critical>
<!-- Check if tracking system is configured -->
<check if="sprint status file exists">
<action>Load {{sprint_status}} and extract tracking_system configuration</action>
<action>Set {{tracking_system}} from sprint-status.yaml (default: github-issues)</action>
<action>Extract milestone or iteration name if configured</action>
<action>Extract epic parent reference (epic_issue_{{epic_num}} or epic_work_item_{{epic_num}})</action>
</check>
<check if="sprint status file does NOT exist OR tracking_system not configured">
<action>Set {{tracking_system}} = "none"</action>
<output> No tracking system configured - skipping external issue creation</output>
<action>GOTO workflow end</action>
</check>
<!-- GitHub Issues Provider -->
<check if="{{tracking_system}} == 'github-issues'">
<action>Extract repo from sprint-status.yaml (format: owner/repo)</action>
<action>Extract milestone name from sprint-status.yaml (if configured)</action>
<action>Read story file content for issue body</action>
<!-- Create issue with milestone if available -->
<check if="milestone is configured">
<action>Run: gh issue create --title "{{story_key}}: {{story_title}}" --body "$(cat {{story_file}})" --label "story,sprint" --milestone "{{milestone}}"</action>
</check>
<check if="milestone is NOT configured">
<action>Run: gh issue create --title "{{story_key}}: {{story_title}}" --body "$(cat {{story_file}})" --label "story,sprint"</action>
</check>
<action>Capture issue number from command output</action>
<action>Update sprint-status.yaml with tracking_ref: {{issue_number}} for this story key</action>
<!-- Link to parent epic issue if available -->
<check if="epic_issue_{{epic_num}} exists in sprint-status.yaml">
<action>Add comment linking to parent epic: gh issue comment {{issue_number}} --body "Part of Epic #{{epic_issue_number}}"</action>
</check>
<output>✅ GitHub Issue created: #{{issue_number}} (linked to milestone: {{milestone}})</output>
</check>
<!-- Azure DevOps Provider -->
<check if="{{tracking_system}} == 'azure-devops'">
<action>Extract org_url and project from sprint-status.yaml</action>
<action>Extract iteration path from sprint-status.yaml (if configured)</action>
<action>Prepare description from story file (truncate if needed for Azure DevOps limits)</action>
<!-- Create work item with iteration if available -->
<check if="iteration is configured">
<action>Run: az boards work-item create --title "{{story_key}}: {{story_title}}" --type "User Story" --description "{{story_description}}" --iteration "{{iteration_path}}" --org {{org_url}} --project {{project}}</action>
</check>
<check if="iteration is NOT configured">
<action>Run: az boards work-item create --title "{{story_key}}: {{story_title}}" --type "User Story" --description "{{story_description}}" --org {{org_url}} --project {{project}}</action>
</check>
<action>Capture work_item_id from command output</action>
<action>Update sprint-status.yaml with tracking_ref: {{work_item_id}} for this story key</action>
<!-- Link to parent epic work item if available -->
<check if="epic_work_item_{{epic_num}} exists in sprint-status.yaml">
<action>Run: az boards work-item relation add --id {{work_item_id}} --relation-type "System.LinkTypes.Hierarchy-Reverse" --target-id {{epic_work_item_id}} --org {{org_url}}</action>
<output>✅ Linked to parent Epic #{{epic_work_item_id}}</output>
</check>
<output>✅ Azure DevOps Work Item created: #{{work_item_id}} (in iteration: {{iteration}})</output>
</check>
<!-- Unknown provider -->
<check if="{{tracking_system}} != 'github-issues' AND {{tracking_system}} != 'azure-devops' AND {{tracking_system}} != 'none'">
<output>⚠️ Unknown tracking system: {{tracking_system}} - skipping external issue creation</output>
</check>
</step>
</workflow>

View File

@ -219,6 +219,18 @@
<output> No sprint status file exists - story progress will be tracked in story file only</output>
<action>Set {{current_sprint_status}} = "no-sprint-tracking"</action>
</check>
<!-- Create feature branch for story (provider-agnostic) -->
<check if="current status == 'ready-for-dev'">
<action>Check if already on story branch: git branch --show-current</action>
<check if="current branch != story/{{story_key}}">
<action>Run: git checkout -b story/{{story_key}}</action>
<output>🌿 Created feature branch: story/{{story_key}}</output>
</check>
<check if="current branch == story/{{story_key}}">
<output>🌿 Already on feature branch: story/{{story_key}}</output>
</check>
</check>
</step>
<step n="5" goal="Implement task following red-green-refactor cycle">
@ -327,6 +339,60 @@
<action>Execute enhanced definition-of-done validation</action>
<action>Update the story Status to: "review"</action>
<!-- Create Pull Request (provider-aware) -->
<check if="{{sprint_status}} file exists">
<action>Load {{sprint_status}} and extract tracking_system configuration</action>
<action>Set {{tracking_system}} from sprint-status.yaml (default: github-issues)</action>
</check>
<check if="{{sprint_status}} file does NOT exist OR tracking_system not configured">
<action>Set {{tracking_system}} = "none"</action>
</check>
<!-- GitHub PR creation -->
<check if="{{tracking_system}} == 'github-issues'">
<action>Stage and commit all changes: git add -A && git commit -m "{{story_key}}: Implementation complete"</action>
<action>Push branch: git push -u origin story/{{story_key}}</action>
<action>Prepare PR body with story summary and AC validation results</action>
<!-- Extract issue number for auto-close linking -->
<action>Extract issue_number from sprint-status.yaml tracking_ref for {{story_key}}</action>
<check if="issue_number exists">
<action>Append "Closes #{{issue_number}}" to PR body for auto-close on merge</action>
<action>Run: gh pr create --title "{{story_key}}: {{story_title}}" --body "{{pr_body}}\n\nCloses #{{issue_number}}" --base main</action>
</check>
<check if="issue_number does NOT exist">
<action>Run: gh pr create --title "{{story_key}}: {{story_title}}" --body "{{pr_body}}" --base main</action>
</check>
<action>Capture PR URL from command output</action>
<output>🔀 GitHub PR created: {{pr_url}}</output>
</check>
<!-- Azure DevOps PR creation -->
<check if="{{tracking_system}} == 'azure-devops'">
<action>Extract org_url and project from sprint-status.yaml</action>
<action>Stage and commit all changes: git add -A && git commit -m "{{story_key}}: Implementation complete"</action>
<action>Push branch: git push -u origin story/{{story_key}}</action>
<action>Prepare PR description with story summary and AC validation results</action>
<!-- Extract work item ID for linking -->
<action>Extract work_item_id from sprint-status.yaml tracking_ref for {{story_key}}</action>
<check if="work_item_id exists">
<action>Run: az repos pr create --title "{{story_key}}: {{story_title}}" --description "{{pr_description}}" --source-branch story/{{story_key}} --target-branch main --work-items {{work_item_id}} --org {{org_url}} --project {{project}}</action>
<output>🔀 Azure DevOps PR created and linked to Work Item #{{work_item_id}}</output>
</check>
<check if="work_item_id does NOT exist">
<action>Run: az repos pr create --title "{{story_key}}: {{story_title}}" --description "{{pr_description}}" --source-branch story/{{story_key}} --target-branch main --org {{org_url}} --project {{project}}</action>
<output>🔀 Azure DevOps PR created (no work item link)</output>
</check>
<action>Capture PR ID from command output</action>
</check>
<check if="{{tracking_system}} == 'none'">
<output> No tracking system configured - PR creation skipped</output>
</check>
<!-- Enhanced Definition of Done Validation -->
<action>Validate definition-of-done checklist with essential requirements:
- All tasks/subtasks marked complete with [x]

View File

@ -1356,6 +1356,61 @@ Retrospective document was saved successfully, but {sprint_status_file} may need
</step>
<step n="11.5" goal="Create retrospective tracking item in external system">
<critical>Create retrospective record in configured DevOps system</critical>
<action>Load {sprint_status_file} and extract tracking_system configuration</action>
<action>Set {{tracking_system}} from sprint-status.yaml (default: file-system)</action>
<check if="tracking_system == 'file-system' OR tracking_system not configured">
<output> Using file-system tracking only - no external retrospective item created</output>
<action>Skip external tracking creation</action>
</check>
<!-- GitHub Retrospective Issue -->
<check if="tracking_system == 'github-issues'">
<action>Extract repo and milestone from sprint-status.yaml</action>
<action>Prepare retrospective summary for issue body</action>
<action>Run: gh issue create --title "Retrospective: Epic {{epic_number}} - {{epic_title}}" --body "{{retrospective_summary}}\n\n## Action Items\n{{action_items_list}}\n\n## Key Insights\n{{key_insights}}\n\n**Retro Date:** {date}\n**Document:** {retrospectives_folder}/epic-{{epic_number}}-retro-{date}.md" --label "retrospective,epic-{{epic_number}}" --milestone "{{milestone}}"</action>
<action>Capture issue number</action>
<!-- Close epic issue if all stories done -->
<check if="all stories in epic {{epic_number}} are done">
<action>Extract epic_issue_{{epic_number}} from sprint-status.yaml</action>
<check if="epic issue exists">
<action>Run: gh issue close {{epic_issue_number}} --comment "🎉 Epic {{epic_number}} completed! See retrospective #{{retro_issue_number}}"</action>
<output>✅ Epic Issue #{{epic_issue_number}} closed</output>
</check>
</check>
<output>✅ GitHub Retrospective Issue created: #{{retro_issue_number}}</output>
</check>
<!-- Azure DevOps Retrospective Work Item -->
<check if="tracking_system == 'azure-devops'">
<action>Extract org_url, project, and iteration from sprint-status.yaml</action>
<action>Prepare retrospective summary for work item description</action>
<action>Run: az boards work-item create --title "Retrospective: Epic {{epic_number}} - {{epic_title}}" --type "Task" --description "{{retrospective_summary}}\n\n## Action Items\n{{action_items_list}}\n\n## Key Insights\n{{key_insights}}\n\n**Retro Date:** {date}" --iteration "{{iteration_path}}" --org {{org_url}} --project {{project}}</action>
<action>Capture work_item_id</action>
<action>Add tag: az boards work-item update --id {{work_item_id}} --fields "System.Tags=retrospective" --org {{org_url}}</action>
<!-- Link to epic and close if all stories done -->
<check if="all stories in epic {{epic_number}} are done">
<action>Extract epic_work_item_{{epic_number}} from sprint-status.yaml</action>
<check if="epic work item exists">
<action>Run: az boards work-item relation add --id {{work_item_id}} --relation-type "System.LinkTypes.Hierarchy-Reverse" --target-id {{epic_work_item_id}} --org {{org_url}}</action>
<action>Run: az boards work-item update --id {{epic_work_item_id}} --state "Closed" --org {{org_url}}</action>
<output>✅ Epic Work Item #{{epic_work_item_id}} closed</output>
</check>
</check>
<output>✅ Azure DevOps Retrospective Work Item created: #{{work_item_id}}</output>
</check>
</step>
<step n="12" goal="Final Summary and Handoff">
<output>

View File

@ -143,6 +143,66 @@ development_status:
<action>Ensure all items are ordered: epic, its stories, its retrospective, next epic...</action>
</step>
<step n="4.5" goal="Create milestone/iteration and epic items in external tracking system">
<critical>Create sprint tracking artifacts in configured DevOps system</critical>
<action>Check if tracking_system is configured in {status_file}</action>
<action>Extract tracking_system value (default: file-system)</action>
<check if="tracking_system == 'file-system' OR tracking_system not configured">
<output> Using file-system tracking only - no external DevOps integration</output>
<action>Skip external tracking creation</action>
</check>
<!-- GitHub Milestone and Epic Creation -->
<check if="tracking_system == 'github-issues'">
<action>Extract repo from sprint-status.yaml (format: owner/repo)</action>
<!-- Create Sprint Milestone -->
<action>Set milestone_title = "Sprint: {project_name} - Epic {{epic_num}}"</action>
<action>Set milestone_description = "Sprint milestone for {project_name} covering Epic {{epic_num}} stories"</action>
<action>Run: gh api repos/{repo}/milestones -f title="{{milestone_title}}" -f description="{{milestone_description}}"</action>
<action>Capture milestone number from response</action>
<action>Update {status_file} with milestone: {{milestone_title}}</action>
<output>✅ GitHub Milestone created: {{milestone_title}}</output>
<!-- Create Epic Issues -->
<action>For each epic found in epic files:</action>
<action>Run: gh issue create --title "Epic {{epic_num}}: {{epic_title}}" --body "{{epic_description}}" --label "epic,{project_key}"</action>
<action>Capture epic issue number</action>
<action>Store epic_issue_{{epic_num}} = issue number in sprint-status.yaml</action>
<output>✅ GitHub Epic Issue created: #{{epic_issue_number}} - Epic {{epic_num}}: {{epic_title}}</output>
</check>
<!-- Azure DevOps Iteration and Epic Creation -->
<check if="tracking_system == 'azure-devops'">
<action>Extract org_url and project from sprint-status.yaml</action>
<!-- Create Sprint Iteration -->
<action>Set iteration_name = "Sprint: {project_name} - Epic {{epic_num}}"</action>
<action>Calculate start_date = today</action>
<action>Calculate end_date = today + 2 weeks (default sprint length)</action>
<action>Run: az boards iteration project create --name "{{iteration_name}}" --path "\\{{project}}\\Iteration" --start-date "{{start_date}}" --finish-date "{{end_date}}" --org {{org_url}} --project {{project}}</action>
<action>Capture iteration path from response</action>
<action>Update {status_file} with iteration: {{iteration_name}}</action>
<output>✅ Azure DevOps Iteration created: {{iteration_name}}</output>
<!-- Create Epic Work Items -->
<action>For each epic found in epic files:</action>
<action>Run: az boards work-item create --title "Epic {{epic_num}}: {{epic_title}}" --type "Epic" --description "{{epic_description}}" --org {{org_url}} --project {{project}}</action>
<action>Capture work_item_id from response</action>
<action>Store epic_work_item_{{epic_num}} = work_item_id in sprint-status.yaml</action>
<output>✅ Azure DevOps Epic created: #{{work_item_id}} - Epic {{epic_num}}: {{epic_title}}</output>
</check>
<output>
**External Tracking Setup Complete:**
- Tracking System: {{tracking_system}}
- Milestone/Iteration: {{milestone_or_iteration_name}}
- Epic Items Created: {{epic_count}}
</output>
</step>
<step n="5" goal="Validate and report">
<action>Perform validation checks:</action>

View File

@ -31,15 +31,48 @@
# - Mark epic as 'in-progress' when starting work on its first story
# - SM typically creates next story ONLY after previous one is 'done' to incorporate learnings
# - Dev moves story to 'review', then Dev runs code-review (fresh context, ideally different LLM)
#
# PROVIDER CONFIGURATION:
# =======================
# For GitHub Issues:
# tracking_system: github-issues
# repo: owner/repo-name
# milestone: "Sprint: ProjectName - Epic 1" # Created by sprint-planning
#
# For Azure DevOps:
# tracking_system: azure-devops
# org_url: https://dev.azure.com/your-org
# project: YourProjectName
# iteration: "Sprint: ProjectName - Epic 1" # Created by sprint-planning
#
# For File-System Only (no external tracking):
# tracking_system: file-system
#
# TRACKING REFERENCES:
# ====================
# Each story can have a tracking_ref field added automatically:
# 1-1-user-authentication:
# status: ready-for-dev
# tracking_ref: 42 # GitHub issue number or Azure DevOps work item ID
#
# Epic tracking references:
# epic_issue_1: 40 # GitHub: epic issue number
# epic_work_item_1: 100 # Azure DevOps: epic work item ID
# EXAMPLE STRUCTURE (your actual epics/stories will replace these):
generated: 05-06-2-2025 21:30
project: My Awesome Project
project_key: jira-1234
tracking_system: file-system
tracking_system: github-issues
repo: owner/repo-name
milestone: "Sprint: My Awesome Project - Epic 1"
story_location: "{story_location}"
# Epic tracking references (auto-populated by sprint-planning)
epic_issue_1: 40
epic_issue_2: 41
development_status:
epic-1: backlog
1-1-user-authentication: done
@ -53,3 +86,8 @@ development_status:
2-2-chat-interface: backlog
2-3-llm-integration: backlog
epic-2-retrospective: optional
# Story tracking references (auto-populated by create-story)
tracking_refs:
1-1-user-authentication: 42
1-2-account-management: 43