Epic Close
Purpose
Complete an epic by conducting a retrospective, tagging the milestone, and updating tracking. No branch merge needed — stories already merged to the development branch during story-close.
Mastery Levels (ShuHaRi)
- Shu: Follow all steps, complete full retrospective template
- Ha: Adjust retrospective depth based on epic complexity
- Ri: Integrate with release workflows, automate metrics extraction
Context
When to use: All stories complete and merged to {dev_branch}. Ready to close the epic lifecycle.
When to skip: Epic abandoned (document why, update backlog as "Abandoned").
Inputs: Epic scope document, all story retrospectives, passing test suite.
Branch config: Read branches.development from .raise/manifest.yaml for {dev_branch}. Default: main.
Steps
Step 1: Verify Stories Complete
Check all stories are done in the epic scope document:
grep -E "^\s*-\s*\[ \]" "work/epics/e{N}-{name}/scope.md"
| Condition | Action |
|---|---|
| All stories checked | Continue |
| Incomplete stories | Complete them first or explicitly descope |
Step 2: Run Tests & Write Retrospective
Determine which test command to run using this priority chain:
- Check
.raise/manifest.yamlforproject.test_command— if set, use it directly (configuration over convention) - Detect language from
project.project_typein manifest, or scan file extensions of changed files (git diff --name-only) - Map language to default using the table below
| Language | Extensions | Default Test Command |
|---|---|---|
| Python | .py, .pyi |
uv run pytest --tb=short |
| TypeScript | .ts, .tsx |
npx vitest run or npm test |
| JavaScript | .js, .jsx |
npx vitest run or npm test |
| C# | .cs |
dotnet test --verbosity quiet |
| Go | .go |
go test ./... |
| PHP | .php |
vendor/bin/phpunit |
| Dart | .dart |
flutter test |
| Unknown | — | Ask developer |
The table is a fallback — project.test_command always wins when present.
Create retrospective at work/epics/e{N}-{name}/retrospective.md using templates/retrospective.md. Fill from story retrospectives and git history.
Step 3: Tag Epic Milestone
Tag the current {dev_branch} HEAD to mark epic completion:
git tag -a "epic/e{N}-complete" -m "Epic E{N}: {Epic Name} complete
Delivered: [key deliverables]
Stories: N stories
Co-Authored-By: Rai <rai@humansys.ai>"
Commit retrospective and any final artifacts:
git add -A
git commit -m "epic(e{N}): close with retrospective
Co-Authored-By: Rai <rai@humansys.ai>"
Step 4: Update Backlog & Context
- Mark epic complete via CLI:
- If Jira issue exists:
rai backlog transition {JIRA_KEY} "Done" -a jira - If no Jira key:
rai backlog search "summary ~ '{epic name}'" -a jirato find it, then transition
- If Jira issue exists:
- Update
CLAUDE.local.mdto reflect completion and next epic - Emit telemetry:
rai signal emit-work epic E{N} --event complete
Output
| Item | Destination |
|---|---|
| Retrospective | work/epics/e{N}-{name}/retrospective.md |
| Tag | epic/e{N}-complete on {dev_branch} |
| Backlog update | Tracker via rai backlog CLI |
| Context update | CLAUDE.local.md |
Quality Checklist
- All stories complete before closing (gate)
- Tests pass before closing
- Retrospective captures metrics, patterns, and process insights
- Epic milestone tagged on
{dev_branch} - Backlog updated via
rai backlog transitionCLI - No epic branch to clean up — epics are logical containers
- NEVER close without retrospective — learnings compound across epics
References
- Retrospective template:
templates/retrospective.md - Previous: All
/rai-story-closecompletions - Backlog:
rai backlogCLI - Next:
/rai-epic-designfor next epic