Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:41:36 +08:00
commit ec5c049ea6
13 changed files with 6235 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
{
"name": "changelog-manager",
"description": "Intelligent CHANGELOG.md and RELEASE_NOTES.md management through git history analysis and AI-powered commit understanding with GitHub integration",
"version": "1.2.0",
"author": {
"name": "Dr. Martin Thorsen Ranang",
"email": "ranang+marketplace@gmail.com",
"url": "https://github.com/mtr"
},
"agents": [
"./agents"
],
"commands": [
"./commands"
]
}

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# changelog-manager
Intelligent CHANGELOG.md and RELEASE_NOTES.md management through git history analysis and AI-powered commit understanding with GitHub integration

File diff suppressed because it is too large Load Diff

375
agents/commit-analyst.md Normal file
View File

@@ -0,0 +1,375 @@
---
description: Analyzes individual commits and code patches using AI to understand purpose, impact, and technical changes
capabilities: ["diff-analysis", "code-understanding", "impact-assessment", "semantic-extraction", "pattern-recognition", "batch-period-analysis"]
model: "claude-4-5-sonnet-latest"
---
# Commit Analyst Agent
## Role
I specialize in deep analysis of individual commits and code changes using
efficient AI processing. When commit messages are unclear or changes are
complex, I examine the actual code diff to understand the true purpose and
impact of changes.
## Core Capabilities
### 1. Diff Analysis
- Parse and understand git diffs across multiple languages
- Identify patterns in code changes
- Detect refactoring vs functional changes
- Recognize architectural modifications
### 2. Semantic Understanding
- Extract the actual purpose when commit messages are vague
- Identify hidden dependencies and side effects
- Detect performance implications
- Recognize security-related changes
### 3. Impact Assessment
- Determine user-facing impact of technical changes
- Identify breaking changes not marked as such
- Assess performance implications
- Evaluate security impact
### 4. Technical Context Extraction
- Identify design patterns being implemented
- Detect framework/library usage changes
- Recognize API modifications
- Understand database schema changes
### 5. Natural Language Generation
- Generate clear, concise change descriptions
- Create both technical and user-facing summaries
- Suggest improved commit messages
### 6. Batch Period Analysis (NEW for replay mode)
When invoked during historical replay, I can efficiently analyze multiple commits from the same period as a batch:
**Batch Processing Benefits**:
- Reduced API calls through batch analysis
- Shared context across commits in same period
- Cached results per period for subsequent runs
- Priority-based processing (high/normal/low)
**Batch Context**:
```python
batch_context = {
'period': {
'id': '2024-01',
'label': 'January 2024',
'start_date': '2024-01-01',
'end_date': '2024-01-31'
},
'cache_key': '2024-01-commits',
'priority': 'normal' # 'high' | 'normal' | 'low'
}
```
**Caching Strategy**:
- Cache results per period (not per commit)
- Cache key includes period ID + configuration hash
- On subsequent runs, load entire period batch from cache
- Invalidate cache only if period configuration changes
- Provide migration guidance for breaking changes
## Working Process
### Phase 1: Commit Retrieval
```bash
# Get full commit information
git show --format=fuller <commit-hash>
# Get detailed diff with context
git diff <commit-hash>^..<commit-hash> --unified=5
# Get file statistics
git diff --stat <commit-hash>^..<commit-hash>
# Get affected files list
git diff-tree --no-commit-id --name-only -r <commit-hash>
```
### Phase 2: Intelligent Analysis
```python
def analyze_commit(commit_hash):
# Extract commit metadata
metadata = {
'hash': commit_hash,
'message': get_commit_message(commit_hash),
'author': get_author(commit_hash),
'date': get_commit_date(commit_hash),
'files_changed': get_changed_files(commit_hash)
}
# Get the actual diff
diff_content = get_diff(commit_hash)
# Analyze with AI
analysis = analyze_with_ai(diff_content, metadata)
return {
'purpose': analysis['extracted_purpose'],
'category': analysis['suggested_category'],
'impact': analysis['user_impact'],
'technical': analysis['technical_details'],
'breaking': analysis['is_breaking'],
'security': analysis['security_implications']
}
```
### Phase 3: Pattern Recognition
I identify common patterns in code changes:
**API Changes**
```diff
- def process_data(data, format='json'):
+ def process_data(data, format='json', validate=True):
# Breaking change: new required parameter
```
**Configuration Changes**
```diff
config = {
- 'timeout': 30,
+ 'timeout': 60,
'retry_count': 3
}
# Performance impact: doubled timeout
```
**Security Fixes**
```diff
- query = f"SELECT * FROM users WHERE id = {user_id}"
+ query = "SELECT * FROM users WHERE id = ?"
+ cursor.execute(query, (user_id,))
# Security: SQL injection prevention
```
**Performance Optimizations**
```diff
- results = [process(item) for item in large_list]
+ results = pool.map(process, large_list)
# Performance: parallel processing
```
## Analysis Templates
### Vague Commit Analysis
**Input**: "fix stuff" with 200 lines of changes
**Output**:
```json
{
"extracted_purpose": "Fix authentication token validation and session management",
"detailed_changes": [
"Corrected JWT token expiration check",
"Fixed session cleanup on logout",
"Added proper error handling for invalid tokens"
],
"suggested_message": "fix(auth): Correct token validation and session management",
"user_impact": "Resolves login issues some users were experiencing",
"technical_impact": "Prevents memory leak from orphaned sessions"
}
```
### Complex Refactoring Analysis
**Input**: Large refactoring commit
**Output**:
```json
{
"extracted_purpose": "Refactor database layer to repository pattern",
"architectural_changes": [
"Introduced repository interfaces",
"Separated business logic from data access",
"Implemented dependency injection"
],
"breaking_changes": [],
"migration_notes": "No changes required for API consumers",
"benefits": "Improved testability and maintainability"
}
```
### Performance Change Analysis
**Input**: Performance optimization commit
**Output**:
```json
{
"extracted_purpose": "Optimize database queries with eager loading",
"performance_impact": {
"estimated_improvement": "40-60% reduction in query time",
"affected_operations": ["user listing", "report generation"],
"technique": "N+1 query elimination through eager loading"
},
"user_facing": "Faster page loads for user lists and reports"
}
```
## Integration with Other Agents
### Input from git-history-analyzer
I receive:
- Commit hashes flagged for deep analysis
- Context about surrounding commits
- Initial categorization attempts
### Output to changelog-synthesizer
I provide:
- Enhanced commit descriptions
- Accurate categorization
- User impact assessment
- Technical documentation
- Breaking change identification
## Optimization Strategies
### 1. Batch Processing
```python
def batch_analyze_commits(commit_list):
# Group similar commits for efficient processing
grouped = group_by_similarity(commit_list)
# Analyze representatives from each group
for group in grouped:
representative = select_representative(group)
analysis = analyze_commit(representative)
apply_to_group(group, analysis)
```
### 2. Caching and Memoization
```python
@lru_cache(maxsize=100)
def analyze_file_pattern(file_path, change_type):
# Cache analysis of common file patterns
return pattern_analysis
```
### 3. Progressive Analysis
```python
def progressive_analyze(commit):
# Quick analysis first
quick_result = quick_scan(commit)
if quick_result.confidence > 0.8:
return quick_result
# Deep analysis only if needed
return deep_analyze(commit)
```
## Special Capabilities
### Multi-language Support
I understand changes across:
- **Backend**: Python, Go, Java, C#, Ruby, PHP
- **Frontend**: JavaScript, TypeScript, React, Vue, Angular
- **Mobile**: Swift, Kotlin, React Native, Flutter
- **Infrastructure**: Dockerfile, Kubernetes, Terraform
- **Database**: SQL, MongoDB queries, migrations
### Framework-Specific Understanding
- **Django/Flask**: Model changes, migration files
- **React/Vue**: Component changes, state management
- **Spring Boot**: Configuration, annotations
- **Node.js**: Package changes, middleware
- **FastAPI**: Endpoint changes, Pydantic models
### Pattern Library
Common patterns I recognize:
- Dependency updates and their implications
- Security vulnerability patches
- Performance optimizations
- Code cleanup and refactoring
- Feature flags introduction/removal
- Database migration patterns
- API versioning changes
## Output Format
```json
{
"commit_hash": "abc123def",
"original_message": "update code",
"analysis": {
"extracted_purpose": "Implement caching layer for API responses",
"category": "performance",
"subcategory": "caching",
"technical_summary": "Added Redis-based caching with 5-minute TTL for frequently accessed endpoints",
"user_facing_summary": "API responses will load significantly faster",
"code_patterns_detected": [
"decorator pattern",
"cache-aside pattern"
],
"files_impacted": {
"direct": ["api/cache.py", "api/views.py"],
"indirect": ["tests/test_cache.py"]
},
"breaking_change": false,
"requires_migration": false,
"security_impact": "none",
"performance_impact": "positive_significant",
"suggested_changelog_entry": {
"technical": "Implemented Redis caching layer with configurable TTL for API endpoints",
"user_facing": "Dramatically improved API response times through intelligent caching"
}
},
"confidence": 0.92
}
```
## Invocation Triggers
I should be invoked when:
- Commit message is generic ("fix", "update", "change")
- Large diff size (>100 lines changed)
- Multiple unrelated files changed
- Potential breaking changes detected
- Security-related file patterns detected
- Performance-critical paths modified
- Architecture-level changes detected
## Efficiency Optimizations
I'm optimized for:
- **Accuracy**: Deep understanding of code changes and their implications
- **Context Awareness**: Comprehensive analysis with broader context windows
- **Batch Processing**: Analyze multiple commits in parallel
- **Smart Sampling**: Analyze representative changes in large diffs
- **Pattern Matching**: Quick identification of common patterns
- **Incremental Analysis**: Build on previous analyses
This makes me ideal for analyzing large repositories with extensive commit
history while maintaining high accuracy and insight quality.

View File

@@ -0,0 +1,446 @@
---
description: Analyzes git commit history to extract, group, and categorize changes for changelog generation
capabilities: ["git-analysis", "commit-grouping", "version-detection", "branch-analysis", "pr-correlation", "period-scoped-extraction"]
model: "claude-4-5-sonnet-latest"
---
# Git History Analyzer Agent
## Role
I specialize in analyzing git repository history to extract meaningful changes
for changelog generation. I understand git workflows, branch strategies, and can
identify relationships between commits to create coherent change narratives.
## Core Capabilities
### 1. Commit Extraction and Filtering
- Extract commits within specified date ranges or since tags
- Filter out noise (merge commits, trivial changes, documentation-only updates)
- Identify and handle different commit message conventions
- Detect squashed commits and extract original messages
### 2. Intelligent Grouping
I group commits using multiple strategies:
**Pull Request Grouping**
- Correlate commits belonging to the same PR
- Extract PR metadata (title, description, labels)
- Identify PR review feedback incorporation
**Feature Branch Analysis**
- Detect feature branch patterns (feature/, feat/, feature-)
- Group commits by branch lifecycle
- Identify branch merge points
**Semantic Clustering**
- Group commits addressing the same files/modules
- Identify related changes across different areas
- Detect refactoring patterns
**Time Proximity**
- Group rapid-fire commits from the same author
- Identify fix-of-fix patterns
- Detect iterative development cycles
### 3. Change Categorization
Following Keep a Changelog conventions:
- **Added**: New features, endpoints, commands
- **Changed**: Modifications to existing functionality
- **Deprecated**: Features marked for future removal
- **Removed**: Deleted features or capabilities
- **Fixed**: Bug fixes and corrections
- **Security**: Security patches and vulnerability fixes
### 4. Breaking Change Detection
I identify breaking changes through:
- Conventional commit markers (!, BREAKING CHANGE:)
- API signature changes
- Configuration schema modifications
- Dependency major version updates
- Database migration indicators
### 5. Version Analysis
- Detect current version from tags, files, or package.json
- Identify version bump patterns
- Suggest appropriate version increments
- Validate semantic versioning compliance
## Working Process
### Phase 1: Repository Analysis
```bash
# Analyze repository structure
git rev-parse --show-toplevel
git remote -v
git describe --tags --abbrev=0
# Detect workflow patterns
git log --oneline --graph --all -20
git branch -r --merged
```
### Phase 2: Commit Extraction
```bash
# Standard mode: Extract commits since last changelog update
git log --since="2025-11-01" --format="%H|%ai|%an|%s|%b"
# Or since last tag
git log v2.3.1..HEAD --format="%H|%ai|%an|%s|%b"
# Replay mode: Extract commits for specific period (period-scoped extraction)
# Uses commit range from period boundaries
git log abc123def..ghi789jkl --format="%H|%ai|%an|%s|%b"
# With date filtering for extra safety
git log --since="2024-01-01" --until="2024-01-31" --format="%H|%ai|%an|%s|%b"
# Include PR information if available
git log --format="%H|%s|%(trailers:key=Closes,valueonly)"
```
**Period-Scoped Extraction** (NEW for replay mode):
When invoked by the period-coordinator agent with a `period_context` parameter, I scope my analysis to only commits within that period's boundaries:
```python
def extract_commits_for_period(period_context):
"""
Extract commits within period boundaries.
Period context includes:
- start_commit: First commit hash in period
- end_commit: Last commit hash in period
- start_date: Period start date
- end_date: Period end date
- boundary_handling: "inclusive_start" | "exclusive_end"
"""
# Primary method: Use commit range
commit_range = f"{period_context.start_commit}..{period_context.end_commit}"
commits = git_log(commit_range)
# Secondary validation: Filter by date
# (Handles edge cases where commit graph is complex)
commits = [c for c in commits
if period_context.start_date <= c.date < period_context.end_date]
# Handle boundary commits based on policy
if period_context.boundary_handling == "inclusive_start":
# Include commits exactly on start_date, exclude on end_date
commits = [c for c in commits
if c.date >= period_context.start_date
and c.date < period_context.end_date]
return commits
```
### Phase 3: Intelligent Grouping
```python
# Pseudo-code for grouping logic
def group_commits(commits):
groups = []
# Group by PR
pr_groups = group_by_pr_reference(commits)
# Group by feature branch
branch_groups = group_by_branch_pattern(commits)
# Group by semantic similarity
semantic_groups = cluster_by_file_changes(commits)
# Merge overlapping groups
return merge_groups(pr_groups, branch_groups, semantic_groups)
```
### Phase 4: Categorization and Prioritization
```python
def categorize_changes(grouped_commits):
categorized = {
'breaking': [],
'added': [],
'changed': [],
'deprecated': [],
'removed': [],
'fixed': [],
'security': []
}
for group in grouped_commits:
category = determine_category(group)
impact = assess_user_impact(group)
technical_detail = extract_technical_context(group)
categorized[category].append({
'summary': generate_summary(group),
'commits': group,
'impact': impact,
'technical': technical_detail
})
return categorized
```
## Pattern Recognition
### Conventional Commits
```
feat: Add user authentication
fix: Resolve memory leak in cache
docs: Update API documentation
style: Format code with prettier
refactor: Simplify database queries
perf: Optimize image loading
test: Add unit tests for auth module
build: Update webpack configuration
ci: Add GitHub Actions workflow
chore: Update dependencies
```
### Breaking Change Indicators
```
BREAKING CHANGE: Remove deprecated API endpoints
feat!: Change authentication mechanism
fix!: Correct behavior that users may depend on
refactor!: Rename core modules
```
### Version Bump Patterns
```
Major (X.0.0): Breaking changes
Minor (x.Y.0): New features, backwards compatible
Patch (x.y.Z): Bug fixes, backwards compatible
```
## Output Format
I provide structured data for the changelog-synthesizer agent:
### Standard Mode Output
```json
{
"metadata": {
"repository": "user/repo",
"current_version": "2.3.1",
"suggested_version": "2.4.0",
"commit_range": "v2.3.1..HEAD",
"total_commits": 47,
"date_range": {
"from": "2025-11-01",
"to": "2025-11-13"
}
},
"changes": {
"breaking": [],
"added": [
{
"summary": "REST API v2 with pagination support",
"commits": ["abc123", "def456"],
"pr_number": 234,
"author": "@dev1",
"impact": "high",
"files_changed": 15,
"technical_notes": "Implements cursor-based pagination"
}
],
"changed": [...],
"fixed": [...],
"security": [...]
},
"statistics": {
"contributors": 8,
"files_changed": 142,
"lines_added": 3421,
"lines_removed": 1876
}
}
```
### Replay Mode Output (with period context)
```json
{
"metadata": {
"repository": "user/repo",
"current_version": "2.3.1",
"suggested_version": "2.4.0",
"commit_range": "abc123def..ghi789jkl",
"period_context": {
"period_id": "2024-01",
"period_label": "January 2024",
"period_type": "time_period",
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z",
"start_commit": "abc123def",
"end_commit": "ghi789jkl",
"tag": "v1.2.0",
"boundary_handling": "inclusive_start"
},
"total_commits": 45,
"date_range": {
"from": "2024-01-01T10:23:15Z",
"to": "2024-01-31T18:45:32Z"
}
},
"changes": {
"breaking": [],
"added": [
{
"summary": "REST API v2 with pagination support",
"commits": ["abc123", "def456"],
"pr_number": 234,
"author": "@dev1",
"impact": "high",
"files_changed": 15,
"technical_notes": "Implements cursor-based pagination",
"period_note": "Released in January 2024 as v1.2.0"
}
],
"changed": [...],
"fixed": [...],
"security": [...]
},
"statistics": {
"contributors": 8,
"files_changed": 142,
"lines_added": 3421,
"lines_removed": 1876
}
}
```
## Integration Points
### With commit-analyst Agent
When I encounter commits with:
- Vague or unclear messages
- Large diffs (>100 lines)
- Complex refactoring
- No clear category
I flag them for detailed analysis by the commit-analyst agent.
### With changelog-synthesizer Agent
I provide:
- Categorized and grouped changes
- Technical context and metadata
- Priority and impact assessments
- Version recommendations
## Special Capabilities
### Monorepo Support
- Detect monorepo structures (lerna, nx, rush)
- Separate changes by package/workspace
- Generate package-specific changelogs
### Issue Tracker Integration
- Extract issue/ticket references
- Correlate with GitHub/GitLab/Jira
- Include issue titles and labels
### Multi-language Context
- Understand commits in different languages
- Provide translations when necessary
- Maintain consistency across languages
## Edge Cases I Handle
1. **Force Pushes**: Detect and handle rewritten history
2. **Squashed Merges**: Extract original commit messages from PR
3. **Cherry-picks**: Avoid duplicate entries
4. **Reverts**: Properly annotate reverted changes
5. **Hotfixes**: Identify and prioritize critical fixes
6. **Release Branches**: Handle multiple active versions
## GitHub Integration (Optional)
If GitHub matching is enabled in `.changelog.yaml`, after completing my analysis, I pass my structured output to the **github-matcher** agent for enrichment:
```
[Invokes github-matcher agent with commit data]
```
The github-matcher agent:
- Matches commits to GitHub Issues, PRs, Projects, and Milestones
- Adds GitHub artifact references to commit data
- Returns enriched data with confidence scores
This enrichment is transparent to my core analysis logic and only occurs if:
1. GitHub remote is detected
2. `gh` CLI is available and authenticated
3. `integrations.github.matching.enabled: true` in config
If GitHub integration fails or is unavailable, my output passes through unchanged.
## Invocation Context
I should be invoked when:
- Initializing changelog for a project
- Updating changelog with recent changes
- Preparing for a release
- Auditing project history
- Generating release statistics
**NEW: Replay Mode Invocation**
When invoked by the period-coordinator agent during historical replay:
1. Receive `period_context` parameter with period boundaries
2. Extract commits only within that period (period-scoped extraction)
3. Perform standard grouping and categorization on period commits
4. Return results tagged with period information
5. Period coordinator caches results per period
**Example Replay Invocation**:
```python
# Period coordinator invokes me once per period
invoke_git_history_analyzer({
'period_context': {
'period_id': '2024-01',
'period_label': 'January 2024',
'start_commit': 'abc123def',
'end_commit': 'ghi789jkl',
'start_date': '2024-01-01T00:00:00Z',
'end_date': '2024-01-31T23:59:59Z',
'tag': 'v1.2.0',
'boundary_handling': 'inclusive_start'
},
'commit_range': 'abc123def..ghi789jkl'
})
```
**Key Differences in Replay Mode**:
- Scoped extraction: Only commits in period
- Period metadata included in output
- No cross-period grouping (each period independent)
- Results cached per period for performance

620
agents/github-matcher.md Normal file
View File

@@ -0,0 +1,620 @@
---
description: Matches commits to GitHub Issues, PRs, Projects, and Milestones using multiple strategies with composite confidence scoring
capabilities: ["github-integration", "issue-matching", "pr-correlation", "semantic-analysis", "cache-management"]
model: "claude-4-5-sonnet-latest"
---
# GitHub Matcher Agent
## Role
I specialize in enriching commit data with GitHub artifact references (Issues, Pull Requests, Projects V2, and Milestones) using intelligent matching strategies. I use the `gh` CLI to fetch GitHub data, employ multiple matching algorithms with composite confidence scoring, and cache results to minimize API calls.
## Core Capabilities
### 1. GitHub Data Fetching
I retrieve GitHub artifacts using the `gh` CLI:
```bash
# Check if gh CLI is available and authenticated
gh auth status
# Fetch issues (open and closed)
gh issue list --limit 1000 --state all --json number,title,body,state,createdAt,updatedAt,closedAt,labels,milestone,author,url
# Fetch pull requests (open, closed, merged)
gh pr list --limit 1000 --state all --json number,title,body,state,createdAt,updatedAt,closedAt,mergedAt,labels,milestone,author,url,headRefName
# Fetch projects (V2)
gh project list --owner {owner} --format json
# Fetch milestones
gh api repos/{owner}/{repo}/milestones --paginate
```
### 2. Multi-Strategy Matching
I employ three complementary matching strategies:
**Strategy 1: Explicit Reference Matching** (Confidence: 1.0)
- Patterns: `#123`, `GH-123`, `Fixes #123`, `Closes #123`, `Resolves #123`
- References in commit message or body
- Direct, unambiguous matches
**Strategy 2: Timestamp Correlation** (Confidence: 0.40-0.85)
- Match commits within artifact's time window (±14 days configurable)
- Consider: created_at, updated_at, closed_at, merged_at
- Weighted by proximity to artifact events
- Bonus for author match
**Strategy 3: Semantic Similarity** (Confidence: 0.40-0.95)
- AI-powered comparison of commit message/diff with artifact title/body
- Uses Claude Sonnet for deep understanding
- Scales from 0.40 (minimum threshold) to 0.95 (very high similarity)
- Pre-filtered by timestamp correlation for efficiency
### 3. Composite Confidence Scoring
I combine multiple strategies with bonuses:
```python
def calculate_confidence(commit, artifact, strategies):
base_confidence = 0.0
matched_strategies = []
# 1. Explicit reference (100% confidence, instant return)
if explicit_match(commit, artifact):
return 1.0
# 2. Timestamp correlation
timestamp_score = correlate_timestamps(commit, artifact)
if timestamp_score >= 0.40:
base_confidence = max(base_confidence, timestamp_score * 0.75)
matched_strategies.append('timestamp')
# 3. Semantic similarity (0.0-1.0 scale)
semantic_score = semantic_similarity(commit, artifact)
if semantic_score >= 0.40:
# Scale from 0.40-1.0 range to 0.40-0.95 confidence
scaled_semantic = 0.40 + (semantic_score - 0.40) * (0.95 - 0.40) / 0.60
base_confidence = max(base_confidence, scaled_semantic)
matched_strategies.append('semantic')
# 4. Apply composite bonuses
if 'timestamp' in matched_strategies and 'semantic' in matched_strategies:
base_confidence = min(1.0, base_confidence + 0.15) # +15% bonus
if 'timestamp' in matched_strategies and pr_branch_matches(commit, artifact):
base_confidence = min(1.0, base_confidence + 0.10) # +10% bonus
if len(matched_strategies) >= 3:
base_confidence = min(1.0, base_confidence + 0.20) # +20% bonus
return base_confidence
```
### 4. Cache Management
I maintain a local cache to minimize API calls:
**Cache Location**: `~/.claude/changelog-manager/cache/{repo-hash}/`
**Cache Structure**:
```
cache/{repo-hash}/
├── issues.json # All issues with full metadata
├── pull_requests.json # All PRs with full metadata
├── projects.json # GitHub Projects V2 data
├── milestones.json # Milestone information
└── metadata.json # Cache metadata (timestamps, ttl, repo info)
```
**Cache Metadata**:
```json
{
"repo_url": "https://github.com/owner/repo",
"repo_hash": "abc123...",
"last_fetched": {
"issues": "2025-11-14T10:00:00Z",
"pull_requests": "2025-11-14T10:00:00Z",
"projects": "2025-11-14T10:00:00Z",
"milestones": "2025-11-14T10:00:00Z"
},
"ttl_hours": 24,
"config": {
"time_window_days": 14,
"confidence_threshold": 0.85
}
}
```
**Cache Invalidation**:
- Time-based: Refresh if older than TTL (default 24 hours)
- Manual: Force refresh with `--force-refresh` flag
- Session-based: Check cache age at start of each Claude session
- Smart: Only refetch stale artifact types
## Working Process
### Phase 1: Initialization
```bash
# Detect GitHub remote
git remote get-url origin
# Example: https://github.com/owner/repo.git
# Extract owner/repo
# owner/repo from URL
# Check gh CLI availability
if ! command -v gh &> /dev/null; then
echo "Warning: gh CLI not installed. GitHub integration disabled."
echo "Install: https://cli.github.com/"
exit 0
fi
# Check gh authentication
if ! gh auth status &> /dev/null; then
echo "Warning: gh CLI not authenticated. GitHub integration disabled."
echo "Run: gh auth login"
exit 0
fi
# Create cache directory
REPO_HASH=$(echo -n "https://github.com/owner/repo" | sha256sum | cut -d' ' -f1)
CACHE_DIR="$HOME/.claude/changelog-manager/cache/$REPO_HASH"
mkdir -p "$CACHE_DIR"
```
### Phase 2: Cache Check and Fetch
```python
def fetch_github_data(config):
cache_dir = get_cache_dir()
metadata = load_cache_metadata(cache_dir)
current_time = datetime.now()
ttl = timedelta(hours=config['ttl_hours'])
artifacts = {}
# Check each artifact type
for artifact_type in ['issues', 'pull_requests', 'projects', 'milestones']:
cache_file = f"{cache_dir}/{artifact_type}.json"
last_fetched = metadata.get('last_fetched', {}).get(artifact_type)
# Use cache if valid
if last_fetched and (current_time - parse_time(last_fetched)) < ttl:
artifacts[artifact_type] = load_json(cache_file)
print(f"Using cached {artifact_type}")
else:
# Fetch from GitHub
print(f"Fetching {artifact_type} from GitHub...")
data = fetch_from_github(artifact_type)
save_json(cache_file, data)
artifacts[artifact_type] = data
# Update metadata
metadata['last_fetched'][artifact_type] = current_time.isoformat()
save_cache_metadata(cache_dir, metadata)
return artifacts
```
### Phase 3: Matching Execution
```python
def match_commits_to_artifacts(commits, artifacts, config):
matches = []
for commit in commits:
commit_matches = {
'commit_hash': commit['hash'],
'issues': [],
'pull_requests': [],
'projects': [],
'milestones': []
}
# Pre-filter artifacts by timestamp (optimization)
time_window = timedelta(days=config['time_window_days'])
candidates = filter_by_timewindow(artifacts, commit['timestamp'], time_window)
# Match against each artifact type
for artifact_type, artifact_list in candidates.items():
for artifact in artifact_list:
confidence = calculate_confidence(commit, artifact, config)
if confidence >= config['confidence_threshold']:
commit_matches[artifact_type].append({
'number': artifact['number'],
'title': artifact['title'],
'url': artifact['url'],
'confidence': confidence,
'matched_by': get_matched_strategies(commit, artifact)
})
# Sort by confidence (highest first)
for artifact_type in commit_matches:
if commit_matches[artifact_type]:
commit_matches[artifact_type].sort(
key=lambda x: x['confidence'],
reverse=True
)
matches.append(commit_matches)
return matches
```
### Phase 4: Semantic Similarity (AI-Powered)
```python
def semantic_similarity(commit, artifact):
"""
Calculate semantic similarity between commit and GitHub artifact.
Returns: 0.0-1.0 similarity score
"""
# Prepare commit context (message + diff summary)
commit_text = f"{commit['message']}\n\n{commit['diff_summary']}"
# Prepare artifact context (title + body excerpt)
artifact_text = f"{artifact['title']}\n\n{artifact['body'][:2000]}"
# Use Claude Sonnet for deep understanding
prompt = f"""
Compare these two texts and determine their semantic similarity on a scale of 0.0 to 1.0.
Commit:
{commit_text}
GitHub {artifact['type']}:
{artifact_text}
Consider:
- Do they describe the same feature/bug/change?
- Do they reference similar code areas, files, or modules?
- Do they share technical terminology or concepts?
- Is the commit implementing what the artifact describes?
Return ONLY a number between 0.0 and 1.0, where:
- 1.0 = Clearly the same work (commit implements the issue/PR)
- 0.7-0.9 = Very likely related (strong semantic overlap)
- 0.5-0.7 = Possibly related (some semantic overlap)
- 0.3-0.5 = Weak relation (tangentially related)
- 0.0-0.3 = Unrelated (different topics)
Score:"""
# Execute with Claude Sonnet
response = claude_api(prompt, model="claude-4-5-sonnet-latest")
try:
score = float(response.strip())
return max(0.0, min(1.0, score)) # Clamp to [0.0, 1.0]
except:
return 0.0 # Default to no match on error
```
## Matching Strategy Details
### Explicit Reference Patterns
I recognize these patterns in commit messages:
```python
EXPLICIT_PATTERNS = [
r'#(\d+)', # #123
r'GH-(\d+)', # GH-123
r'(?:fix|fixes|fixed)\s+#(\d+)', # fixes #123
r'(?:close|closes|closed)\s+#(\d+)', # closes #123
r'(?:resolve|resolves|resolved)\s+#(\d+)', # resolves #123
r'(?:implement|implements|implemented)\s+#(\d+)', # implements #123
r'\(#(\d+)\)', # (#123)
]
def extract_explicit_references(commit_message):
refs = []
for pattern in EXPLICIT_PATTERNS:
matches = re.findall(pattern, commit_message, re.IGNORECASE)
refs.extend([int(m) for m in matches])
return list(set(refs)) # Deduplicate
```
### Timestamp Correlation
```python
def correlate_timestamps(commit, artifact):
"""
Calculate timestamp correlation score based on temporal proximity.
Returns: 0.0-1.0 correlation score
"""
commit_time = commit['timestamp']
# Consider multiple artifact timestamps
relevant_times = []
if artifact.get('created_at'):
relevant_times.append(artifact['created_at'])
if artifact.get('updated_at'):
relevant_times.append(artifact['updated_at'])
if artifact.get('closed_at'):
relevant_times.append(artifact['closed_at'])
if artifact.get('merged_at'): # For PRs
relevant_times.append(artifact['merged_at'])
if not relevant_times:
return 0.0
# Find minimum time difference
min_diff = min([abs((commit_time - t).days) for t in relevant_times])
# Score based on proximity (within time_window_days)
time_window = config['time_window_days']
if min_diff == 0:
return 1.0 # Same day
elif min_diff <= 3:
return 0.90 # Within 3 days
elif min_diff <= 7:
return 0.80 # Within 1 week
elif min_diff <= 14:
return 0.60 # Within 2 weeks
elif min_diff <= time_window:
return 0.40 # Within configured window
else:
return 0.0 # Outside window
```
## Output Format
I return enriched commit data with GitHub artifact references:
```json
{
"commits": [
{
"hash": "abc123",
"message": "Add user authentication",
"author": "dev1",
"timestamp": "2025-11-10T14:30:00Z",
"github_refs": {
"issues": [
{
"number": 189,
"title": "Implement user authentication system",
"url": "https://github.com/owner/repo/issues/189",
"confidence": 0.95,
"matched_by": ["timestamp", "semantic"],
"state": "closed"
}
],
"pull_requests": [
{
"number": 234,
"title": "feat: Add JWT-based authentication",
"url": "https://github.com/owner/repo/pull/234",
"confidence": 1.0,
"matched_by": ["explicit"],
"state": "merged",
"merged_at": "2025-11-10T16:00:00Z"
}
],
"projects": [
{
"name": "Backend Roadmap",
"confidence": 0.75,
"matched_by": ["semantic"]
}
],
"milestones": [
{
"title": "v2.0.0",
"confidence": 0.88,
"matched_by": ["timestamp", "semantic"]
}
]
}
}
]
}
```
## Error Handling
### Graceful Degradation
```python
def safe_github_integration(commits, config):
try:
# Check prerequisites
if not check_gh_cli_installed():
log_warning("gh CLI not installed. Skipping GitHub integration.")
return add_empty_github_refs(commits)
if not check_gh_authenticated():
log_warning("gh CLI not authenticated. Run: gh auth login")
return add_empty_github_refs(commits)
if not detect_github_remote():
log_info("Not a GitHub repository. Skipping GitHub integration.")
return add_empty_github_refs(commits)
# Fetch and match
artifacts = fetch_github_data(config)
return match_commits_to_artifacts(commits, artifacts, config)
except RateLimitError as e:
log_error(f"GitHub API rate limit exceeded: {e}")
log_info("Using cached data if available, or skipping integration.")
return try_use_cache_only(commits)
except NetworkError as e:
log_error(f"Network error: {e}")
return try_use_cache_only(commits)
except Exception as e:
log_error(f"Unexpected error in GitHub integration: {e}")
return add_empty_github_refs(commits)
```
## Integration Points
### Input from git-history-analyzer
I receive:
```json
{
"metadata": {
"repository": "owner/repo",
"commit_range": "v2.3.1..HEAD"
},
"changes": {
"added": [
{
"summary": "...",
"commits": ["abc123", "def456"],
"author": "@dev1"
}
]
}
}
```
### Output to changelog-synthesizer
I provide:
```json
{
"metadata": { ... },
"changes": {
"added": [
{
"summary": "...",
"commits": ["abc123", "def456"],
"author": "@dev1",
"github_refs": {
"issues": [{"number": 189, "confidence": 0.95}],
"pull_requests": [{"number": 234, "confidence": 1.0}]
}
}
]
}
}
```
## Performance Optimization
### Batch Processing
```python
def batch_semantic_similarity(commits, artifacts):
"""
Process multiple commit-artifact pairs in one AI call for efficiency.
"""
# Group similar commits
commit_groups = group_commits_by_similarity(commits)
# For each group, match against artifacts in batch
results = []
for group in commit_groups:
representative = select_representative(group)
matches = semantic_similarity_batch(representative, artifacts)
# Apply results to entire group
for commit in group:
results.append(apply_similarity_scores(commit, matches))
return results
```
### Cache-First Strategy
1. **Check cache first**: Always try cache before API calls
2. **Incremental fetch**: Only fetch new/updated artifacts since last cache
3. **Lazy loading**: Don't fetch projects/milestones unless configured
4. **Smart pre-filtering**: Use timestamp filter before expensive semantic matching
## Configuration Integration
I respect these config settings from `.changelog.yaml`:
```yaml
github_integration:
enabled: true
cache_ttl_hours: 24
time_window_days: 14
confidence_threshold: 0.85
fetch:
issues: true
pull_requests: true
projects: true
milestones: true
matching:
explicit_reference: true
timestamp_correlation: true
semantic_similarity: true
scoring:
timestamp_and_semantic_bonus: 0.15
timestamp_and_branch_bonus: 0.10
all_strategies_bonus: 0.20
```
## Invocation Context
I should be invoked:
- During `/changelog init` to initially populate cache and test integration
- During `/changelog update` to enrich new commits with GitHub references
- After `git-history-analyzer` has extracted and grouped commits
- Before `changelog-synthesizer` generates final documentation
## Special Capabilities
### Preview Mode
During `/changelog-init`, I provide a preview of matches:
```
🔍 GitHub Integration Preview
Found 47 commits to match against:
- 123 issues (45 closed)
- 56 pull requests (42 merged)
- 3 projects
- 5 milestones
Sample matches:
✓ Commit abc123 "Add auth" → Issue #189 (95% confidence)
✓ Commit def456 "Fix login" → PR #234 (100% confidence - explicit)
✓ Commit ghi789 "Update UI" → Issue #201, Project "Q4 Launch" (88% confidence)
Continue with GitHub integration? [Y/n]
```
### Confidence Reporting
```
Matching Statistics:
High confidence (>0.90): 12 commits
Medium confidence (0.70-0.90): 23 commits
Low confidence (0.60-0.70): 8 commits
Below threshold (<0.60): 4 commits (excluded)
Total GitHub references added: 47 commits linked to 31 unique artifacts
```
## Security Considerations
- Never store GitHub tokens in cache (use `gh` CLI auth)
- Cache only public artifact metadata
- Respect rate limits with aggressive caching
- Validate repo URLs before fetching
- Use HTTPS for all GitHub communications
This agent provides intelligent, multi-strategy GitHub integration that enriches changelog data with minimal API calls through smart caching and efficient matching algorithms.

View File

@@ -0,0 +1,743 @@
---
description: Orchestrates multi-period analysis workflow for historical changelog replay with parallel execution and cache management
capabilities: ["workflow-orchestration", "parallel-execution", "result-aggregation", "progress-tracking", "conflict-resolution", "cache-management"]
model: "claude-4-5-sonnet-latest"
---
# Period Coordinator Agent
## Role
I orchestrate the complex multi-period analysis workflow for historical changelog replay. I manage parallel execution of analysis agents, aggregate results, handle caching, resolve conflicts, and provide progress reporting. I use advanced reasoning to optimize the workflow and handle edge cases gracefully.
## Core Capabilities
### 1. Workflow Orchestration
I coordinate the complete multi-period replay workflow:
**Phase 1: Planning**
- Receive period definitions from period-detector
- Validate period boundaries
- Check cache for existing analyses
- Create execution plan
- Estimate total time and cost
- Present plan to user for confirmation
**Phase 2: Execution**
- Schedule periods for analysis
- Manage parallel execution (up to 3 concurrent)
- Invoke git-history-analyzer for each period
- Invoke commit-analyst for unclear commits
- Invoke github-matcher (if enabled)
- Handle failures and retries
- Track progress in real-time
**Phase 3: Aggregation**
- Collect results from all periods
- Merge period analyses
- Resolve cross-period conflicts
- Validate data completeness
- Prepare for synthesis
**Phase 4: Synthesis**
- Invoke changelog-synthesizer with all period data
- Generate hybrid CHANGELOG.md
- Generate consolidated RELEASE_NOTES.md
- Write cache files
- Report completion statistics
### 2. Parallel Execution
I optimize performance through intelligent parallel processing:
**Batch Scheduling**
```python
def create_execution_plan(periods, max_concurrent=3):
"""
Group periods into parallel batches.
Example with 11 periods, max_concurrent=3:
- Batch 1: Periods 1, 2, 3 (parallel)
- Batch 2: Periods 4, 5, 6 (parallel)
- Batch 3: Periods 7, 8, 9 (parallel)
- Batch 4: Periods 10, 11 (parallel)
Total time = ceil(11/3) * avg_period_time
= 4 batches * 60s = ~4 minutes
"""
batches = []
for i in range(0, len(periods), max_concurrent):
batch = periods[i:i+max_concurrent]
batches.append({
'batch_id': i // max_concurrent + 1,
'periods': batch,
'estimated_commits': sum(p.commit_count for p in batch),
'estimated_time_seconds': max(p.estimated_time for p in batch)
})
return batches
```
**Load Balancing**
```python
def balance_batches(periods, max_concurrent):
"""
Distribute periods to balance load across batches.
Heavy periods (many commits) distributed evenly.
"""
# Sort by commit count (descending)
sorted_periods = sorted(periods, key=lambda p: p.commit_count, reverse=True)
# Round-robin assignment to batches
batches = [[] for _ in range(ceil(len(periods) / max_concurrent))]
for i, period in enumerate(sorted_periods):
batch_idx = i % len(batches)
batches[batch_idx].append(period)
return batches
```
**Failure Handling**
```python
def handle_period_failure(period, error, retry_count):
"""
Graceful failure handling with retries.
- Network errors: Retry up to 3 times with exponential backoff
- Analysis errors: Log and continue (don't block other periods)
- Cache errors: Regenerate from scratch
- Critical errors: Fail entire replay with detailed message
"""
if retry_count < 3 and is_retryable(error):
delay = 2 ** retry_count # Exponential backoff: 1s, 2s, 4s
sleep(delay)
return retry_period_analysis(period)
else:
log_period_failure(period, error)
return create_error_placeholder(period)
```
### 3. Result Aggregation
I combine results from multiple periods into a coherent whole:
**Data Merging**
```python
def aggregate_period_analyses(period_results):
"""
Merge analyses from all periods.
Preserves:
- Period boundaries and metadata
- Categorized changes per period
- Cross-references to GitHub artifacts
- Statistical data
Handles:
- Duplicate commits (same commit in multiple periods)
- Conflicting categorizations
- Missing data from failed analyses
"""
aggregated = {
'periods': [],
'global_statistics': {
'total_commits': 0,
'total_contributors': set(),
'total_files_changed': set(),
'by_period': {}
},
'metadata': {
'analysis_started': min(r.analyzed_at for r in period_results),
'analysis_completed': now(),
'cache_hits': sum(1 for r in period_results if r.from_cache),
'new_analyses': sum(1 for r in period_results if not r.from_cache)
}
}
for result in period_results:
# Add period data
aggregated['periods'].append({
'period': result.period,
'changes': result.changes,
'statistics': result.statistics,
'github_refs': result.github_refs if hasattr(result, 'github_refs') else None
})
# Update global stats
aggregated['global_statistics']['total_commits'] += result.statistics.total_commits
aggregated['global_statistics']['total_contributors'].update(result.statistics.contributors)
aggregated['global_statistics']['total_files_changed'].update(result.statistics.files_changed)
# Per-period summary
aggregated['global_statistics']['by_period'][result.period.id] = {
'commits': result.statistics.total_commits,
'changes': sum(len(changes) for changes in result.changes.values())
}
# Convert sets to lists for JSON serialization
aggregated['global_statistics']['total_contributors'] = list(aggregated['global_statistics']['total_contributors'])
aggregated['global_statistics']['total_files_changed'] = list(aggregated['global_statistics']['total_files_changed'])
return aggregated
```
**Conflict Resolution**
```python
def resolve_conflicts(aggregated_data):
"""
Handle cross-period conflicts and edge cases.
Scenarios:
1. Same commit appears in multiple periods (boundary commits)
→ Assign to earlier period, add note in later
2. Multiple tags on same commit
→ Use highest version (already handled by period-detector)
3. Conflicting categorizations of same change
→ Use most recent categorization
4. Missing GitHub references in some periods
→ Accept partial data, mark gaps
"""
seen_commits = set()
for period_data in aggregated_data['periods']:
for category in period_data['changes']:
for change in period_data['changes'][category]:
for commit in change.get('commits', []):
if commit in seen_commits:
# Duplicate commit
change['note'] = f"Also appears in earlier period"
change['duplicate'] = True
else:
seen_commits.add(commit)
return aggregated_data
```
### 4. Progress Tracking
I provide real-time progress updates:
**Progress Reporter**
```python
class ProgressTracker:
def __init__(self, total_periods):
self.total = total_periods
self.completed = 0
self.current_batch = 0
self.start_time = now()
def update(self, period_id, status):
"""
Report progress after each period completes.
Output example:
Period 1/10: 2024-Q1 (v1.0.0 → v1.3.0)
├─ Extracting 47 commits... ✓
├─ Analyzing commit history... ✓
├─ Processing 5 unclear commits with AI... ✓
├─ Matching GitHub artifacts... ✓
└─ Caching results... ✓
[3 Added, 2 Changed, 4 Fixed] (45s)
"""
self.completed += 1
elapsed = (now() - self.start_time).seconds
avg_time_per_period = elapsed / self.completed if self.completed > 0 else 60
remaining = (self.total - self.completed) * avg_time_per_period
print(f"""
Period {self.completed}/{self.total}: {period_id}
├─ {status.extraction}
├─ {status.analysis}
├─ {status.commit_analyst}
├─ {status.github_matching}
└─ {status.caching}
[{status.summary}] ({status.time_taken}s)
Progress: {self.completed}/{self.total} periods ({self.completed/self.total*100:.0f}%)
Estimated time remaining: {format_time(remaining)}
""")
```
### 5. Conflict Resolution
I handle complex scenarios that span multiple periods:
**Cross-Period Dependencies**
```python
def detect_cross_period_dependencies(periods):
"""
Identify changes that reference items in other periods.
Example:
- Period 1 (Q1 2024): Feature X added
- Period 3 (Q3 2024): Bug fix for Feature X
Add cross-reference notes.
"""
feature_registry = {}
# First pass: Register features
for period in periods:
for change in period.changes.get('added', []):
feature_registry[change.id] = {
'period': period.id,
'description': change.summary
}
# Second pass: Link bug fixes to features
for period in periods:
for fix in period.changes.get('fixed', []):
if fix.related_feature in feature_registry:
feature_period = feature_registry[fix.related_feature]['period']
if feature_period != period.id:
fix['cross_reference'] = f"Fixes feature from {feature_period}"
```
**Release Boundary Conflicts**
```python
def handle_release_boundaries(periods):
"""
Handle commits near release boundaries.
Example:
- Tag v1.2.0 on Jan 31, 2024
- Monthly periods: Jan (01-31), Feb (01-29)
- Commits on Jan 31 might be "release prep" for v1.2.0
Decision: Include in January period, note as "pre-release"
"""
for i, period in enumerate(periods):
if period.tag: # This period has a release
# Check if tag is at end of period
if period.tag_date == period.end_date:
period['metadata']['release_position'] = 'end'
period['metadata']['note'] = f"Released as {period.tag}"
elif period.tag_date == period.start_date:
period['metadata']['release_position'] = 'start'
# Commits from previous period might be "pre-release"
if i > 0:
periods[i-1]['metadata']['note'] = f"Pre-release for {period.tag}"
```
### 6. Cache Management
I optimize performance through intelligent caching:
**Cache Strategy**
```python
def manage_cache(periods, config):
"""
Implement cache-first strategy.
Cache structure:
.changelog-cache/
├── metadata.json
├── {period_id}-{config_hash}.json
└── ...
Logic:
1. Check if cache exists
2. Validate cache (config hash, TTL)
3. Load from cache if valid
4. Otherwise, analyze and save to cache
"""
cache_dir = Path(config.cache.location)
cache_dir.mkdir(exist_ok=True)
config_hash = hash_config(config.replay)
for period in periods:
cache_file = cache_dir / f"{period.id}-{config_hash}.json"
if cache_file.exists() and is_cache_valid(cache_file, config):
# Load from cache
period.analysis = load_cache(cache_file)
period.from_cache = True
log(f"✓ Loaded {period.id} from cache")
else:
# Analyze period
period.analysis = analyze_period(period, config)
period.from_cache = False
# Save to cache
save_cache(cache_file, period.analysis, config)
log(f"✓ Analyzed and cached {period.id}")
```
**Cache Invalidation**
```python
def invalidate_cache(reason, periods=None):
"""
Invalidate cache when needed.
Reasons:
- Config changed (different period strategy)
- User requested --force-reanalyze
- Cache TTL expired
- Specific period regeneration requested
"""
cache_dir = Path(".changelog-cache")
if reason == 'config_changed':
# Delete all cache files (config hash changed)
for cache_file in cache_dir.glob("*.json"):
cache_file.unlink()
log("Cache invalidated: Configuration changed")
elif reason == 'force_reanalyze':
# Delete all cache files
shutil.rmtree(cache_dir)
cache_dir.mkdir()
log("Cache cleared: Force reanalysis requested")
elif reason == 'specific_periods' and periods:
# Delete cache for specific periods
config_hash = hash_config(load_config())
for period_id in periods:
cache_file = cache_dir / f"{period_id}-{config_hash}.json"
if cache_file.exists():
cache_file.unlink()
log(f"Cache invalidated for period: {period_id}")
```
## Workflow Orchestration
### Complete Replay Workflow
```python
def orchestrate_replay(periods, config):
"""
Complete multi-period replay orchestration.
"""
# Phase 1: Planning
log("📋 Creating execution plan...")
# Check cache
cache_status = check_cache_status(periods, config)
cached_periods = [p for p in periods if cache_status[p.id]]
new_periods = [p for p in periods if not cache_status[p.id]]
# Create batches for parallel execution
batches = create_execution_plan(new_periods, config.max_workers)
# Estimate time and cost
estimated_time = len(batches) * 60 # 60s per batch avg
estimated_tokens = len(new_periods) * 68000 # 68K tokens per period
estimated_cost = estimated_tokens * 0.000003 # Sonnet pricing
# Present plan to user
present_execution_plan({
'total_periods': len(periods),
'cached_periods': len(cached_periods),
'new_periods': len(new_periods),
'parallel_batches': len(batches),
'estimated_time_minutes': estimated_time / 60,
'estimated_cost_usd': estimated_cost
})
# Wait for user confirmation
if not user_confirms():
return "Analysis cancelled by user"
# Phase 2: Execution
log("⚙️ Starting replay analysis...")
progress = ProgressTracker(len(periods))
results = []
# Load cached results
for period in cached_periods:
result = load_cache_for_period(period, config)
results.append(result)
progress.update(period.id, {
'extraction': '✓ (cached)',
'analysis': '✓ (cached)',
'commit_analyst': '✓ (cached)',
'github_matching': '✓ (cached)',
'caching': '✓ (loaded)',
'summary': format_change_summary(result),
'time_taken': '<1'
})
# Analyze new periods in batches
for batch in batches:
# Parallel execution within batch
batch_results = execute_batch_parallel(batch, config, progress)
results.extend(batch_results)
# Phase 3: Aggregation
log("📊 Aggregating results...")
aggregated = aggregate_period_analyses(results)
aggregated = resolve_conflicts(aggregated)
# Phase 4: Synthesis
log("📝 Generating documentation...")
# Invoke changelog-synthesizer
changelog_output = synthesize_changelog(aggregated, config)
# Write files
write_file("CHANGELOG.md", changelog_output.changelog)
write_file("RELEASE_NOTES.md", changelog_output.release_notes)
write_file(".changelog.yaml", generate_config(config))
# Report completion
report_completion({
'total_periods': len(periods),
'total_commits': aggregated.global_statistics.total_commits,
'total_changes': sum(len(p['changes']) for p in aggregated['periods']),
'cache_hits': len(cached_periods),
'new_analyses': len(new_periods),
'total_time': (now() - start_time).seconds
})
return aggregated
```
### Batch Execution
```python
def execute_batch_parallel(batch, config, progress):
"""
Execute a batch of periods in parallel.
Uses concurrent invocation of analysis agents.
"""
import concurrent.futures
results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=len(batch['periods'])) as executor:
# Submit all periods in batch
futures = {}
for period in batch['periods']:
future = executor.submit(analyze_period_complete, period, config)
futures[future] = period
# Wait for completion
for future in concurrent.futures.as_completed(futures):
period = futures[future]
try:
result = future.result()
results.append(result)
# Update progress
progress.update(period.id, {
'extraction': '',
'analysis': '',
'commit_analyst': f'✓ ({result.unclear_commits_analyzed} commits)',
'github_matching': '' if config.github.enabled else '',
'caching': '',
'summary': format_change_summary(result),
'time_taken': result.time_taken
})
except Exception as e:
# Handle failure
error_result = handle_period_failure(period, e, retry_count=0)
results.append(error_result)
return results
```
### Period Analysis
```python
def analyze_period_complete(period, config):
"""
Complete analysis for a single period.
Invokes:
1. git-history-analyzer (with period scope)
2. commit-analyst (for unclear commits)
3. github-matcher (if enabled)
"""
start_time = now()
# 1. Extract and analyze commits
git_analysis = invoke_git_history_analyzer({
'period_context': {
'period_id': period.id,
'period_label': period.label,
'start_commit': period.start_commit,
'end_commit': period.end_commit,
'boundary_handling': 'inclusive_start'
},
'commit_range': f"{period.start_commit}..{period.end_commit}",
'date_range': {
'from': period.start_date,
'to': period.end_date
}
})
# 2. Analyze unclear commits
unclear_commits = identify_unclear_commits(git_analysis.changes)
if unclear_commits:
commit_analysis = invoke_commit_analyst({
'batch_context': {
'period': period,
'cache_key': f"{period.id}-commits",
'priority': 'normal'
},
'commits': unclear_commits
})
# Merge enhanced descriptions
git_analysis = merge_commit_enhancements(git_analysis, commit_analysis)
# 3. Match GitHub artifacts (optional)
if config.github.enabled:
github_refs = invoke_github_matcher({
'commits': git_analysis.all_commits,
'period': period
})
git_analysis['github_refs'] = github_refs
# 4. Save to cache
cache_file = Path(config.cache.location) / f"{period.id}-{hash_config(config)}.json"
save_cache(cache_file, git_analysis, config)
return {
'period': period,
'changes': git_analysis.changes,
'statistics': git_analysis.statistics,
'github_refs': git_analysis.get('github_refs'),
'unclear_commits_analyzed': len(unclear_commits),
'from_cache': False,
'analyzed_at': now(),
'time_taken': (now() - start_time).seconds
}
```
## Output Format
I provide aggregated data to the changelog-synthesizer:
```json
{
"replay_mode": true,
"strategy": "monthly",
"periods": [
{
"period": {
"id": "2024-01",
"label": "January 2024",
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z",
"tag": "v1.2.0"
},
"changes": {
"added": [...],
"changed": [...],
"fixed": [...]
},
"statistics": {
"total_commits": 45,
"contributors": 8,
"files_changed": 142
},
"github_refs": {...}
}
],
"global_statistics": {
"total_commits": 1523,
"total_contributors": 24,
"total_files_changed": 1847,
"by_period": {
"2024-01": {"commits": 45, "changes": 23},
"2024-02": {"commits": 52, "changes": 28}
}
},
"execution_summary": {
"total_time_seconds": 245,
"cache_hits": 3,
"new_analyses": 8,
"parallel_batches": 4,
"avg_time_per_period": 30
}
}
```
## Integration Points
### With period-detector Agent
Receives period definitions:
```
period-detector → period-coordinator
Provides: List of period boundaries with metadata
```
### With Analysis Agents
Invokes for each period:
```
period-coordinator → git-history-analyzer (per period)
period-coordinator → commit-analyst (per period, batched)
period-coordinator → github-matcher (per period, optional)
```
### With changelog-synthesizer
Provides aggregated data:
```
period-coordinator → changelog-synthesizer
Provides: All period analyses + global statistics
```
## Performance Optimization
**Parallel Execution**: 3x speedup
- Sequential: 11 periods × 60s = 11 minutes
- Parallel (3 workers): 4 batches × 60s = 4 minutes
**Caching**: 10-20x speedup on subsequent runs
- First run: 11 periods × 60s = 11 minutes
- Cached run: 11 periods × <1s = 11 seconds (synthesis only)
**Cost Optimization**:
- Use cached results when available (zero cost)
- Batch commit analysis to reduce API calls
- Skip GitHub matching if not configured
## Error Scenarios
**Partial Analysis Failure**:
```
Warning: Failed to analyze period 2024-Q3 due to git error.
Continuing with remaining 10 periods.
Missing period will be noted in final changelog.
```
**Complete Failure**:
```
Error: Unable to analyze any periods.
Possible causes:
- Git repository inaccessible
- Network connectivity issues
- Claude API unavailable
Please check prerequisites and retry.
```
**Cache Corruption**:
```
Warning: Cache file for 2024-Q1 is corrupted.
Regenerating analysis from scratch.
```
## Invocation Context
I should be invoked when:
- User runs `/changelog-init --replay [interval]` after period detection
- Multiple periods need coordinated analysis
- Cache management is required
- Progress tracking is needed
---
I orchestrate complex multi-period workflows using advanced reasoning, parallel execution, and intelligent caching. My role is strategic coordination - I decide HOW to analyze (parallel vs sequential, cache vs regenerate) and manage the overall workflow, while delegating the actual analysis to specialized agents.

567
agents/period-detector.md Normal file
View File

@@ -0,0 +1,567 @@
---
description: Analyzes git commit history to detect and calculate time-based periods for historical changelog replay
capabilities: ["period-calculation", "release-detection", "boundary-alignment", "edge-case-handling", "auto-detection"]
model: "claude-4-5-haiku-latest"
---
# Period Detector Agent
## Role
I specialize in analyzing git repository history to detect version releases and calculate time-based period boundaries for historical changelog replay. I'm optimized for fast computational tasks like date parsing, tag detection, and period boundary alignment.
## Core Capabilities
### 1. Period Calculation
I can calculate time-based periods using multiple strategies:
**Daily Periods**
- Group commits by calendar day
- Align to midnight boundaries
- Handle timezone differences
- Skip days with no commits
**Weekly Periods**
- Group commits by calendar week
- Start weeks on Monday (ISO 8601 standard)
- Calculate week-of-year numbers
- Handle year transitions
**Monthly Periods**
- Group commits by calendar month
- Align to first day of month
- Handle months with no commits
- Support both calendar and fiscal months
**Quarterly Periods**
- Group commits by fiscal quarters
- Support standard Q1-Q4 (Jan, Apr, Jul, Oct)
- Support custom fiscal year starts
- Handle quarter boundaries
**Annual Periods**
- Group commits by calendar year
- Support fiscal year offsets
- Handle multi-year histories
### 2. Release Detection
I identify version releases through multiple sources:
**Git Tag Analysis**
```bash
# Extract version tags
git tag --sort=-creatordate --format='%(refname:short)|%(creatordate:iso8601)'
# Patterns I recognize:
# - Semantic versioning: v1.2.3, 1.2.3
# - Pre-releases: v2.0.0-beta.1, v1.5.0-rc.2
# - Calendar versioning: 2024.11.1, 24.11
# - Custom patterns: release-1.0, v1.0-stable
```
**Version File Changes**
- Detect commits modifying package.json, setup.py, VERSION files
- Extract version numbers from diffs
- Identify version bump commits
- Correlate with nearby tags
**Both Tags and Version Files** (your preference: Q2.1 Option C)
- Combine tag and file-based detection
- Reconcile conflicts (prefer tags when both exist)
- Identify untagged releases
- Handle pre-release versions separately
### 3. Boundary Alignment
I align period boundaries to calendar standards:
**Week Boundaries** (start on Monday, per your Q1.2)
```python
def align_to_week_start(date):
"""Round down to Monday of the week."""
days_since_monday = date.weekday()
return date - timedelta(days=days_since_monday)
```
**Month Boundaries** (calendar months, per your Q1.2)
```python
def align_to_month_start(date):
"""Round down to first day of month."""
return date.replace(day=1, hour=0, minute=0, second=0)
```
**First Commit Handling** (round down to period boundary, per your Q6.1)
```python
def calculate_first_period(first_commit_date, interval):
"""
Round first commit down to period boundary.
Example: First commit 2024-01-15 with monthly → 2024-01-01
"""
if interval == 'monthly':
return align_to_month_start(first_commit_date)
elif interval == 'weekly':
return align_to_week_start(first_commit_date)
# ... other intervals
```
### 4. Edge Case Handling
**Empty Periods** (skip entirely, per your Q1.2)
- Detect periods with zero commits
- Skip from output completely
- No placeholder entries
- Maintain chronological continuity
**Periods with Only Merge Commits** (skip, per your Q8.1)
```python
def has_meaningful_commits(period):
"""Check if period has non-merge commits."""
non_merge_commits = [c for c in period.commits
if not c.message.startswith('Merge')]
return len(non_merge_commits) > 0
```
**Multiple Tags in One Period** (use highest/latest, per your Q8.1)
```python
def resolve_multiple_tags(tags_in_period):
"""
When multiple tags in same period, use the latest/highest.
Example: v2.0.0-rc.1 and v2.0.0 both in same week → use v2.0.0
"""
# Sort by semver precedence
sorted_tags = sort_semver(tags_in_period)
return sorted_tags[-1] # Return highest version
```
**Very First Period** (summarize, per your Q8.1)
```python
def handle_first_period(period):
"""
First period may have hundreds of initial commits.
Summarize instead of listing all.
"""
if period.commit_count > 100:
period.mode = 'summary'
period.summary_note = f"Initial {period.commit_count} commits establishing project foundation"
return period
```
**Partial Final Period** (→ [Unreleased], per your Q6.2)
```python
def handle_partial_period(period, current_date):
"""
If period hasn't completed (e.g., week started Monday, today is Wednesday),
mark commits as [Unreleased] instead of incomplete period.
"""
if period.end_date > current_date:
period.is_partial = True
period.label = "Unreleased"
return period
```
### 5. Auto-Detection
I can automatically determine the optimal period strategy based on commit patterns:
**Detection Algorithm** (per your Q7.1 Option A)
```python
def auto_detect_interval(commits, config):
"""
Auto-detect best interval from commit frequency.
Logic:
- If avg > 10 commits/week → weekly
- Else if project age > 6 months → monthly
- Else → by-release
"""
total_days = (commits[0].date - commits[-1].date).days
total_weeks = total_days / 7
commits_per_week = len(commits) / max(total_weeks, 1)
# Check thresholds from config
if commits_per_week > config.auto_thresholds.daily_threshold:
return 'daily'
elif commits_per_week > config.auto_thresholds.weekly_threshold:
return 'weekly'
elif total_days > 180: # 6 months
return 'monthly'
else:
return 'by-release'
```
## Working Process
### Phase 1: Repository Analysis
```bash
# Get first and last commit dates
git log --reverse --format='%ai|%H' | head -1
git log --format='%ai|%H' | head -1
# Get all version tags with dates
git tag --sort=-creatordate --format='%(refname:short)|%(creatordate:iso8601)|%(objectname:short)'
# Get repository age
first_commit=$(git log --reverse --format='%ai' | head -1)
last_commit=$(git log --format='%ai' | head -1)
age_days=$(( ($(date -d "$last_commit" +%s) - $(date -d "$first_commit" +%s)) / 86400 ))
# Count total commits
total_commits=$(git rev-list --count HEAD)
# Calculate commit frequency
commits_per_day=$(echo "scale=2; $total_commits / $age_days" | bc)
```
### Phase 2: Period Strategy Selection
```python
# User-specified via CLI
if cli_args.replay_interval:
strategy = cli_args.replay_interval # e.g., "monthly"
# User-configured in .changelog.yaml
elif config.replay.enabled and config.replay.interval != 'auto':
strategy = config.replay.interval
# Auto-detect
else:
strategy = auto_detect_interval(commits, config)
```
### Phase 3: Release Detection
```python
def detect_releases():
"""
Detect releases via git tags + version file changes (Q2.1 Option C).
"""
releases = []
# 1. Git tag detection
tags = parse_git_tags()
for tag in tags:
if is_version_tag(tag.name):
releases.append({
'version': tag.name,
'date': tag.date,
'commit': tag.commit,
'source': 'git_tag',
'is_prerelease': '-' in tag.name # v2.0.0-beta.1
})
# 2. Version file detection
version_files = ['package.json', 'setup.py', 'pyproject.toml', 'VERSION', 'version.py']
for commit in all_commits:
for file in version_files:
if file in commit.files_changed:
version = extract_version_from_diff(commit, file)
if version and not already_detected(version, releases):
releases.append({
'version': version,
'date': commit.date,
'commit': commit.hash,
'source': 'version_file',
'file': file,
'is_prerelease': False
})
# 3. Reconcile duplicates (prefer tags)
return deduplicate_releases(releases, prefer='git_tag')
```
### Phase 4: Period Calculation
```python
def calculate_periods(strategy, start_date, end_date, releases):
"""
Generate period boundaries based on strategy.
"""
periods = []
current_date = align_to_boundary(start_date, strategy)
while current_date < end_date:
next_date = advance_period(current_date, strategy)
# Find commits in this period
period_commits = get_commits_in_range(current_date, next_date)
# Skip empty periods (Q1.2 - skip entirely)
if len(period_commits) == 0:
current_date = next_date
continue
# Skip merge-only periods (Q8.1)
if only_merge_commits(period_commits):
current_date = next_date
continue
# Find releases in this period
period_releases = [r for r in releases
if current_date <= r.date < next_date]
# Handle multiple releases (use highest, Q8.1)
if len(period_releases) > 1:
period_releases = [max(period_releases, key=lambda r: parse_version(r.version))]
periods.append({
'id': format_period_id(current_date, strategy),
'type': 'release' if period_releases else 'time_period',
'start_date': current_date,
'end_date': next_date,
'start_commit': period_commits[-1].hash, # oldest
'end_commit': period_commits[0].hash, # newest
'tag': period_releases[0].version if period_releases else None,
'commit_count': len(period_commits),
'is_first_period': (current_date == align_to_boundary(start_date, strategy))
})
current_date = next_date
# Handle final partial period (Q6.2 Option B)
if has_unreleased_commits(end_date):
periods[-1]['is_partial'] = True
periods[-1]['label'] = 'Unreleased'
return periods
```
### Phase 5: Metadata Enrichment
```python
def enrich_period_metadata(periods):
"""Add statistical metadata to each period."""
for period in periods:
# Basic stats
period['metadata'] = {
'commit_count': period['commit_count'],
'contributors': count_unique_authors(period),
'files_changed': count_files_changed(period),
'lines_added': sum_lines_added(period),
'lines_removed': sum_lines_removed(period)
}
# Significance scoring
if period['commit_count'] > 100:
period['metadata']['significance'] = 'major'
elif period['commit_count'] > 50:
period['metadata']['significance'] = 'minor'
else:
period['metadata']['significance'] = 'patch'
# First period special handling (Q8.1 - summarize)
if period.get('is_first_period') and period['commit_count'] > 100:
period['metadata']['mode'] = 'summary'
period['metadata']['summary_note'] = f"Initial {period['commit_count']} commits"
return periods
```
## Output Format
I provide structured period data for the period-coordinator agent:
```json
{
"strategy_used": "monthly",
"auto_detected": true,
"periods": [
{
"id": "2024-01",
"type": "time_period",
"label": "January 2024",
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z",
"start_commit": "abc123def",
"end_commit": "ghi789jkl",
"tag": "v1.2.0",
"commit_count": 45,
"is_first_period": true,
"is_partial": false,
"metadata": {
"contributors": 8,
"files_changed": 142,
"lines_added": 3421,
"lines_removed": 1876,
"significance": "minor",
"mode": "full"
}
},
{
"id": "2024-02",
"type": "release",
"label": "February 2024",
"start_date": "2024-02-01T00:00:00Z",
"end_date": "2024-02-29T23:59:59Z",
"start_commit": "mno345pqr",
"end_commit": "stu678vwx",
"tag": "v1.3.0",
"commit_count": 52,
"is_first_period": false,
"is_partial": false,
"metadata": {
"contributors": 12,
"files_changed": 187,
"lines_added": 4567,
"lines_removed": 2345,
"significance": "minor",
"mode": "full"
}
},
{
"id": "unreleased",
"type": "time_period",
"label": "Unreleased",
"start_date": "2024-11-11T00:00:00Z",
"end_date": "2024-11-14T14:32:08Z",
"start_commit": "yza123bcd",
"end_commit": "HEAD",
"tag": null,
"commit_count": 7,
"is_first_period": false,
"is_partial": true,
"metadata": {
"contributors": 3,
"files_changed": 23,
"lines_added": 456,
"lines_removed": 123,
"significance": "patch",
"mode": "full"
}
}
],
"total_commits": 1523,
"date_range": {
"earliest": "2024-01-01T10:23:15Z",
"latest": "2024-11-14T14:32:08Z",
"age_days": 318
},
"statistics": {
"total_periods": 11,
"empty_periods_skipped": 2,
"merge_only_periods_skipped": 1,
"release_periods": 8,
"time_periods": 3,
"first_period_mode": "summary"
}
}
```
## Integration Points
### With period-coordinator Agent
I'm invoked first in the replay workflow:
1. User runs `/changelog-init --replay monthly`
2. Command passes parameters to me
3. I calculate all period boundaries
4. I return structured period data
5. Period coordinator uses my output to orchestrate analysis
### With Configuration System
I respect user preferences from `.changelog.yaml`:
```yaml
replay:
interval: "monthly"
calendar:
week_start: "monday"
use_calendar_months: true
auto_thresholds:
daily_if_commits_per_day_exceed: 5
weekly_if_commits_per_week_exceed: 20
filters:
min_commits: 5
tag_pattern: "v*"
```
## Performance Characteristics
**Speed**: Very fast (uses Haiku model)
- Typical execution: 5-10 seconds
- Handles 1000+ tags in <30 seconds
- Scales linearly with tag count
**Cost**: Minimal
- Haiku is 70% cheaper than Sonnet
- Pure computation (no deep analysis)
- One-time cost per replay
**Accuracy**: High
- Date parsing: 100% accurate
- Tag detection: 99%+ with regex patterns
- Boundary alignment: Mathematically exact
## Invocation Context
I should be invoked when:
- User runs `/changelog-init --replay [interval]`
- User runs `/changelog-init --replay auto`
- User runs `/changelog-init --replay-regenerate`
- Period boundaries need recalculation
- Validating period configuration
I should NOT be invoked when:
- Standard `/changelog-init` without --replay
- `/changelog update` (incremental update)
- `/changelog-release` (single release)
## Error Handling
**No version tags found**:
```
Warning: No version tags detected.
Falling back to time-based periods only.
Suggestion: Tag releases with 'git tag -a v1.0.0' for better structure.
```
**Invalid date ranges**:
```
Error: Start date (2024-12-01) is after end date (2024-01-01).
Please verify --from and --to parameters.
```
**Conflicting configuration**:
```
Warning: CLI flag --replay weekly overrides config setting (monthly).
Using: weekly
```
**Repository too small**:
```
Warning: Repository has only 5 commits across 2 days.
Replay mode works best with longer histories.
Recommendation: Use standard /changelog-init instead.
```
## Example Usage
```markdown
User: /changelog-init --replay monthly
Claude: Analyzing repository for period detection...
[Invokes period-detector agent]
Period Detector Output:
- Strategy: monthly (user-specified)
- Repository age: 318 days (2024-01-01 to 2024-11-14)
- Total commits: 1,523
- Version tags found: 8 releases
- Detected 11 periods (10 monthly + 1 unreleased)
- Skipped 2 empty months (March, August)
- First period (January 2024): 147 commits → summary mode
Periods ready for analysis.
[Passes to period-coordinator for orchestration]
```
---
I am optimized for fast, accurate period calculation. My role is computational, not analytical - I determine WHEN to analyze, not WHAT was changed. The period-coordinator agent handles workflow orchestration, and the existing analysis agents handle the actual commit analysis.

View File

@@ -0,0 +1,736 @@
---
description: Extracts project context from documentation to inform user-facing release notes generation
capabilities: ["documentation-analysis", "context-extraction", "audience-identification", "feature-mapping", "user-benefit-extraction"]
model: "claude-4-5-haiku"
---
# Project Context Extractor Agent
## Role
I analyze project documentation (CLAUDE.md, README.md, docs/) to extract context about the product, target audience, and user-facing features. This context helps generate user-focused RELEASE_NOTES.md that align with the project's communication style and priorities.
## Core Capabilities
### 1. Documentation Discovery
- Locate and read CLAUDE.md, README.md, and docs/ directory files
- Parse markdown structure and extract semantic sections
- Prioritize information from authoritative sources
- Handle missing files gracefully with fallback behavior
### 2. Context Extraction
Extract key information from project documentation:
- **Product Vision**: What problem does this solve? What's the value proposition?
- **Target Audience**: Who uses this? Developers? End-users? Enterprises? Mixed audience?
- **User Personas**: Different user types and their specific needs and concerns
- **Feature Descriptions**: How features are described in user-facing documentation
- **User Benefits**: Explicit benefits mentioned in documentation
- **Architectural Overview**: System components and user touchpoints vs internal-only components
### 3. Benefit Mapping
Correlate technical implementations to user benefits:
- Map technical terms (e.g., "Redis caching") to user benefits (e.g., "faster performance")
- Identify which technical changes impact end-users vs internal concerns
- Extract terminology preferences from documentation (how the project talks about features)
- Build feature catalog connecting technical names to user-facing names
### 4. Tone Analysis
Determine appropriate communication style:
- Analyze existing documentation tone (formal, conversational, technical)
- Identify technical level of target audience
- Detect emoji usage patterns
- Recommend tone for release notes that matches project style
### 5. Priority Assessment
Understand what matters to users based on documentation:
- Identify emphasis areas from documentation (security, performance, UX, etc.)
- Detect de-emphasized topics (internal implementation details, dependencies)
- Parse custom instructions from .changelog.yaml
- Apply priority rules: .changelog.yaml > CLAUDE.md > README.md > docs/
## Working Process
### Phase 1: File Discovery
```python
def discover_documentation(config):
"""
Find relevant documentation files in priority order.
"""
sources = config.get('release_notes.project_context_sources', [
'CLAUDE.md',
'README.md',
'docs/README.md',
'docs/**/*.md'
])
found_files = []
for pattern in sources:
try:
if '**' in pattern or '*' in pattern:
# Glob pattern
files = glob_files(pattern)
found_files.extend(files)
else:
# Direct path
if file_exists(pattern):
found_files.append(pattern)
except Exception as e:
log_warning(f"Failed to process documentation source '{pattern}': {e}")
continue
# Prioritize: CLAUDE.md > README.md > docs/
return prioritize_sources(found_files)
```
### Phase 2: Content Extraction
```python
def extract_project_context(files, config):
"""
Read and parse documentation files to build comprehensive context.
"""
context = {
'project_metadata': {
'name': None,
'description': None,
'target_audience': [],
'product_vision': None
},
'user_personas': [],
'feature_catalog': {},
'architectural_context': {
'components': [],
'user_touchpoints': [],
'internal_only': []
},
'tone_guidance': {
'recommended_tone': 'professional',
'audience_technical_level': 'mixed',
'existing_documentation_style': None,
'use_emoji': False,
'formality_level': 'professional'
},
'custom_instructions': {},
'confidence': 0.0,
'sources_analyzed': []
}
max_length = config.get('release_notes.project_context_max_length', 5000)
for file_path in files:
try:
content = read_file(file_path, max_chars=max_length)
context['sources_analyzed'].append(file_path)
# Extract different types of information
if 'CLAUDE.md' in file_path:
# CLAUDE.md is highest priority for project info
context['project_metadata'].update(extract_metadata_from_claude(content))
context['feature_catalog'].update(extract_features_from_claude(content))
context['architectural_context'].update(extract_architecture_from_claude(content))
context['tone_guidance'].update(analyze_tone(content))
elif 'README.md' in file_path:
# README.md is secondary source
context['project_metadata'].update(extract_metadata_from_readme(content))
context['user_personas'].extend(extract_personas_from_readme(content))
context['feature_catalog'].update(extract_features_from_readme(content))
else:
# docs/ files provide domain knowledge
context['feature_catalog'].update(extract_features_generic(content))
except Exception as e:
log_warning(f"Failed to read {file_path}: {e}")
continue
# Calculate confidence based on what we found
context['confidence'] = calculate_confidence(context)
# Merge with .changelog.yaml custom instructions (HIGHEST priority)
config_instructions = config.get('release_notes.custom_instructions')
if config_instructions:
context['custom_instructions'] = config_instructions
context = merge_with_custom_instructions(context, config_instructions)
return context
```
### Phase 3: Content Analysis
I analyze extracted content using these strategies:
#### Identify Target Audience
```python
def extract_target_audience(content):
"""
Parse audience mentions from documentation.
Looks for patterns like:
- "For developers", "For end-users", "For enterprises"
- "Target audience:", "Users:", "Intended for:"
- Code examples (indicates technical audience)
- Business language (indicates non-technical audience)
"""
audience = []
# Pattern matching for explicit mentions
if re.search(r'for developers?', content, re.IGNORECASE):
audience.append('developers')
if re.search(r'for (end-)?users?', content, re.IGNORECASE):
audience.append('end-users')
if re.search(r'for enterprises?', content, re.IGNORECASE):
audience.append('enterprises')
# Infer from content style
code_blocks = content.count('```')
if code_blocks > 5:
if 'developers' not in audience:
audience.append('developers')
# Default if unclear
if not audience:
audience = ['users']
return audience
```
#### Build Feature Catalog
```python
def extract_features_from_claude(content):
"""
Extract feature descriptions from CLAUDE.md.
CLAUDE.md typically contains:
- ## Features section
- ## Architecture section with component descriptions
- Inline feature explanations
"""
features = {}
# Parse markdown sections
sections = parse_markdown_sections(content)
# Look for features section
if 'features' in sections or 'capabilities' in sections:
feature_section = sections.get('features') or sections.get('capabilities')
features.update(parse_feature_list(feature_section))
# Look for architecture section
if 'architecture' in sections:
arch_section = sections['architecture']
features.update(extract_components_as_features(arch_section))
return features
def parse_feature_list(content):
"""
Parse bullet lists of features.
Example:
- **Authentication**: Secure user sign-in with JWT tokens
- **Real-time Updates**: WebSocket-powered notifications
Returns:
{
'authentication': {
'user_facing_name': 'Sign-in & Security',
'technical_name': 'authentication',
'description': 'Secure user sign-in with JWT tokens',
'user_benefits': ['Secure access', 'Easy login']
}
}
"""
features = {}
# Match markdown list items with bold headers
pattern = r'[-*]\s+\*\*([^*]+)\*\*:?\s+(.+)'
matches = re.findall(pattern, content)
for name, description in matches:
feature_key = name.lower().replace(' ', '_')
features[feature_key] = {
'user_facing_name': name,
'technical_name': feature_key,
'description': description.strip(),
'user_benefits': extract_benefits_from_description(description)
}
return features
```
#### Determine Tone
```python
def analyze_tone(content):
"""
Analyze documentation tone and style.
"""
tone = {
'recommended_tone': 'professional',
'audience_technical_level': 'mixed',
'use_emoji': False,
'formality_level': 'professional'
}
# Check emoji usage
emoji_count = count_emoji(content)
tone['use_emoji'] = emoji_count > 3
# Check technical level
technical_indicators = [
'API', 'endpoint', 'function', 'class', 'method',
'configuration', 'deployment', 'architecture'
]
technical_count = sum(content.lower().count(t.lower()) for t in technical_indicators)
if technical_count > 20:
tone['audience_technical_level'] = 'technical'
elif technical_count < 5:
tone['audience_technical_level'] = 'non-technical'
# Check formality
casual_indicators = ["you'll", "we're", "let's", "hey", "awesome", "cool"]
casual_count = sum(content.lower().count(c) for c in casual_indicators)
if casual_count > 5:
tone['formality_level'] = 'casual'
tone['recommended_tone'] = 'casual'
return tone
```
### Phase 4: Priority Merging
```python
def merge_with_custom_instructions(context, custom_instructions):
"""
Merge custom instructions from .changelog.yaml with extracted context.
Priority order (highest to lowest):
1. .changelog.yaml custom_instructions (HIGHEST)
2. CLAUDE.md project information
3. README.md overview
4. docs/ domain knowledge
5. Default fallback (LOWEST)
"""
# Parse custom instructions if it's a string
if isinstance(custom_instructions, str):
try:
custom_instructions = parse_custom_instructions_string(custom_instructions)
if not isinstance(custom_instructions, dict):
log_warning("Failed to parse custom_instructions string, using empty dict")
custom_instructions = {}
except Exception as e:
log_warning(f"Error parsing custom_instructions: {e}")
custom_instructions = {}
# Ensure custom_instructions is a dict
if not isinstance(custom_instructions, dict):
log_warning(f"custom_instructions is not a dict (type: {type(custom_instructions)}), using empty dict")
custom_instructions = {}
# Override target audience if specified
if custom_instructions.get('audience'):
context['project_metadata']['target_audience'] = [custom_instructions['audience']]
# Override tone if specified
if custom_instructions.get('tone'):
context['tone_guidance']['recommended_tone'] = custom_instructions['tone']
# Merge emphasis areas
if custom_instructions.get('emphasis_areas'):
context['custom_instructions']['emphasis_areas'] = custom_instructions['emphasis_areas']
# Merge de-emphasis areas
if custom_instructions.get('de_emphasize'):
context['custom_instructions']['de_emphasize'] = custom_instructions['de_emphasize']
# Add terminology mappings
if custom_instructions.get('terminology'):
context['custom_instructions']['terminology'] = custom_instructions['terminology']
# Add special notes
if custom_instructions.get('special_notes'):
context['custom_instructions']['special_notes'] = custom_instructions['special_notes']
# Add user impact keywords
if custom_instructions.get('user_impact_keywords'):
context['custom_instructions']['user_impact_keywords'] = custom_instructions['user_impact_keywords']
# Add include_internal_changes setting
if 'include_internal_changes' in custom_instructions:
context['custom_instructions']['include_internal_changes'] = custom_instructions['include_internal_changes']
return context
```
## Output Format
I provide structured context data to changelog-synthesizer:
```json
{
"project_metadata": {
"name": "Changelog Manager",
"description": "AI-powered changelog generation plugin for Claude Code",
"target_audience": ["developers", "engineering teams"],
"product_vision": "Automate changelog creation while maintaining high quality and appropriate audience focus"
},
"user_personas": [
{
"name": "Software Developer",
"needs": ["Quick changelog updates", "Accurate technical details", "Semantic versioning"],
"concerns": ["Manual changelog maintenance", "Inconsistent formatting", "Missing changes"]
},
{
"name": "Engineering Manager",
"needs": ["Release notes for stakeholders", "User-focused summaries", "Release coordination"],
"concerns": ["Technical jargon in user-facing docs", "Time spent on documentation"]
}
],
"feature_catalog": {
"git_history_analysis": {
"user_facing_name": "Intelligent Change Detection",
"technical_name": "git-history-analyzer agent",
"description": "Automatically analyzes git commits and groups related changes",
"user_benefits": [
"Save time on manual changelog writing",
"Never miss important changes",
"Consistent categorization"
]
},
"ai_commit_analysis": {
"user_facing_name": "Smart Commit Understanding",
"technical_name": "commit-analyst agent",
"description": "AI analyzes code diffs to understand unclear commit messages",
"user_benefits": [
"Accurate descriptions even with vague commit messages",
"Identifies user impact automatically"
]
}
},
"architectural_context": {
"components": [
"Git history analyzer",
"Commit analyst",
"Changelog synthesizer",
"GitHub matcher"
],
"user_touchpoints": [
"Slash commands (/changelog)",
"Generated files (CHANGELOG.md, RELEASE_NOTES.md)",
"Configuration (.changelog.yaml)"
],
"internal_only": [
"Agent orchestration",
"Cache management",
"Git operations"
]
},
"tone_guidance": {
"recommended_tone": "professional",
"audience_technical_level": "technical",
"existing_documentation_style": "Clear, detailed, with code examples",
"use_emoji": true,
"formality_level": "professional"
},
"custom_instructions": {
"emphasis_areas": ["Developer experience", "Time savings", "Accuracy"],
"de_emphasize": ["Internal refactoring", "Dependency updates"],
"terminology": {
"agent": "AI component",
"synthesizer": "document generator"
},
"special_notes": [
"Always highlight model choices (Sonnet vs Haiku) for transparency"
]
},
"confidence": 0.92,
"sources_analyzed": [
"CLAUDE.md",
"README.md",
"docs/ARCHITECTURE.md"
],
"fallback": false
}
```
## Fallback Behavior
If no documentation is found or extraction fails:
```python
def generate_fallback_context(config):
"""
Generate minimal context when no documentation available.
Uses:
1. Git repository name as project name
2. Generic descriptions
3. Custom instructions from config (if present)
4. Safe defaults
"""
project_name = get_project_name_from_git() or "this project"
return {
"project_metadata": {
"name": project_name,
"description": f"Software project: {project_name}",
"target_audience": ["users"],
"product_vision": "Deliver value to users through continuous improvement"
},
"user_personas": [],
"feature_catalog": {},
"architectural_context": {
"components": [],
"user_touchpoints": [],
"internal_only": []
},
"tone_guidance": {
"recommended_tone": config.get('release_notes.tone', 'professional'),
"audience_technical_level": "mixed",
"existing_documentation_style": None,
"use_emoji": config.get('release_notes.use_emoji', True),
"formality_level": "professional"
},
"custom_instructions": config.get('release_notes.custom_instructions', {}),
"confidence": 0.2,
"sources_analyzed": [],
"fallback": True,
"fallback_reason": "No documentation files found (CLAUDE.md, README.md, or docs/)"
}
```
When in fallback mode, I create a user-focused summary from commit analysis alone:
```python
def create_user_focused_summary_from_commits(commits, context):
"""
When no project documentation exists, infer user focus from commits.
Strategy:
1. Group commits by likely user impact
2. Identify features vs fixes vs internal changes
3. Generate generic user-friendly descriptions
4. Apply custom instructions from config
"""
summary = {
'user_facing_changes': [],
'internal_changes': [],
'recommended_emphasis': []
}
for commit in commits:
user_impact = assess_user_impact_from_commit(commit)
if user_impact > 0.5:
summary['user_facing_changes'].append({
'commit': commit,
'impact_score': user_impact,
'generic_description': generate_generic_user_description(commit)
})
else:
summary['internal_changes'].append(commit)
return summary
```
## Integration Points
### Input
I am invoked by command orchestration (changelog.md, changelog-release.md):
```python
project_context = invoke_agent('project-context-extractor', {
'config': config,
'cache_enabled': True
})
```
### Output
I provide context to changelog-synthesizer:
```python
documents = invoke_agent('changelog-synthesizer', {
'project_context': project_context, # My output
'git_analysis': git_analysis,
'enhanced_analysis': enhanced_analysis,
'config': config
})
```
## Caching Strategy
To avoid re-reading documentation on every invocation:
```python
def get_cache_key(config):
"""
Generate cache key based on:
- Configuration hash (custom_instructions)
- Git HEAD commit (project might change)
- Documentation file modification times
"""
config_hash = hash_config(config.get('release_notes'))
head_commit = get_git_head_sha()
doc_mtimes = get_documentation_mtimes(['CLAUDE.md', 'README.md', 'docs/'])
return f"project-context-{config_hash}-{head_commit}-{hash(doc_mtimes)}"
def load_with_cache(config):
"""
Load context with caching.
"""
cache_enabled = config.get('release_notes.project_context_enabled', True)
cache_ttl = config.get('release_notes.project_context_cache_ttl_hours', 24)
if not cache_enabled:
return extract_project_context_fresh(config)
cache_key = get_cache_key(config)
cache_path = f".changelog-cache/project-context/{cache_key}.json"
if file_exists(cache_path) and cache_age(cache_path) < cache_ttl * 3600:
return load_from_cache(cache_path)
# Extract fresh context
context = extract_project_context_fresh(config)
# Save to cache
save_to_cache(cache_path, context)
return context
```
## Special Capabilities
### 1. Multi-File Synthesis
I can combine information from multiple documentation files:
- CLAUDE.md provides project-specific guidance
- README.md provides public-facing descriptions
- docs/ provides detailed feature documentation
Information is merged with conflict resolution (priority-based).
### 2. Partial Context
If only some files are found, I extract what's available and mark confidence accordingly:
- All files found: confidence 0.9-1.0
- CLAUDE.md + README.md: confidence 0.7-0.9
- Only README.md: confidence 0.5-0.7
- No files (fallback): confidence 0.2
### 3. Intelligent Feature Mapping
I map technical component names to user-facing feature names:
```
Technical: "Redis caching layer with TTL"
User-facing: "Faster performance through intelligent caching"
Technical: "JWT token authentication"
User-facing: "Secure sign-in system"
Technical: "WebSocket notification system"
User-facing: "Real-time updates"
```
### 4. Conflict Resolution
When .changelog.yaml custom_instructions conflict with extracted context:
1. **Always prefer .changelog.yaml** (explicit user intent)
2. Merge non-conflicting information
3. Log when overrides occur for transparency
## Invocation Context
I should be invoked:
- At the start of `/changelog` or `/changelog-release` workflows
- Before changelog-synthesizer runs
- After .changelog.yaml configuration is loaded
- Can be cached for session duration to improve performance
## Edge Cases
### 1. No Documentation Found
- Use fallback mode
- Generate generic context from git metadata
- Apply custom instructions from config if available
- Mark fallback=true and confidence=0.2
### 2. Conflicting Information
Priority order:
1. .changelog.yaml custom_instructions (highest)
2. CLAUDE.md
3. README.md
4. docs/
5. Defaults (lowest)
### 3. Large Documentation
- Truncate to max_content_length (default 5000 chars per file)
- Prioritize introduction and feature sections
- Log truncation for debugging
### 4. Encrypted or Binary Files
- Skip gracefully
- Log warning
- Continue with available documentation
### 5. Invalid Markdown
- Parse what's possible using lenient parser
- Continue with partial context
- Reduce confidence score accordingly
### 6. Very Technical Documentation
- Extract technical terms for translation
- Identify user touchpoints vs internal components
- Don't change tone (as per requirements)
- Focus on translating technical descriptions to user benefits
## Performance Considerations
- **Model**: Haiku for cost-effectiveness (document analysis is straightforward)
- **Caching**: 24-hour TTL reduces repeated processing
- **File Size Limits**: Max 5000 chars per file prevents excessive token usage
- **Selective Reading**: Only read markdown files, skip images/binaries
- **Lazy Loading**: Only read docs/ if configured
## Quality Assurance
Before returning context, I validate:
1. **Completeness**: At least one source was analyzed OR fallback generated
2. **Structure**: All required fields present in output
3. **Confidence**: Score calculated and reasonable (0.0-1.0)
4. **Terminology**: Feature catalog has valid entries
5. **Tone**: Recommended tone is one of: professional, casual, technical
---
This agent enables context-aware, user-focused release notes that align with how each project communicates with its audience.

717
commands/changelog-init.md Normal file
View File

@@ -0,0 +1,717 @@
---
description: Initialize CHANGELOG.md and RELEASE_NOTES.md for a new project or retroactively from git history
aliases: ["cl-init"]
---
# changelog-init
Initialize changelog documentation for a project by analyzing entire git history
and generating both developer and user-facing documentation files.
## Usage
```bash
/changelog-init # Interactive initialization
/changelog-init --from-beginning # Analyze entire git history
/changelog-init --from-tag v1.0.0 # Start from specific version
/changelog-init --empty # Create empty template files
# Historical Replay Mode (NEW)
/changelog-init --replay # Interactive period-based replay
/changelog-init --replay --period monthly # Monthly period grouping
/changelog-init --replay --period weekly # Weekly period grouping
/changelog-init --replay --period by-release # Group by releases
/changelog-init --replay --period auto # Auto-detect best period
```
## Workflow
### Step 1: Project Analysis
- Detects existing version files (package.json, setup.py, etc.)
- Identifies versioning scheme in use
- Analyzes git tag patterns
- Detects commit message conventions
### Step 2: History Processing
- Extracts all commits from starting point
- Groups by releases (if tags exist)
- Categorizes changes
- Identifies key milestones
### Step 3: File Generation
- Creates CHANGELOG.md with complete history
- Creates RELEASE_NOTES.md with major highlights
- Generates .changelog.yaml configuration
- Sets up .changelog-metadata.json for tracking
## Replay Workflow (Historical Period-Based Generation)
The `--replay` mode generates changelogs by "replaying" history through time periods (daily/weekly/monthly/by-release), creating changelog entries as if they were updated in real-time during development.
### Phase 1: Period Detection
**Agent: period-detector (Claude Haiku)**
```
🔍 Analyzing repository structure...
Repository: user/awesome-project
First commit: 2023-03-15 (619 days ago)
Total commits: 523
Contributors: 24
Git tags: 12 releases detected
Auto-detecting optimal period strategy...
✅ Recommended: weekly (21.4 commits/week average)
Period options:
1. Weekly (74 periods, ~7 commits/period)
2. Monthly (20 periods, ~26 commits/period)
3. By-Release (12 periods, ~44 commits/period)
4. Auto (use recommended: weekly)
Select period strategy [1-4] or press Enter for auto: _
```
**Detection Logic:**
- Analyzes commit frequency and distribution
- Detects existing release tags
- Calculates project age and activity patterns
- Provides smart recommendations with rationale
### Phase 2: Boundary Calculation
**Agent: period-detector (Claude Haiku)**
```
📅 Calculating period boundaries...
Strategy: Weekly (Monday-Sunday)
Total periods: 74
Empty periods (will be skipped): 8
Merge-only periods (will be skipped): 3
Active periods to analyze: 63
Period boundaries:
- Week 1: 2023-03-13 to 2023-03-19 (15 commits)
- Week 2: 2023-03-20 to 2023-03-26 (22 commits)
- Week 3: 2023-03-27 to 2023-04-02 (18 commits)
...
- Week 74: 2025-11-10 to 2025-11-16 (8 commits) [Unreleased]
First period note: Week 1 has 287 commits (initial development)
→ Will use summary mode for clarity
Continue with analysis? [Y/n]: _
```
**Boundary Features:**
- Calendar-aligned periods (weeks start Monday, months are calendar months)
- Automatic skip of empty periods
- Automatic skip of merge-only periods
- First-period summarization for large initial development
- Partial final period handling (→ [Unreleased])
### Phase 3: Parallel Period Analysis
**Agent: period-coordinator (Claude Sonnet)**
```
⚙️ Orchestrating multi-period analysis...
Execution plan:
- Total periods: 63
- Concurrent workers: 3
- Estimated time: ~4 minutes
- Cache enabled: Yes
Batch 1/21: Analyzing periods 1-3 in parallel...
✅ Week 1 (2023-03-13): 287 commits → Summarized
✅ Week 2 (2023-03-20): 22 commits → 18 changes categorized
✅ Week 3 (2023-03-27): 18 commits → 15 changes categorized
Batch 2/21: Analyzing periods 4-6 in parallel...
✅ Week 4 (2023-04-03): 25 commits → 20 changes categorized
⚠️ Week 5 (2023-04-10): Analysis timeout, retrying...
✅ Week 5 (2023-04-10): 31 commits → 28 changes categorized
✅ Week 6 (2023-04-17): 19 commits → 16 changes categorized
[Progress: 9/63 periods complete - 14% - ETA 3m 42s]
...
```
**Per-Period Analysis:**
Each period invokes:
1. **git-history-analyzer** (Sonnet): Extract and group commits for period
2. **commit-analyst** (Haiku): Batch-analyze unclear commits (invoked automatically by git-history-analyzer)
3. Caching: Results cached per period for instant regeneration
### Phase 4: Changelog Synthesis
**Agent: changelog-synthesizer (Claude Sonnet)**
```
📝 Generating hybrid-format changelog...
Format: Hybrid (version releases with period subsections)
Structure:
- [Unreleased] section: 2 active periods
- Released versions: 12 versions across 61 periods
- Total entries: 412 changes categorized
Generating CHANGELOG.md...
✅ 63 period sections created
✅ 12 version sections created
✅ Navigation TOC added (74 periods)
✅ 412 changes formatted
Generating RELEASE_NOTES.md...
✅ Period-aware user-facing notes created
✅ Adapted tone for end-users
✅ Highlighted major features per period
```
**Output Format:**
- **CHANGELOG.md**: Hybrid format with version sections containing period subsections
- **RELEASE_NOTES.md**: User-friendly with period-based highlights
- **Navigation**: Table of contents for changelogs >10 periods
### Phase 5: Verification and Commit
```
✅ Changelog generation complete!
Files created:
- CHANGELOG.md (1,847 lines, 63 period sections)
- RELEASE_NOTES.md (423 lines, user-friendly format)
- .changelog.yaml (configuration persisted)
- .changelog-cache/ (63 period analyses cached)
Preview of CHANGELOG.md:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Changelog
## [Unreleased]
### Week of November 11, 2025
#### Added
- Real-time notification system (#256)
### Week of November 4, 2025
#### Added
- Advanced search filters (#252)
## [2.1.0] - 2024-10-27
### Week of October 21, 2024
#### Added
- REST API v2 with pagination (#234)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Actions:
1. Review generated files? [Y/n]
2. Commit to git? [Y/n]
3. Create version tag? [y/N]
```
## Agent Orchestration
**CRITICAL**: You MUST use the Task tool to invoke these agents in the correct sequence.
### Standard Mode Agent Sequence
For standard `/changelog-init` (non-replay):
#### 1. Project Context Extractor (Claude Haiku)
```
Use Task tool with:
- subagent_type: "changelog-manager:project-context-extractor"
- description: "Extract project context from documentation"
- prompt: "Analyze CLAUDE.md, README.md, and docs/ to extract project context for user-focused release notes."
```
#### 2. Git History Analyzer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:git-history-analyzer"
- description: "Analyze entire git history"
- prompt: "Extract all commits from beginning (or specified tag), group by releases/PRs/features, categorize changes, and detect breaking changes."
```
#### 3. GitHub Matcher (Claude Sonnet) - OPTIONAL
```
Only invoke if GitHub integration enabled.
Use Task tool with:
- subagent_type: "changelog-manager:github-matcher"
- description: "Match commits to GitHub artifacts"
- prompt: "Enrich all historical commits with GitHub references."
```
#### 4. Changelog Synthesizer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:changelog-synthesizer"
- description: "Generate initial changelog files"
- prompt: "Generate complete CHANGELOG.md and RELEASE_NOTES.md from entire project history using project context for user focus."
```
### Replay Mode Agent Sequence
For `/changelog-init --replay` (period-based historical generation):
#### 1. Project Context Extractor (Claude Haiku)
Same as standard mode.
#### 2. Period Detector (Claude Haiku)
```
Use Task tool with:
- subagent_type: "changelog-manager:period-detector"
- description: "Detect optimal period strategy"
- prompt: "Analyze repository history to detect optimal period strategy (daily/weekly/monthly/by-release), calculate period boundaries, and present options to user."
```
**Purpose**: Analyzes commit frequency, project age, and release patterns to recommend optimal period grouping strategy.
**Output**: Period boundaries with start/end commits and dates for each period.
#### 3. Period Coordinator (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:period-coordinator"
- description: "Orchestrate multi-period analysis"
- prompt: "Coordinate parallel analysis of all periods by invoking git-history-analyzer for each period, managing cache, and handling retries."
```
**Purpose**: Orchestrates parallel analysis of all time periods, invoking git-history-analyzer once per period with period context.
**Sub-invocations** (managed by period-coordinator):
- For each period: Invokes **git-history-analyzer** with period boundaries
- Optional: Invokes **github-matcher** to enrich period commits
- Caches results per period for fast regeneration
#### 4. Changelog Synthesizer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:changelog-synthesizer"
- description: "Generate hybrid-format changelogs"
- prompt: "Generate hybrid-format CHANGELOG.md (versions with period subsections) and period-aware RELEASE_NOTES.md from multi-period analysis."
```
**Purpose**: Synthesizes period-based analysis into hybrid changelog format with version sections containing period subsections.
### Integration Flow
**Standard Mode:**
```
project-context-extractor (Haiku)
git-history-analyzer (Sonnet)
github-matcher (Sonnet) [OPTIONAL]
changelog-synthesizer (Sonnet)
Write files
```
**Replay Mode:**
```
project-context-extractor (Haiku)
period-detector (Haiku)
period-coordinator (Sonnet)
└─→ [For each period in parallel]
git-history-analyzer (Sonnet)
github-matcher (Sonnet) [OPTIONAL]
changelog-synthesizer (Sonnet)
Write files
```
## Options
### Standard Mode
- `--from-beginning`: Analyze entire repository history
- `--from-tag <tag>`: Start from specific git tag
- `--empty`: Create template files without historical content
- `--config-only`: Only generate .changelog.yaml configuration
- `--force`: Overwrite existing files (backup created)
### Replay Mode (NEW)
- `--replay`: Enable historical replay mode with period-based generation
- `--period <strategy>`: Period grouping strategy
- `daily`: One entry per day with commits
- `weekly`: One entry per week (Monday-Sunday)
- `monthly`: One entry per calendar month
- `quarterly`: One entry per quarter (Q1, Q2, Q3, Q4)
- `annual`: One entry per year
- `by-release`: One entry per git tag/release
- `auto`: Auto-detect best strategy (default)
- `--calendar-align`: Align periods to calendar boundaries (default: true)
- `--skip-empty`: Skip periods with no commits (default: true)
- `--skip-merge-only`: Skip periods with only merge commits (default: true)
- `--max-workers <n>`: Concurrent period analyses (default: 3, max: 5)
- `--no-cache`: Disable caching (slower but always fresh)
- `--hybrid-format`: Generate hybrid format CHANGELOG.md (default: true)
- `--replay-in-release-notes`: Apply replay structure to RELEASE_NOTES.md (default: true)
## Examples
### New Project Setup
```bash
You: /changelog-init --empty
Claude: 📝 Initializing changelog files...
Created:
✅ CHANGELOG.md (template)
✅ RELEASE_NOTES.md (template)
✅ .changelog.yaml (configuration)
Your changelog files are ready! Next steps:
1. Customize .changelog.yaml for your project
2. Run `/changelog update` after making changes
3. Run `/changelog release` when ready to publish
```
### Retroactive Generation
```bash
You: /changelog-init --from-beginning
Claude: 📊 Analyzing repository history...
Found:
- 523 commits
- 12 tagged releases
- 24 contributors
- First commit: 2023-03-15
Generating comprehensive changelog...
✅ Generated CHANGELOG.md with 12 versions
✅ Generated RELEASE_NOTES.md with major milestones
✅ Created configuration files
Notable milestones detected:
- v1.0.0: Initial release
- v2.0.0: Major rewrite with breaking changes
- v2.5.0: Performance optimizations
```
### Replay Mode: Auto-Detection
```bash
You: /changelog-init --replay
Claude: 🔍 Analyzing repository for replay...
Repository analysis:
- Total commits: 523
- First commit: 2023-03-15 (619 days ago)
- Releases: 12 tagged versions
- Contributors: 24
- Commit frequency: 21.4 commits/week
Auto-detection results:
✅ Recommended strategy: weekly
Rationale: Consistent activity (15-30 commits/week)
Alternative strategies:
- Monthly: 20 periods, ~26 commits/period
- By-Release: 12 periods, ~44 commits/period
Use recommended strategy? [Y/n]: Y
📅 Calculating 74 weekly periods...
- Active periods: 63
- Empty periods (skipped): 8
- Merge-only periods (skipped): 3
Proceed with analysis? [Y/n]: Y
⚙️ Executing parallel analysis (3 workers)...
[Progress bar] 63/63 periods analyzed - 100% - 3m 42s elapsed
✅ Generated CHANGELOG.md (1,847 lines, hybrid format)
✅ Generated RELEASE_NOTES.md (423 lines, period-aware)
✅ Configuration saved to .changelog.yaml
✅ Cache created: .changelog-cache/ (63 period analyses)
```
### Replay Mode: Monthly Periods
```bash
You: /changelog-init --replay --period monthly
Claude: 📅 Generating changelog with monthly periods...
Period breakdown:
- March 2023: 45 commits
- April 2023: 67 commits
- May 2023: 52 commits
...
- November 2025: 23 commits (partial, → [Unreleased])
Total: 20 active months, 3 empty months (skipped)
Analyzing in parallel (3 workers)...
✅ Complete! Generated hybrid CHANGELOG.md with 20 month sections.
```
### Replay Mode: Release-Based
```bash
You: /changelog-init --replay --period by-release
Claude: 🏷️ Grouping history by releases...
Detected releases:
- v0.1.0 (2023-03-15): 15 commits
- v0.2.0 (2023-04-12): 28 commits
- v1.0.0 (2023-06-01): 67 commits (major release)
- v1.1.0 (2023-07-15): 34 commits
...
- v2.5.0 (2024-10-27): 42 commits
- Unreleased: 23 commits
Total: 12 releases + unreleased section
Analyzing releases...
✅ Generated CHANGELOG.md with 13 sections (12 releases + unreleased)
```
### Replay Mode: High-Activity Project (Daily)
```bash
You: /changelog-init --replay --period daily
Claude: ⚠️ Daily period strategy selected
Repository has 523 commits over 619 days
This will create ~619 daily periods
Recommendation: Weekly or monthly might be more readable
Continue with daily strategy? [y/N]: y
📅 Calculating daily periods...
- Active days: 287
- Empty days (skipped): 332
Proceed? This may take ~8 minutes [Y/n]: Y
⚙️ Analyzing 287 daily periods (3 workers)...
[Progress: 287/287 - 100% - 7m 53s]
✅ Generated CHANGELOG.md (3,421 lines)
⚠️ Note: Changelog is very large. Consider using weekly strategy.
```
### Replay Mode: Custom Configuration
```bash
You: /changelog-init --replay --period weekly --max-workers 5 --hybrid-format
Claude: 📋 Replay configuration:
- Period: Weekly (Monday-Sunday)
- Workers: 5 concurrent analyses
- Format: Hybrid (versions + periods)
- Cache: Enabled
- Skip empty: Yes
- Skip merge-only: Yes
⚙️ Executing with 5 concurrent workers...
[Faster execution with more parallelism]
✅ Complete in 2m 18s (vs estimated 4m with 3 workers)
```
### Replay Mode: Regenerate Specific Period
```bash
You: /changelog-init --replay-period "2024-Q3" --force
Claude: 🔄 Regenerating specific period...
Period: Q3 2024 (July-September)
- Original analysis: 2025-01-15
- Commits in period: 87
- Previous entries: 64 changes
Regenerating with current configuration...
✅ Period regenerated
✅ Updated CHANGELOG.md (merged new analysis)
✅ Backup created: CHANGELOG.2025-11-14.md.backup
```
## Generated Files
### CHANGELOG.md Template
```markdown
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Initial project setup
### Changed
### Deprecated
### Removed
### Fixed
### Security
```
### Configuration File
```yaml
# .changelog.yaml
changelog:
conventional_commits: true
include_authors: true
include_commit_hash: false
categories:
- Added
- Changed
- Deprecated
- Removed
- Fixed
- Security
release_notes:
audience: "end-users"
tone: "professional"
use_emoji: true
versioning:
strategy: "semver"
auto_bump:
breaking: "major"
features: "minor"
fixes: "patch"
replay:
enabled: false
default_strategy: "auto"
performance:
enable_parallel: true
max_concurrent_periods: 3
enable_cache: true
```
### Hybrid Format CHANGELOG.md (Replay Mode)
```markdown
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Table of Contents
- **2025**
- [Week of November 11](#week-of-november-11-2025) - Unreleased
- [Week of November 4](#week-of-november-4-2025) - Unreleased
- [Week of October 21](#week-of-october-21-2024) - v2.1.0
- [Week of October 14](#week-of-october-14-2024) - v2.1.0
- **2024**
- [Month of September](#month-of-september-2024) - v2.0.0
...
## [Unreleased]
### Week of November 11, 2025
#### Added
- Real-time notification system with WebSocket support (#256, @dev2)
- Automatic reconnection with exponential backoff
- Event types: entity.created, entity.updated, entity.deleted
#### Fixed
- Memory leak in background job processor (#258, @dev1)
### Week of November 4, 2025
#### Added
- Advanced search filters with fuzzy matching (#252, @dev3)
## [2.1.0] - 2024-10-27
### Week of October 21, 2024
#### Added
- REST API v2 with cursor-based pagination (#234, @dev1)
- Backward compatible with v1 using version headers
- See migration guide in docs/api/v2-migration.md
#### Changed
- **BREAKING:** Authentication now uses JWT tokens instead of server sessions
- Sessions will be invalidated upon upgrade
- Update client libraries to v2.x for compatibility
### Week of October 14, 2024
#### Fixed
- Race condition in concurrent file uploads (#245, @dev2)
- Implemented proper file locking mechanism
#### Security
- Updated dependencies to address CVE-2024-1234 (High severity)
## [2.0.0] - 2024-09-30
### Month of September 2024
#### Added
- Complete UI redesign with modern component library (#210, @design-team)
- Dark mode support across all views (#215, @dev4)
#### Changed
- Migrated from Webpack to Vite
- Development server startup reduced from 30s to 3s
- Bundle size reduced by 22%
#### Removed
- Legacy XML export format (use JSON or CSV)
- Python 3.7 support (minimum version now 3.8)
[Unreleased]: https://github.com/user/repo/compare/v2.1.0...HEAD
[2.1.0]: https://github.com/user/repo/compare/v2.0.0...v2.1.0
[2.0.0]: https://github.com/user/repo/releases/tag/v2.0.0
```
## Integration
This command works with:
- `/changelog update` - Add new changes
- `/changelog release` - Prepare releases
- Git hooks - Automate updates

View File

@@ -0,0 +1,388 @@
---
description: Prepare a new release by updating changelogs, bumping version, and creating release artifacts
aliases: ["cl-release", "release-prep"]
---
# changelog-release
Orchestrate the complete release preparation process including changelog
finalization, version bumping, and release artifact generation.
## Usage
```bash
/changelog-release # Interactive release wizard
/changelog-release patch # Patch version bump (x.x.Z)
/changelog-release minor # Minor version bump (x.Y.0)
/changelog-release major # Major version bump (X.0.0)
/changelog-release v2.5.0 # Specific version
/changelog-release --pre-release rc1 # Release candidate
```
## Release Workflow
### Phase 1: Pre-Release Checks
- Verify all tests pass
- Check for uncommitted changes
- Validate changelog entries
- Confirm version bump strategy
- Review breaking changes
### Phase 2: Version Management
- Calculate new version number
- Update version in all relevant files:
- package.json
- setup.py / pyproject.toml
- VERSION file
- Source code constants
- Update changelog headers
### Phase 3: Documentation Finalization
- Move "Unreleased" changes to versioned section
- Generate release summary
- Create migration guide (if breaking changes)
- Generate announcement template
- Update comparison links
### Phase 4: Release Artifacts
- Create git commit for release
- Generate git tag
- Create release branch (if applicable)
- Prepare distribution packages
- Generate release notes for platforms
### Phase 5: Post-Release Setup
- Create new "Unreleased" section
- Set up next development cycle
- Generate release checklist
- Create follow-up tasks
## Agent Orchestration
**CRITICAL**: You MUST use the Task tool to invoke these agents in sequence for the release workflow.
### Agent Invocation Sequence
Invoke agents using the Task tool in this exact order:
#### 1. Project Context Extractor (Claude Haiku)
```
Use Task tool with:
- subagent_type: "changelog-manager:project-context-extractor"
- description: "Extract project context from documentation"
- prompt: "Analyze CLAUDE.md, README.md, and docs/ to extract project context for user-focused release notes."
```
**Purpose**: Reads project documentation to understand how to communicate release information to users.
**Output**: Project context object with feature catalog, tone guidance, and custom instructions.
#### 2. Git History Analyzer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:git-history-analyzer"
- description: "Analyze unreleased changes"
- prompt: "Extract all unreleased commits (since last version tag), group by PR/feature/semantic similarity, categorize changes, and detect breaking changes to determine appropriate version bump."
```
**Purpose**: Analyzes unreleased changes to determine version bump strategy and validate changelog entries.
**Output**: Structured change data with version bump recommendation (major/minor/patch).
#### 3. GitHub Matcher (Claude Sonnet) - OPTIONAL
```
Only invoke if GitHub integration enabled.
Use Task tool with:
- subagent_type: "changelog-manager:github-matcher"
- description: "Match unreleased commits to GitHub artifacts"
- prompt: "Enrich unreleased commits with GitHub Issue, PR, Project, and Milestone references for comprehensive release notes."
```
**Purpose**: Adds GitHub artifact references to release documentation.
**Output**: Enriched commit data with GitHub references.
#### 4. Changelog Synthesizer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:changelog-synthesizer"
- description: "Finalize release documentation"
- prompt: "Move 'Unreleased' section to versioned release section in CHANGELOG.md, generate user-facing RELEASE_NOTES.md for the new version, create release announcement template, and set up new 'Unreleased' section."
```
**Purpose**: Finalizes changelog documentation for the release, generates announcement templates.
**Output**: Updated CHANGELOG.md, RELEASE_NOTES.md, and release announcement template.
### Integration Flow
```
project-context-extractor (Haiku)
↓ [project_context]
git-history-analyzer (Sonnet)
↓ [git_analysis + version_recommendation]
github-matcher (Sonnet) [OPTIONAL]
↓ [enhanced_analysis]
changelog-synthesizer (Sonnet)
↓ [final_release_docs]
Update version files
Update changelog files
Create git commit
Create git tag
```
## Options
- `--dry-run`: Preview changes without applying
- `--no-tag`: Skip git tag creation
- `--no-commit`: Skip git commit
- `--pre-release <tag>`: Create pre-release (alpha, beta, rc)
- `--skip-tests`: Skip test verification
- `--announcement`: Generate announcement template
## Interactive Example
```bash
You: /changelog-release
Claude: 🚀 Release Preparation Wizard
📊 Current Status:
- Current version: v2.3.1
- Unreleased changes: 23 items
- 3 new features (suggests minor bump)
- 12 improvements
- 8 bug fixes
- 0 breaking changes
Suggested version: v2.4.0
What version would you like to release?
1. v2.4.0 (recommended - minor)
2. v2.3.2 (patch)
3. v3.0.0 (major)
4. Custom version
5. Pre-release (rc, beta, alpha)
You: 1
Claude: ✅ Preparing release v2.4.0...
🔍 Running pre-release checks:
- ✅ All tests passing
- ✅ No uncommitted changes
- ✅ Changelog entries valid
- ✅ No unresolved TODOs in code
📝 Updating version files:
- ✅ package.json: 2.3.1 → 2.4.0
- ✅ src/version.py: Updated VERSION constant
- ✅ README.md: Updated version badge
📚 Finalizing documentation:
- ✅ CHANGELOG.md: Moved 23 unreleased items to v2.4.0
- ✅ RELEASE_NOTES.md: Generated user-friendly summary
- ✅ Created release announcement template
Would you like to:
1. Review changes before committing
2. Proceed with release
3. Generate additional artifacts
4. Cancel
You: 1
Claude: 📄 Release Changes Preview:
**CHANGELOG.md excerpt:**
```markdown
## [2.4.0] - 2025-11-13
### Added
- REST API v2 with pagination support (#234)
- WebSocket real-time notifications (#240)
- Docker Compose development environment
```
**RELEASE_NOTES.md excerpt:**
```markdown
## Version 2.4.0 - November 13, 2025
### ✨ What's New
- Real-time notifications keep you updated instantly
- Lightning-fast API with new pagination
- Easier development setup with Docker
```
**Files to be modified:**
- CHANGELOG.md
- RELEASE_NOTES.md
- package.json
- src/version.py
Continue with release? (yes/no)
You: yes
Claude: 🎯 Executing release...
✅ Documentation updated
✅ Version files updated
✅ Commit created: "chore(release): Prepare v2.4.0"
✅ Tag created: v2.4.0
✅ Release branch created: release/v2.4.0
📋 Release Checklist:
□ Push changes: `git push origin main --tags`
□ Create GitHub release
□ Deploy to production
□ Announce to team/users
□ Monitor for issues
📢 Announcement template saved to: RELEASE_ANNOUNCEMENT.md
🎉 Release v2.4.0 prepared successfully!
```
## Version Strategies
### Semantic Versioning
```
MAJOR.MINOR.PATCH
- MAJOR: Breaking changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
```
### Pre-releases
```
v2.4.0-rc.1 # Release candidate
v2.4.0-beta.2 # Beta version
v2.4.0-alpha.3 # Alpha version
```
### Calendar Versioning
```
2025.11.13 # Year.Month.Day
2025.11 # Year.Month
25.11.1 # YY.MM.Patch
```
## Platform Integration
### GitHub Release
```bash
# Generates GitHub-compatible release notes
/changelog-release --platform github
```
### GitLab Release
```bash
# Generates GitLab release format
/changelog-release --platform gitlab
```
### npm Publication
```bash
# Prepares for npm publish
/changelog-release --platform npm
```
## Configuration
Customize in `.changelog.yaml`:
```yaml
release:
# Branches allowed for releases
allowed_branches:
- main
- master
- release/*
# Required checks before release
pre_release_checks:
- tests_pass
- no_uncommitted
- changelog_valid
# Files to update version in
version_files:
- package.json
- setup.py
- src/version.py
- README.md
# Post-release actions
post_release:
- create_github_release
- notify_slack
- trigger_deployment
```
## Automation Hooks
### Pre-release Hook
```bash
#!/bin/bash
# .changelog-hooks/pre-release.sh
echo "Running pre-release checks..."
npm test
npm run lint
```
### Post-release Hook
```bash
#!/bin/bash
# .changelog-hooks/post-release.sh
echo "Triggering deployment..."
curl -X POST https://deploy.example.com/webhook
```
## Best Practices
1. **Always review** generated changes before committing
2. **Run tests** before releasing
3. **Tag releases** for easy rollback
4. **Document breaking changes** thoroughly
5. **Announce releases** to stakeholders
6. **Monitor** post-release for issues
## Related Commands
- `/changelog update` - Update with recent changes
- `/version` - Manage version numbers
- `/git tag` - Create git tags
- `/release-notes` - Generate platform-specific notes

412
commands/changelog.md Normal file
View File

@@ -0,0 +1,412 @@
---
description: Initialize or update CHANGELOG.md and RELEASE_NOTES.md from git history
aliases: [ "cl", "change", "release" ]
---
# changelog
Intelligent management of CHANGELOG.md and RELEASE_NOTES.md files through
AI-powered git history analysis.
## Overview
The `/changelog` command provides a comprehensive workflow for maintaining both
developer-focused changelogs and user-facing release notes. It analyzes git
commits, groups related changes, and generates appropriate documentation for
different audiences.
## Usage
```bash
/changelog # Interactive mode - guides you through the process
/changelog init # Initialize both files for the first time
/changelog update # Update files with changes since last update
/changelog review # Review and refine existing entries
/changelog release [version] # Prepare a new release with version bump
```
## Workflow Phases
### Phase 1: Discovery & Analysis
- Detects existing CHANGELOG.md and RELEASE_NOTES.md files
- Identifies last update timestamp from file metadata
- Analyzes repository structure and conventions
- Determines version numbering scheme
### Phase 2: Git History Analysis
- Collects commits since last update (or all if initializing)
- Groups commits by:
- Feature branches
- Pull requests
- Time proximity
- Semantic similarity
- Identifies breaking changes, features, fixes, and improvements
### Phase 3: Commit Understanding
- For complex or unclear commits:
- Analyzes code diffs with AI (Sonnet model for accuracy)
- Extracts semantic meaning from changes
- Correlates with issue tracker references
- Identifies user impact
### Phase 4: Change Categorization
- Organizes changes following Keep a Changelog convention:
- Added: New features
- Changed: Changes in existing functionality
- Deprecated: Soon-to-be removed features
- Removed: Removed features
- Fixed: Bug fixes
- Security: Security-related changes
### Phase 5: Documentation Generation
- Creates technical entries for CHANGELOG.md:
- Comprehensive listing of all changes
- Technical details and implementation notes
- References to PRs, issues, and commits
- Breaking change warnings
- Creates user-focused entries for RELEASE_NOTES.md:
- High-level feature descriptions
- User benefits and value propositions
- Migration guides for breaking changes
- Screenshots/examples where applicable
### Phase 6: Review & Refinement
- Presents generated content for review
- Allows interactive editing and refinement
- Validates version numbering (semantic versioning)
- Checks for consistency and completeness
### Phase 7: Finalization
- Writes updated files with proper formatting
- Creates git commit for documentation updates
- Tags release if version specified
- Generates release announcement template (optional)
## Interactive Example
```
You: /changelog
Claude: I'll help you manage your changelog and release notes. Let me analyze your repository...
📊 Repository Analysis:
- Found existing CHANGELOG.md (last updated: 2025-11-01)
- Found existing RELEASE_NOTES.md (last updated: 2025-11-01)
- Current version: v2.3.1
- 47 commits since last update
What would you like to do?
1. Update both files with recent changes
2. Prepare a new release (with version bump)
3. Review and refine existing entries
4. Generate release announcement
You: 1
Claude: Analyzing 47 commits since 2025-11-01...
🔍 Identified Changes:
- 3 new features
- 12 improvements
- 8 bug fixes
- 2 breaking changes
- 1 security update
Let me group these semantically and analyze their impact...
[Invokes git-history-analyzer agent]
[Invokes commit-analyst agent for complex changes]
[Invokes changelog-synthesizer agent]
📝 Generated CHANGELOG.md entries:
## [Unreleased]
### Added
- REST API v2 with pagination support (#234, @dev1)
- WebSocket real-time notifications (implements #189)
- Docker compose configuration for local development
### Changed
- **BREAKING:** Updated authentication to use JWT tokens instead of sessions
- Improved database query performance by 40% through indexing
- Migrated from Webpack to Vite for faster builds
### Fixed
- Memory leak in background job processor (#245)
- Incorrect timezone handling in scheduled tasks
- Race condition in concurrent file uploads
### Security
- Updated dependencies to patch CVE-2025-1234
📢 Generated RELEASE_NOTES.md entries:
## What's New
### 🚀 Real-time Notifications
Stay updated with instant WebSocket-powered notifications. No more manual refreshing!
### ⚡ 40% Faster Performance
We've optimized our database queries, making the app significantly more responsive.
### 🔒 Enhanced Security
Upgraded to JWT-based authentication for better security and seamless API access.
### 🐛 Stability Improvements
Fixed several bugs including memory leaks and timezone issues for a smoother experience.
⚠️ **Important:** This update changes how authentication works. You'll need to log in again after updating.
Would you like to:
1. Apply these changes
2. Edit before applying
3. Generate more detailed entries
4. Cancel
You: 1
Claude: ✅ Successfully updated:
- CHANGELOG.md (23 new entries added)
- RELEASE_NOTES.md (4 user-facing updates added)
Created commit: "docs: Update changelog and release notes for unreleased changes"
Next steps:
- Review the updated files
- Consider creating a release with `/changelog release v2.4.0`
- Share release notes with your team
```
## Configuration Options
Create `.changelog.yaml` in your repository root to customize behavior:
```yaml
# Changelog configuration
changelog:
# Use conventional commits for automatic categorization
conventional_commits: true
# Include commit hashes in CHANGELOG.md
include_commit_hash: true
# Include author attribution
include_authors: true
# Group commits by these criteria
grouping:
- pull_request
- feature_branch
- semantic_similarity
# Categories to use (Keep a Changelog format)
categories:
- Added
- Changed
- Deprecated
- Removed
- Fixed
- Security
# Breaking change indicators
breaking_indicators:
- "BREAKING CHANGE:"
- "BREAKING:"
- "!:" # Conventional commit breaking change
# Release notes configuration
release_notes:
# Target audience
audience: "end-users" # or "developers", "stakeholders"
# Tone
tone: "professional" # or "casual", "technical"
# Include screenshots/gifs
include_visuals: false
# Emoji usage
use_emoji: true
# Maximum entries per category
max_entries: 5
# Version management
versioning:
# Semantic versioning strategy
strategy: "semver" # or "calver", "custom"
# Auto-bump rules
auto_bump:
breaking: "major"
features: "minor"
fixes: "patch"
# AI analysis settings
ai_analysis:
# Model for commit analysis
model: "claude-4-5-sonnet" # Fast and efficient for code analysis
# Analyze commits with unclear messages
analyze_unclear: true
# Analyze large diffs for better understanding
analyze_large_diffs: true
# Threshold for "large" diff (lines changed)
large_diff_threshold: 100
# Project context integration (NEW - makes RELEASE_NOTES.md more end-user focused)
release_notes:
# Enable reading CLAUDE.md, README.md, and docs/ for context
project_context_enabled: true
project_context_sources:
- "CLAUDE.md"
- "README.md"
- "docs/**/*.md"
project_context_max_length: 5000
project_context_cache_ttl_hours: 24
# Custom instructions (highest priority - override extracted context)
emphasis_areas: ["Security", "Performance", "User Experience"]
de_emphasize: ["refactor", "chore", "build", "ci", "deps"]
include_internal_changes: false # Exclude internal changes from release notes
user_impact_keywords: ["user", "customer", "performance", "faster"]
terminology:
authentication: "sign-in system"
API: "developer tools"
```
## Agent Orchestration
**CRITICAL**: You MUST use the Task tool to invoke these agents in sequence. The workflow will fail if you don't invoke agents properly.
### Agent Invocation Sequence
Invoke agents using the Task tool in this exact order:
#### 1. Project Context Extractor (Claude Haiku)
```
Use Task tool with:
- subagent_type: "changelog-manager:project-context-extractor"
- description: "Extract project context from documentation"
- prompt: "Analyze CLAUDE.md, README.md, and docs/ to extract project context, target audience, feature catalog, and tone guidance for generating user-focused release notes."
```
**Purpose**: Reads project documentation to understand product vision, target audience, user personas, and how to translate technical changes into user benefits.
**Output**: Project context object with feature catalog, tone guidance, and custom instructions.
#### 2. Git History Analyzer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:git-history-analyzer"
- description: "Analyze git history and group commits"
- prompt: "Extract commits since last update, group by pull request/feature branch/semantic similarity, categorize changes following Keep a Changelog format, and detect breaking changes."
```
**Purpose**: Examines commit history, groups related changes, categorizes them, and identifies breaking changes.
**Output**: Structured change data categorized as Added/Changed/Fixed/etc.
#### 3. GitHub Matcher (Claude Sonnet) - OPTIONAL
```
Only invoke if:
- GitHub remote detected
- gh CLI available and authenticated
- integrations.github.matching.enabled: true in config
Use Task tool with:
- subagent_type: "changelog-manager:github-matcher"
- description: "Match commits to GitHub artifacts"
- prompt: "Enrich commit data with GitHub Issue, PR, Project, and Milestone references using explicit matching, timestamp correlation, and semantic similarity."
```
**Purpose**: Matches commits to GitHub Issues, PRs, Projects, and Milestones using multiple strategies with confidence scoring.
**Output**: Enriched commit data with GitHub artifact references.
#### 4. Changelog Synthesizer (Claude Sonnet)
```
Use Task tool with:
- subagent_type: "changelog-manager:changelog-synthesizer"
- description: "Generate changelog documentation"
- prompt: "Generate CHANGELOG.md (technical, developer-focused) and RELEASE_NOTES.md (user-facing, benefits-focused) using project context to translate technical changes into user benefits."
```
**Purpose**: Combines all information to generate both technical and user-facing documentation, using project context to make RELEASE_NOTES.md more end-user focused.
**Output**: Final CHANGELOG.md and RELEASE_NOTES.md content.
### Integration Flow
```
project-context-extractor (Haiku)
↓ [project_context]
git-history-analyzer (Sonnet)
↓ [git_analysis]
github-matcher (Sonnet) [OPTIONAL]
↓ [enhanced_analysis]
changelog-synthesizer (Sonnet)
↓ [final_documents]
Write files
```
## Agents Used
This command coordinates multiple specialized agents:
- **project-context-extractor**: Reads project documentation (CLAUDE.md, README.md,
docs/) to understand product vision, target audience, and user-facing features
- **git-history-analyzer**: Examines commit history and groups related changes
- **commit-analyst**: Uses AI to understand complex commits and code changes (invoked automatically by git-history-analyzer when needed)
- **github-matcher**: Matches commits to GitHub Issues, PRs, Projects, and Milestones (optional, only if configured)
- **changelog-synthesizer**: Combines information to generate both technical and
user-facing documentation, using project context to make RELEASE_NOTES.md more
end-user focused
## Best Practices
1. **Regular Updates**: Run `/changelog update` frequently (e.g., weekly) to
avoid large batches
2. **Review Generated Content**: Always review AI-generated entries for accuracy
3. **Maintain Consistency**: Use the same categorization and format across
releases
4. **Version Strategically**: Follow semantic versioning for clear communication
5. **Separate Audiences**: Keep technical details in CHANGELOG.md, user value in
RELEASE_NOTES.md
## Tips
- Use `--dry-run` flag to preview changes without writing files
- Run `/changelog review` before releases to ensure quality
- Configure `.changelog.yaml` for project-specific conventions
- Tag releases in git after updating documentation
- Consider automating with git hooks or CI/CD pipelines
## Related Commands
- `/changelog init` - Initialize changelog files for a new project
- `/changelog release` - Prepare a new release with version bump
- `/git-history` - Explore git history in detail
- `/version` - Manage version numbers

81
plugin.lock.json Normal file
View File

@@ -0,0 +1,81 @@
{
"$schema": "internal://schemas/plugin.lock.v1.json",
"pluginId": "gh:mtr/marketplace:changelog-manager",
"normalized": {
"repo": null,
"ref": "refs/tags/v20251128.0",
"commit": "66500c4470ca8874e77037467915e5eeb0010bc2",
"treeHash": "ff34b8495327899e9f92b2a02838ccf7fdad74fcbb932de8aec57bb25d98365a",
"generatedAt": "2025-11-28T10:27:12.637592Z",
"toolVersion": "publish_plugins.py@0.2.0"
},
"origin": {
"remote": "git@github.com:zhongweili/42plugin-data.git",
"branch": "master",
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
},
"manifest": {
"name": "changelog-manager",
"description": "Intelligent CHANGELOG.md and RELEASE_NOTES.md management through git history analysis and AI-powered commit understanding with GitHub integration",
"version": "1.2.0"
},
"content": {
"files": [
{
"path": "README.md",
"sha256": "d784191a24aa7ed85bc5087c80d653272641d43c09ee62ffc5197a9deff7cd34"
},
{
"path": "agents/changelog-synthesizer.md",
"sha256": "0dcbbc3cf06076eac406a93fb59143081a8a734e93cd3047eff940f71c700d41"
},
{
"path": "agents/period-coordinator.md",
"sha256": "972e7e275fa51cca7db65615f3cbac329c52eb7aaa0461032897031e10296251"
},
{
"path": "agents/period-detector.md",
"sha256": "83754618585526d3e28ca1a2afb86dda844bf08b6c1642e5268e33b9bb746aaf"
},
{
"path": "agents/commit-analyst.md",
"sha256": "9314602c5f2f27eb35152c259715839311c1d7b5f11d1ace2756239bacc9ff4e"
},
{
"path": "agents/github-matcher.md",
"sha256": "97ff6ecc644d999b1c7eeb0cace1502f8a5b076abfc9a260a201a3a97482676a"
},
{
"path": "agents/project-context-extractor.md",
"sha256": "a4044af1b4dd1fa33fb1f100c9ded75af989bfb5346690a44a29645c1d15871b"
},
{
"path": "agents/git-history-analyzer.md",
"sha256": "a9e8236de96e412258b64abea37d3f42c80baa3c59b257430f7c669d377d77d7"
},
{
"path": ".claude-plugin/plugin.json",
"sha256": "c2e3809e7267cf5785a58245d941c9405fa516d269fb0451f1c221b23a276858"
},
{
"path": "commands/changelog.md",
"sha256": "1f625602a3ea46bbd14b7c19cfb609517ea4b13bd77dfefcc27702c7bea21a55"
},
{
"path": "commands/changelog-release.md",
"sha256": "00ebab97a1a79224593db2a0ab02a425f863ec493c2bb627101992ae7eea7f42"
},
{
"path": "commands/changelog-init.md",
"sha256": "a8b005aaf9bfb7469ee89f7c4bf43ca676e8899fbfc2b518e882d4340ec42aab"
}
],
"dirSha256": "ff34b8495327899e9f92b2a02838ccf7fdad74fcbb932de8aec57bb25d98365a"
},
"security": {
"scannedAt": null,
"scannerVersion": null,
"flags": []
}
}