Files
gh-macroman5-claude-code-wo…/.claude/commands/review.md
2025-11-30 08:38:46 +08:00

1309 lines
35 KiB
Markdown

---
description: Review story and create PR with all committed tasks
argument-hint: "[STORY-ID or PATH]"
allowed-tools: Read, Bash, Task
model: claude-haiku-4-5-20251001
---
# Story Review Command
<command_purpose>
Review entire user story implementation and create single PR if all tasks are approved.
</command_purpose>
## Introduction
<role>Senior Story Review Architect with expertise in user story validation, acceptance criteria verification, and pull request automation</role>
## Prerequisites
<requirements>
- Git repository with story start tag (e.g., `story/US-3.4-start`)
- All tasks completed and tagged (e.g., `task/TASK-1.1-committed`)
- GitHub CLI (`gh`) installed and authenticated
- Story directory structure: `./project-management/US-STORY/US-X.Y-name/`
- Valid US-story.md file with all task references
- Clean working directory (no uncommitted changes)
</requirements>
## Input Variables
<story_file>$ARGUMENTS</story_file>
<base_branch>
Default: "main"
Can be overridden with: --base develop
</base_branch>
<draft_mode>
Default: "false"
Set to "true" with: --draft true
</draft_mode>
## Memory Graph Usage (Auto)
As you review a story, persist durable outcomes discovered in files and commit summaries:
- Use `mcp__memory__search_nodes``create_entities`/`add_observations``create_relations` to record owners, endpoints, repo links, and key decisions (dated).
The UserPromptSubmit and PostToolUse hooks auto-hint when these signals are detected. See `.claude/skills/memory-graph/`.
## Main Tasks
<critical_requirements>
**KEY REQUIREMENTS**:
1. Each completed US (user story) = 1 PR (not per task)
2. If review FAILS → Generate detailed REPORT file
3. Review against project standards AND enterprise guidelines
4. Use reviewer-story agent via Task tool
5. Parse agent JSON output programmatically
6. APPROVED → Auto-create PR with comprehensive body
7. CHANGES_REQUIRED → Generate US-X.Y-REVIEW-REPORT.md with fix guidance
</critical_requirements>
### Step 1: Load and Validate Story File
<critical_requirement>
MUST validate story file exists and contains all required sections before proceeding.
</critical_requirement>
<validation_tasks>
- [ ] Check USER-STORY.md exists at provided path
- [ ] Verify file contains required sections:
- ## User Story
- ## Acceptance Criteria
- ## Technical Requirements
- ## Tasks
- [ ] Parse all task references (TASK-X.Y format)
- [ ] Collect story metadata (ID, title, description)
</validation_tasks>
#### Load Story File
```bash
# Parse input - can be story ID (US-X.Y) or full path
story_input="$ARGUMENTS"
# Check if input is story ID format (US-X.Y)
if [[ "$story_input" =~ ^US-[0-9]+\.[0-9]+$ ]]; then
# Find story directory
story_dir=$(find ./project-management/US-STORY -name "${story_input}-*" -type d 2>/dev/null | head -1)
if [[ -z "$story_dir" ]]; then
echo "❌ Error: Story ${story_input} not found"
echo ""
echo "Available stories:"
ls -1d ./project-management/US-STORY/US-*/ 2>/dev/null || echo " (no stories found)"
echo ""
echo "Usage: /lazy story-review US-X.Y"
echo " or: /lazy story-review ./project-management/US-STORY/US-X.Y-name/US-story.md"
exit 1
fi
story_file="${story_dir}/US-story.md"
tasks_dir="${story_dir}/TASKS"
story_id=$(basename "$story_dir" | grep -oP '^US-\d+\.\d+')
else
# Assume it's a full path to US-story.md
story_file="$story_input"
# Validate story file exists
if [ ! -f "$story_file" ]; then
echo "❌ Error: Story file not found: $story_file"
echo ""
echo "Usage: /lazy story-review US-X.Y"
echo " or: /lazy story-review ./project-management/US-STORY/US-X.Y-name/US-story.md"
exit 1
fi
story_dir=$(dirname "$story_file")
tasks_dir="${story_dir}/TASKS"
story_id=$(basename "$story_dir" | grep -oP '^US-\d+\.\d+')
fi
# Validate tasks directory exists
if [ ! -d "$tasks_dir" ]; then
echo "❌ Error: Tasks directory not found: $tasks_dir"
echo "Story directory may be corrupt"
echo "Run /lazy create-feature to regenerate"
exit 1
fi
# Read story content
story_content=$(cat "$story_file")
story_title=$(grep -m1 "^# " "$story_file" | sed 's/^# //')
# Extract GitHub issue number from story file
story_github_issue=$(grep "GitHub Issue: #" "$story_file" | sed 's/.*#//' | head -1)
```
### Step 2: Verify Story State with Git Tags
<critical_requirement>
Use git tags to track story and task completion state. All tasks must be committed before review.
</critical_requirement>
<state_verification>
Story review uses git tags for state management:
**Story Start Tag:**
```bash
# Created by /lazy create-feature
git tag story/oauth2-start
```
**Task Completion Tags:**
```bash
# Created by /lazy task-exec after each task
git tag task/TASK-1.1-committed
git tag task/TASK-1.2-committed
git tag task/TASK-1.3-committed
```
**Verification:**
```bash
# Get all task tags
task_tags=$(git tag -l 'task/*-committed')
# Get story start tag
story_start=$(git tag -l 'story/*-start' | tail -1)
# Verify story start exists
if [ -z "$story_start" ]; then
echo "❌ Error: No story start tag found"
echo "Expected: story/{story-id}-start"
exit 1
fi
```
</state_verification>
#### Collect Task Tags
<task_collection>
- [ ] Get all task files from TASKS directory
- [ ] Get all task tags: `git tag -l 'task/*-committed'`
- [ ] Parse task IDs from tags (extract TASK-X.Y)
- [ ] Verify all tasks are committed
- [ ] Extract GitHub issue numbers from task files
- [ ] Block review if any task is incomplete
</task_collection>
```bash
# Collect all task files
task_files=$(ls ${tasks_dir}/TASK-*.md 2>/dev/null)
if [[ -z "$task_files" ]]; then
echo "❌ Error: No task files found in ${tasks_dir}"
echo "Story directory may be corrupt"
exit 1
fi
# Collect committed and pending tasks
committed_tasks=()
pending_tasks=()
task_github_issues=()
for task_file in $task_files; do
task_id=$(basename "$task_file" .md) # e.g., TASK-1.1
# Check if task is committed (git tag)
if git tag | grep -q "task/${task_id}-committed"; then
committed_tasks+=("$task_id")
# Extract GitHub issue number if present
github_issue=$(grep "GitHub Issue: #" "$task_file" | sed 's/.*#//' | head -1)
if [[ -n "$github_issue" ]]; then
task_github_issues+=("$task_id:$github_issue")
fi
else
pending_tasks+=("$task_id")
fi
done
# Verify all tasks are committed
if [[ ${#pending_tasks[@]} -gt 0 ]]; then
echo "❌ Error: Not all tasks are committed"
echo ""
echo "Pending tasks:"
for task in "${pending_tasks[@]}"; do
echo " - $task"
done
echo ""
echo "Next steps:"
echo " 1. Complete missing tasks: /lazy task-exec <TASK-ID>"
echo " 2. Re-run story review: /lazy story-review ${story_id}"
exit 1
fi
echo "✅ All ${#committed_tasks[@]} tasks are committed"
```
### Step 3: Collect All Commits Since Story Start
<commit_collection>
Get all commits between story start and current HEAD to include in PR.
</commit_collection>
```bash
# Get commits since story start
commits=$(git log "$story_start"..HEAD --oneline)
commit_count=$(echo "$commits" | wc -l)
# Verify there are commits
if [ $commit_count -eq 0 ]; then
echo "❌ Error: No commits found since story start"
echo "Story start: $story_start"
exit 1
fi
echo "📊 Found $commit_count commits since $story_start"
```
### Step 4: Collect Task Implementations
<implementation_collection>
For each completed task, collect:
- Task file content from TASKS directory
- Implementation files (from git diff)
- Test results (if available)
- GitHub issue links
</implementation_collection>
```bash
# For each task, collect implementation details
all_tasks_summary=""
for task_file in $task_files; do
task_id=$(basename "$task_file" .md)
task_title=$(grep -m1 "^# " "$task_file" | sed 's/^# //')
task_gh_issue=$(grep "GitHub Issue: #" "$task_file" | sed 's/.*#//' | head -1)
# Get files changed in task commits (approximate by commit messages)
task_commits=$(git log "$story_start"..HEAD --oneline --grep="$task_id")
commit_count=$(echo "$task_commits" | wc -l)
# Collect for review
all_tasks_summary="${all_tasks_summary}\n${task_id}: ${task_title}"
if [[ -n "$task_gh_issue" ]]; then
all_tasks_summary="${all_tasks_summary} (GH Issue #${task_gh_issue})"
fi
all_tasks_summary="${all_tasks_summary}\n Commits: ${commit_count}"
done
echo -e "📋 Task Summary:${all_tasks_summary}"
```
### Step 5: Run Test Suite (if tests exist)
<test_execution>
Run project tests if test runner is available.
</test_execution>
```bash
# Detect test framework and run tests
test_results=""
if [ -f "pytest.ini" ] || [ -f "pyproject.toml" ]; then
echo "🧪 Running pytest..."
test_results=$(pytest --tb=short 2>&1 || true)
elif [ -f "package.json" ]; then
if grep -q '"test"' package.json; then
echo "🧪 Running npm test..."
test_results=$(npm test 2>&1 || true)
fi
fi
```
### Step 6: Load Enterprise Standards
<standards_loading>
Load project and enterprise standards for compliance checking.
</standards_loading>
```bash
# Collect all applicable standards
standards_content=""
# 1. Load CLAUDE.md (project standards)
if [ -f "CLAUDE.md" ]; then
echo "📋 Loading project standards from CLAUDE.md..."
standards_content="${standards_content}\n## Project Standards (CLAUDE.md)\n\n"
standards_content="${standards_content}$(cat CLAUDE.md)"
fi
# 2. Load README.md (architecture decisions)
if [ -f "README.md" ]; then
echo "📋 Loading architecture decisions from README.md..."
standards_content="${standards_content}\n## Architecture Decisions (README.md)\n\n"
standards_content="${standards_content}$(cat README.md)"
fi
# 3. Load CONTRIBUTING.md (code standards)
if [ -f ".github/CONTRIBUTING.md" ]; then
echo "📋 Loading code standards from .github/CONTRIBUTING.md..."
standards_content="${standards_content}\n## Code Standards (CONTRIBUTING.md)\n\n"
standards_content="${standards_content}$(cat .github/CONTRIBUTING.md)"
elif [ -f "CONTRIBUTING.md" ]; then
echo "📋 Loading code standards from CONTRIBUTING.md..."
standards_content="${standards_content}\n## Code Standards (CONTRIBUTING.md)\n\n"
standards_content="${standards_content}$(cat CONTRIBUTING.md)"
fi
# 4. Load custom enterprise guidelines (if configured)
enterprise_standards_path="${LAZY_DEV_ENTERPRISE_STANDARDS:-}"
if [ -n "$enterprise_standards_path" ] && [ -f "$enterprise_standards_path" ]; then
echo "📋 Loading enterprise standards from ${enterprise_standards_path}..."
standards_content="${standards_content}\n## Enterprise Guidelines\n\n"
standards_content="${standards_content}$(cat "$enterprise_standards_path")"
fi
# If no standards found, use defaults
if [ -z "$standards_content" ]; then
echo "⚠️ No standards files found - using LAZY-DEV defaults"
standards_content="## Default Standards\n\n- Test coverage >80%\n- Type hints required\n- Documentation required for public APIs\n- OWASP Top 10 security compliance"
fi
echo "✅ Standards loaded successfully"
```
### Step 7: Invoke Story Review Agent
<critical_requirement>
Invoke the Story Review Agent via Task tool with complete context including enterprise standards.
</critical_requirement>
<agent_invocation>
The agent receives all story context, implementation details, and compliance standards.
Agent output format is JSON for programmatic processing.
</agent_invocation>
```bash
# Prepare context for agent
echo "🤖 Invoking Story Review Agent..."
# Read full story content
story_content_full=$(cat "$story_file")
# Get all task file contents
tasks_content=""
for task_file in $task_files; do
task_id=$(basename "$task_file" .md)
tasks_content="${tasks_content}\n### ${task_id}\n\n$(cat "$task_file")\n"
done
# Get git diff stats
files_changed=$(git diff --stat "$story_start"..HEAD)
files_changed_list=$(git diff --name-only "$story_start"..HEAD)
# Get test coverage if available
coverage_result=""
if command -v pytest &> /dev/null; then
coverage_result=$(pytest --cov --cov-report=term-missing 2>&1 || true)
fi
# Store agent context in temporary file for Task tool
cat > /tmp/story_review_context.md <<EOF
You are reviewing Story: ${story_id}
Story Title: ${story_title}
Story File: ${story_file}
Tasks Directory: ${tasks_dir}
Branch: $(git branch --show-current)
## Story Content
${story_content_full}
## All Tasks
${tasks_content}
## Commits (${commit_count} total)
${commits}
## Files Changed ($(echo "$files_changed_list" | wc -l) files)
${files_changed}
## Test Results
${test_results}
${coverage_result}
## Project Standards
${standards_content}
## Review Instructions
You MUST review against:
1. All acceptance criteria in the story file
2. Project standards from CLAUDE.md
3. Enterprise guidelines (if provided)
4. OWASP Top 10 security standards
5. Test coverage requirements (>80%)
6. Integration quality between all tasks
Return JSON output as specified in reviewer-story.md agent template.
EOF
echo "📄 Context prepared: /tmp/story_review_context.md"
```
**Invoke reviewer-story agent now:**
Use the Task tool to invoke `.claude/agents/reviewer-story.md` with the following variable substitutions:
- `story_id`: ${story_id}
- `story_file`: ${story_file}
- `tasks_dir`: ${tasks_dir}
- `branch_name`: $(git branch --show-current)
- `standards`: ${standards_content}
The agent will analyze all context and return JSON output with `status` field of either "APPROVED" or "REQUEST_CHANGES".
### Step 8: Process Review Results
<review_processing>
Parse JSON output from reviewer-story agent and take appropriate action.
</review_processing>
```bash
# Agent returns JSON - parse the status field
agent_status=$(echo "$agent_output" | jq -r '.status' 2>/dev/null || echo "UNKNOWN")
if [ "$agent_status" = "APPROVED" ]; then
echo "✅ Story review APPROVED"
echo ""
# Extract summary from agent output
agent_summary=$(echo "$agent_output" | jq -r '.summary' 2>/dev/null || echo "All checks passed")
echo "📋 Summary: ${agent_summary}"
echo ""
# Proceed to Step 9 (PR creation)
elif [ "$agent_status" = "REQUEST_CHANGES" ]; then
echo "❌ Story review FAILED - Changes Required"
echo ""
# Generate detailed review report
report_file="${story_dir}/${story_id}-review-report.md"
echo "📝 Generating review report: ${report_file}"
# Extract data from agent JSON output
agent_summary=$(echo "$agent_output" | jq -r '.summary' 2>/dev/null || echo "Review found issues")
# Count issues by severity
critical_count=$(echo "$agent_output" | jq '[.issues[] | select(.severity == "CRITICAL")] | length' 2>/dev/null || echo "0")
warning_count=$(echo "$agent_output" | jq '[.issues[] | select(.severity == "WARNING")] | length' 2>/dev/null || echo "0")
suggestion_count=$(echo "$agent_output" | jq '[.issues[] | select(.severity == "SUGGESTION")] | length' 2>/dev/null || echo "0")
total_issues=$((critical_count + warning_count + suggestion_count))
# Get task status summary
tasks_passed=$(echo "$agent_output" | jq '[.tasks_status[] | select(.status == "passed")] | length' 2>/dev/null || echo "0")
tasks_total=$(echo "$agent_output" | jq '.tasks_status | length' 2>/dev/null || echo "0")
# Generate comprehensive report
cat > "$report_file" <<REPORT_EOF
# Story Review Report: ${story_id}
**Status**: ❌ FAILED
**Reviewed**: $(date +"%Y-%m-%d %H:%M")
**Tasks**: ${tasks_passed}/${tasks_total} passed
## Summary
${total_issues} issues found preventing PR creation.
${agent_summary}
## Issues Found
$(echo "$agent_output" | jq -r '
if .issues and (.issues | length > 0) then
.issues | to_entries | map(
"### " + ((.key + 1) | tostring) + ". " +
(if .value.type then (.value.type | gsub("_"; " ") | ascii_upcase) else "Issue" end) +
" (" + (.value.file // "N/A") +
(if .value.line then ":" + (.value.line | tostring) else "" end) + ")\n" +
"- **Type**: " + (.value.type // "unknown") + "\n" +
"- **File**: " + (.value.file // "N/A") +
(if .value.line then ":" + (.value.line | tostring) else "" end) + "\n" +
"- **Issue**: " + .value.description + "\n" +
"- **Fix**: " + .value.fix + "\n"
) | join("\n")
else
"No specific issues documented."
end
')
## Tasks Status
$(echo "$agent_output" | jq -r '
if .tasks_status and (.tasks_status | length > 0) then
.tasks_status | map(
"- " + .task_id + ": " +
(if .status == "passed" then "✅ Passed"
elif .status == "failed" then "❌ Failed (" + (.issues_count | tostring) + " issues)"
elif .status == "warning" then "⚠️ Warning (" + (.issues_count | tostring) + " issues)"
else "⚠️ " + .status
end)
) | join("\n")
else
"- No task status available"
end
')
## Next Steps
Run: \`/lazy fix ${report_file}\`
Or manually fix and re-run: \`/lazy review @${story_file}\`
REPORT_EOF
echo "✅ Review report generated: ${report_file}"
echo ""
echo "Found:"
echo " - ${critical_count} CRITICAL issues"
echo " - ${warning_count} WARNING issues"
echo " - ${suggestion_count} SUGGESTIONS"
echo ""
echo "Next steps:"
echo " 1. Review report: cat ${report_file}"
echo " 2. Fix issues: /lazy fix ${report_file}"
echo " 3. Re-run review: /lazy review ${story_id}"
echo ""
# Exit with status 1 to indicate failure
exit 1
else
echo "❌ Error: Unknown review status from agent: ${agent_status}"
echo "Agent output:"
echo "$agent_output"
exit 1
fi
```
### Step 9: Create Pull Request (If APPROVED)
<pr_creation>
If review is approved, create a single PR containing all story commits with comprehensive summary.
</pr_creation>
<pr_requirements>
- One PR per user story (not per task)
- Includes all commits since story start tag
- References all task GitHub issues
- Includes test results and quality metrics
- Auto-closes related GitHub issues
</pr_requirements>
#### Prepare PR Body
```bash
# Generate comprehensive PR body
echo "📝 Generating PR body..."
# Extract test coverage percentage
test_coverage=$(echo "$coverage_result" | grep "^TOTAL" | awk '{print $NF}' || echo "N/A")
# Get acceptance criteria status
acceptance_criteria_list=$(cat "$story_file" | sed -n '/## Acceptance Criteria/,/##/p' | grep -E "^-.*" | sed 's/^- /✓ /')
# Extract agent summary
pr_summary=$(echo "$agent_output" | jq -r '.summary' 2>/dev/null || echo "Story implementation completed and reviewed")
cat > pr_body.md <<'PR_BODY'
# [FEATURE] ${story_title}
**Story ID**: ${story_id}
**Directory**: `${story_dir}`
$(if [[ -n "$story_github_issue" ]]; then echo "**GitHub Issue**: Closes #${story_github_issue}"; fi)
---
## Summary
${pr_summary}
---
## User Story
$(cat "${story_file}" | sed -n '/## User Story/,/##/p' | tail -n +2 | head -n -1)
---
## Acceptance Criteria
$(echo "$acceptance_criteria_list" | sed 's/^/✓ /')
---
## Tasks Completed
$(for task_file in ${tasks_dir}/TASK-*.md; do
task_id=$(basename "$task_file" .md)
task_title=$(grep "^# " "$task_file" | head -1 | sed 's/^# //')
task_gh_issue=$(grep "GitHub Issue: #" "$task_file" | sed 's/.*#//' | head -1)
if [[ -n "$task_gh_issue" ]]; then
echo "✓ [${task_id}] ${task_title} - Closes #${task_gh_issue}"
else
echo "✓ [${task_id}] ${task_title}"
fi
done)
---
## Commits
\`\`\`
$(git log --oneline ${story_start}..HEAD)
\`\`\`
**Total Commits**: ${commit_count}
---
## Quality Metrics
| Metric | Value |
|--------|-------|
| Files Changed | $(git diff --name-only "$story_start"..HEAD | wc -l) |
| Lines Added | $(git diff --stat "$story_start"..HEAD | tail -1 | grep -oP '\d+(?= insertion)' || echo "0") |
| Lines Removed | $(git diff --stat "$story_start"..HEAD | tail -1 | grep -oP '\d+(?= deletion)' || echo "0") |
| Test Coverage | ${test_coverage} |
| Tests Passing | $(echo "$test_results" | grep -oP '\d+(?= passed)' || echo "All") |
---
## Testing
\`\`\`
${test_results:-No tests run}
\`\`\`
$(if [[ -n "$coverage_result" ]]; then
echo "### Coverage Report"
echo "\`\`\`"
echo "$coverage_result" | head -20
echo "\`\`\`"
fi)
---
## Compliance & Quality Checks
### Story Review
✅ **APPROVED** by reviewer-story agent
### Project Standards
✅ Compliant with CLAUDE.md requirements
✅ Follows project architecture patterns
### Enterprise Guidelines
$(if [[ -n "$enterprise_standards_path" ]]; then
echo "✅ Compliant with enterprise standards: \`${enterprise_standards_path}\`"
else
echo "✅ Compliant with LAZY-DEV framework defaults"
fi)
### Security
✅ OWASP Top 10 compliance verified
✅ No security vulnerabilities detected
✅ Input validation implemented
✅ Authentication/authorization reviewed
### Code Quality
✅ Format: PASS (Black/Ruff)
✅ Lint: PASS (Ruff)
✅ Type: PASS (Mypy)
✅ Tests: PASS (Pytest)
### Documentation
✅ Public APIs documented
✅ README updated (if applicable)
✅ Inline comments for complex logic
---
## Integration Status
✅ All tasks integrate cohesively
✅ No conflicts between task implementations
✅ Data flows correctly between components
✅ No breaking changes to existing functionality
---
## Reviewer Notes
**Review Method**: LAZY-DEV-FRAMEWORK automated story review
**Review Agent**: `.claude/agents/reviewer-story.md`
**Review Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
**Summary**: ${pr_summary}
**Strengths**:
$(echo "$agent_output" | jq -r '.strengths // [] | if length > 0 then map("- " + .) | join("\n") else "- Comprehensive implementation\n- Strong test coverage\n- Clean code quality" end' 2>/dev/null || echo "- High-quality implementation")
---
## Related Issues
$(if [[ -n "$story_github_issue" ]]; then
echo "- Story: #${story_github_issue}"
fi)
$(for task_file in ${tasks_dir}/TASK-*.md; do
task_gh_issue=$(grep "GitHub Issue: #" "$task_file" | sed 's/.*#//' | head -1)
if [[ -n "$task_gh_issue" ]]; then
task_id=$(basename "$task_file" .md)
echo "- Task ${task_id}: #${task_gh_issue}"
fi
done)
---
🤖 Generated with [Claude Code](https://claude.com/claude-code) LAZY-DEV-FRAMEWORK
**Story**: ${story_id}
**Directory**: ${story_dir}
**Framework**: LAZY-DEV v1.0.0-alpha
PR_BODY
# Expand variables in PR body
eval "cat <<'EXPAND_PR_BODY' > pr_body_final.md
$(cat pr_body.md)
EXPAND_PR_BODY"
echo "✅ PR body generated: pr_body_final.md"
```
#### Create PR with gh CLI
```bash
# Determine if draft mode
draft_flag=""
if [ "$draft_mode" = "true" ]; then
draft_flag="--draft"
fi
# Create PR
echo "📦 Creating pull request..."
pr_url=$(gh pr create \
--title "[FEATURE] $story_title" \
--body-file pr_body_final.md \
--base "$base_branch" \
--label "story,automated,reviewed,story:$story_id" \
$draft_flag)
# Verify PR creation
if [ $? -eq 0 ]; then
# Get PR number
pr_number=$(gh pr list --head "$(git branch --show-current)" --json number --jq '.[0].number')
echo "✅ PR Created: $pr_url"
echo ""
echo "📁 Story: ${story_id}"
echo " Directory: ${story_dir}"
echo ""
echo "📦 PR Details:"
echo " Number: #${pr_number}"
echo " Title: [STORY] $story_title"
echo " Base: $base_branch"
echo " Commits: $commit_count"
echo ""
# Close GitHub issues
echo "🔗 Closing GitHub Issues:"
# Close main story issue
if [[ -n "$story_github_issue" ]]; then
gh issue close $story_github_issue --reason completed \
--comment "Completed in PR #${pr_number}" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✅ #${story_github_issue} - [STORY] ${story_title}"
fi
fi
# Close all task issues
for task_file in ${tasks_dir}/TASK-*.md; do
task_id=$(basename "$task_file" .md)
task_title=$(grep "^# " "$task_file" | head -1 | sed 's/^# //')
task_gh_issue=$(grep "GitHub Issue: #" "$task_file" | sed 's/.*#//' | head -1)
if [[ -n "$task_gh_issue" ]]; then
gh issue close $task_gh_issue --reason completed \
--comment "Completed in PR #${pr_number}" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✅ #${task_gh_issue} - [${task_id}] ${task_title}"
fi
fi
done
echo ""
echo "✅ All related issues closed"
echo "✅ Ready for merge"
else
echo "❌ Error: Failed to create PR"
echo "Check: gh auth status"
exit 1
fi
```
## Parallelization During Review
<parallelization>
While the story review is running or after it completes, you can run other commands in parallel if they are independent.
</parallelization>
### Commands That Can Run in Parallel
**During Review (While Waiting for Agent)**:
```bash
# 1. Cleanup unused code (runs on current branch)
/lazy cleanup --scope feature/US-X.Y
# 2. Generate documentation for the story
/lazy documentation --scope US-X.Y
# 3. Check memory graph for this story's entities
/lazy memory-check US-X.Y
```
**After Review Approval (Before PR Merge)**:
```bash
# 1. Start work on next independent story
/lazy create-feature "Next feature brief"
# 2. Update project documentation
/lazy documentation --scope project
# 3. Run refactoring on completed work
/lazy refactor --scope US-X.Y
```
### Commands That CANNOT Run in Parallel
**Blocked Until Review Completes**:
```bash
# ❌ Cannot run another story review simultaneously
/lazy story-review US-Y.Z # Wait for current review to finish
# ❌ Cannot re-execute tasks in the story being reviewed
/lazy task-exec TASK-X.Y # Wait until review fails or make changes after PR
# ❌ Cannot fix review issues until report is generated
/lazy story-fix-review US-X.Y-REVIEW-REPORT.md # Only after review fails
```
### Recommended Workflow
**Optimal Parallelization**:
```bash
# Terminal 1: Run story review
/lazy story-review US-3.4
# Terminal 2: While review is running, cleanup and document in parallel
/lazy cleanup --scope feature/US-3.4
/lazy documentation --scope US-3.4
# If review APPROVED:
# - PR is created automatically
# - GitHub issues are closed
# - Ready to start next story
# If review FAILED:
# - Fix issues: /lazy story-fix-review US-3.4-REVIEW-REPORT.md
# - Re-run: /lazy story-review US-3.4
```
## Integration with Other Commands
### Workflow Integration
**Complete Story Lifecycle**:
```
1. /lazy create-feature "Brief"
Creates: US-X.Y-name/US-story.md
Creates: TASKS/TASK-*.md
Creates: GitHub issues
Sets tag: story/US-X.Y-start
2. /lazy task-exec TASK-1.1
/lazy task-exec TASK-1.2
/lazy task-exec TASK-1.3
Each sets tag: task/TASK-X.Y-committed
Each implements and tests feature
3. /lazy story-review US-X.Y ← THIS COMMAND
Loads: All tasks, commits, standards
Invokes: reviewer-story agent
If APPROVED:
Creates: PR with full context
Closes: All GitHub issues
If CHANGES_REQUIRED:
Creates: US-X.Y-REVIEW-REPORT.md
Outputs: Fix guidance
4. If changes needed:
/lazy story-fix-review US-X.Y-REVIEW-REPORT.md
Routes issues to appropriate agents
Fixes critical/warning issues
Then re-run:
/lazy story-review US-X.Y
5. After PR merge:
/lazy cleanup --scope US-X.Y
/lazy documentation --scope US-X.Y
```
### Command Dependencies
**story-review depends on**:
- `/lazy create-feature` (creates story structure)
- `/lazy task-exec` (completes all tasks)
- Git tags: `story/*-start`, `task/*-committed`
- GitHub CLI: `gh` authenticated
**Commands that depend on story-review**:
- `/lazy story-fix-review` (processes review report)
- Subsequent `/lazy story-review` runs (after fixes)
**Independent parallel commands**:
- `/lazy cleanup` (code cleanup)
- `/lazy documentation` (docs generation)
- `/lazy memory-check` (graph queries)
- `/lazy create-feature` (new independent story)
## Error Handling & Recovery
### Error: Story file not found
```
❌ Error: Story US-3.4 not found
Available stories:
./project-management/US-STORY/US-1.1-user-authentication/
./project-management/US-STORY/US-2.3-payment-integration/
Usage: /lazy story-review US-X.Y
or: /lazy story-review ./project-management/US-STORY/US-X.Y-name/US-story.md
Recovery:
1. Check story ID: ls ./project-management/US-STORY/
2. Use correct story ID: /lazy story-review US-1.1
3. Or use full path to US-story.md
```
### Error: Task tags missing
```
❌ Error: Not all tasks are committed
Pending tasks:
- TASK-1.2
- TASK-1.3
Next steps:
1. Run git tag -l 'task/*' to see completed tasks
2. Execute missing tasks: /lazy task-exec TASK-1.2
3. Retry: /lazy story-review US-3.4
```
### Error: Story start tag missing
```
❌ Error: No story start tag found
Expected: story/US-X.Y-start
Recovery:
1. Check if create-feature was run: git tag -l 'story/*'
2. Create tag manually: git tag story/US-3.4-start $(git log --reverse --oneline | head -1 | cut -d' ' -f1)
3. Retry: /lazy story-review US-3.4
```
### Error: No commits found
```
❌ Error: No commits found since story start
Story start: story/oauth2-start
Recovery:
1. Verify story tag: git log story/oauth2-start
2. Check current branch: git branch --show-current
3. Ensure tasks were committed (not just completed)
```
### Error: Review changes needed
```
⚠️ Story review needs changes:
Critical Issues:
- TASK-1.3 validation: Missing edge case for declined cards
Location: src/payments/validator.py:45
Impact: Invalid cards may be processed
Next steps:
1. Fix validation in TASK-1.3
2. Re-run: /lazy task-exec TASK-1.3
3. Re-review: /lazy story-review US-3.4
```
### Error: Tasks directory not found
```
❌ Error: Tasks directory not found: ./project-management/US-STORY/US-3.4-oauth2/TASKS
Story directory may be corrupt
Run /lazy create-feature to regenerate
Recovery:
1. Verify story structure: ls -la ./project-management/US-STORY/US-3.4-*/
2. Check if TASKS directory exists
3. If missing, regenerate with /lazy create-feature
```
### Error: GitHub issue numbers missing
```
⚠️ Warning: Some task files don't have GitHub issue numbers
This may happen with older stories
Recovery:
1. Manually add GitHub issues
2. Or regenerate story with /lazy create-feature (includes gh issue creation)
3. Issues without numbers won't be auto-closed
```
### Error: gh CLI not found
```
❌ Error: gh command not found
Recovery:
1. Install GitHub CLI: https://cli.github.com
2. Authenticate: gh auth login
3. Verify: gh auth status
4. Retry: /lazy story-review US-3.4
```
### Error: gh auth failed
```
❌ Error: Not authenticated to GitHub
Recovery:
1. Run: gh auth login
2. Follow prompts to authorize
3. Verify: gh auth status
4. Retry: /lazy story-review US-3.4
```
### Error: Base branch doesn't exist
```
❌ Error: Base branch 'develop' not found
Recovery:
1. Check branches: git branch -a
2. Use correct base: /lazy story-review US-3.4 --base main
3. Or create branch: git branch develop
```
## Success Criteria
Story review is successful when:
- ✅ Story file is valid with all required sections
- ✅ Story directory structure is correct: `./project-management/US-STORY/US-X.Y-name/`
- ✅ All task files found in TASKS directory
- ✅ All task tags present: `git tag -l 'task/TASK-*-committed'`
- ✅ All commits collected since story start
- ✅ Review agent approved entire implementation
- ✅ All acceptance criteria validated
- ✅ Architecture, security, and testing validated
- ✅ PR created with title `[STORY] {story-name}`
- ✅ PR body contains full story + all tasks + test results + GitHub issues
- ✅ All commits included in PR history
- ✅ PR is on correct base branch
- ✅ All related GitHub issues closed (story + tasks)
## Example Usage
### Basic story review with story ID
```bash
/lazy story-review US-3.4
```
### Review with full path (backward compatible)
```bash
/lazy story-review ./project-management/US-STORY/US-3.4-oauth2-authentication/US-story.md
```
### Review on specific base branch
```bash
/lazy story-review US-3.4 --base develop
```
### Create as draft PR
```bash
/lazy story-review US-3.4 --draft true
```
### Verify story state before review
```bash
# List available stories
ls -1d ./project-management/US-STORY/US-*/
# Check what tasks are completed
git tag -l 'task/*'
# Check story commits
git log story/US-3.4-start..HEAD --oneline
# Then run review
/lazy story-review US-3.4
```
## Session Logging
All activities logged to `logs/<session-id>/story-review.json`:
```json
{
"story_file": "USER-STORY.md",
"story_id": "oauth2-auth",
"base_branch": "main",
"draft_mode": false,
"timestamp": "2025-10-25T15:45:00Z",
"stages": [
{
"stage": "load_story",
"status": "completed",
"story_title": "Build OAuth2 Authentication"
},
{
"stage": "verify_tags",
"status": "completed",
"all_present": true,
"task_count": 4
},
{
"stage": "collect_commits",
"status": "completed",
"commit_count": 7
},
{
"stage": "collect_implementations",
"status": "completed",
"files_changed": 15
},
{
"stage": "run_tests",
"status": "completed",
"test_result": "passed"
},
{
"stage": "review",
"status": "approved",
"agent": "story-review-agent"
},
{
"stage": "pr_creation",
"status": "completed",
"pr_url": "https://github.com/org/repo/pull/42",
"pr_number": 42
}
],
"result": {
"approved": true,
"pr_url": "https://github.com/org/repo/pull/42",
"tasks_included": ["TASK-1.1", "TASK-1.2", "TASK-1.3", "TASK-1.4"],
"commits_included": 7,
"files_changed": 15
}
}
```
## Integration with Other Commands
### After /lazy create-feature
```bash
# create-feature creates story directory and sets start tag
/lazy create-feature "Add OAuth2 authentication"
# Creates: ./project-management/US-STORY/US-3.4-oauth2-authentication/
# US-story.md, TASKS/TASK-*.md files
# GitHub issues for story and tasks
# Sets tag: story/US-3.4-start
# Execute all tasks
/lazy task-exec TASK-1.1
/lazy task-exec TASK-1.2
/lazy task-exec TASK-1.3
# Review and create PR (using story ID)
/lazy story-review US-3.4
```
### After /lazy task-exec
```bash
# Each task-exec sets a completion tag
/lazy task-exec TASK-1.1
# Sets tag: task/TASK-1.1-committed
# story-review uses these tags to verify completion
/lazy story-review US-3.4
```
### Workflow Summary
```
/lazy create-feature
Creates ./project-management/US-STORY/US-X.Y-name/
story/US-X.Y-start tag created
GitHub issues created
/lazy task-exec TASK-1.1 → task/TASK-1.1-committed
/lazy task-exec TASK-1.2 → task/TASK-1.2-committed
/lazy task-exec TASK-1.3 → task/TASK-1.3-committed
/lazy story-review US-X.Y
Verify all tags present
Collect all commits
Review Agent validation
Create PR (if approved)
Close GitHub issues (story + tasks)
```
## Notes
- Story review is **read-only** - no file modifications during review
- All validation happens through git tags (immutable markers)
- Review agent has complete context (story + tasks + implementations + tests)
- PR creation is automatic only if review is approved
- Draft mode allows additional manual review before merge
- Story state tracking enables iterative review (fix tasks, re-review)
- Accepts both story ID (US-X.Y) and full path for backward compatibility
- Automatically closes all related GitHub issues (story + all tasks)
- Works with new directory structure: `./project-management/US-STORY/US-X.Y-name/`
- Task files are individual TASK-*.md files in TASKS subdirectory
- GitHub issue numbers extracted from story and task files