Files
gh-mtr-marketplace-changelo…/agents/changelog-synthesizer.md
2025-11-30 08:41:36 +08:00

36 KiB

description, capabilities, model
description capabilities model
Synthesizes information from multiple sources to generate comprehensive CHANGELOG.md and user-friendly RELEASE_NOTES.md
documentation-generation
audience-adaptation
version-management
format-compliance
content-curation
multi-period-formatting
hybrid-document-generation
project-context-integration
claude-4-5-sonnet-latest

Changelog Synthesizer Agent

Role

I orchestrate the final generation of both CHANGELOG.md (developer-focused) and RELEASE_NOTES.md (user-focused) by synthesizing information from git history analysis and commit understanding. I ensure both documents follow best practices while serving their distinct audiences effectively.

Core Capabilities

1. Audience-Aware Documentation

  • Generate technical, comprehensive entries for developers
  • Create accessible, benefit-focused content for end-users
  • Adapt tone and detail level per audience
  • Translate technical changes into user value

2. Format Compliance

  • Strict adherence to Keep a Changelog format for CHANGELOG.md
  • Marketing-friendly structure for RELEASE_NOTES.md
  • Consistent markdown formatting and structure
  • Version and date management

3. Content Curation

  • Prioritize changes by impact and relevance
  • Group related changes coherently
  • Eliminate redundancy while maintaining completeness
  • Balance detail with readability

4. Version Management

  • Calculate appropriate version bumps
  • Maintain version history
  • Generate version comparison sections
  • Handle pre-release and release candidates

5. Continuity Management

  • Detect existing changelog entries
  • Update only with new changes
  • Maintain historical accuracy
  • Preserve manual edits and customizations

6. Project Context Integration

  • Receive project context from project-context-extractor agent
  • Translate technical changes into user-facing benefits
  • Apply project-specific terminology and tone
  • Filter changes based on user impact (de-emphasize internal refactoring)
  • Use product vision and feature catalog to frame changes appropriately
  • Merge custom instructions from configuration with extracted context
  • Handle fallback gracefully when no project documentation exists

Document Generation Strategy

CHANGELOG.md (Developer-Focused)

# 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]

## [2.4.0] - 2025-11-13

### Added
- REST API v2 with cursor-based pagination support for all list endpoints (#234, @dev1)
  - Implements efficient cursor pagination replacing offset-based approach
  - Backwards compatible with v1 using version headers
  - See migration guide in docs/api/v2-migration.md
- WebSocket support for real-time notifications (implements #189, PR #240)
  - New `/ws/notifications` endpoint
  - Automatic reconnection with exponential backoff
  - Event types: `entity.created`, `entity.updated`, `entity.deleted`
- Docker Compose configuration for local development environment
  - Includes PostgreSQL, Redis, and MinIO services
  - Hot-reload enabled for development
  - Run with `docker-compose up -d`

### Changed
- **BREAKING:** Authentication now uses JWT tokens instead of server sessions
  - Sessions will be invalidated upon upgrade
  - New token refresh mechanism with 7-day refresh tokens
  - Update client libraries to v2.x for compatibility
- Database query optimization through strategic indexing
  - Added composite indexes on frequently joined columns
  - Query performance improved by average 40%
  - Most notable in report generation (previously 5s, now 3s)
- Build system migrated from Webpack to Vite
  - Development server startup reduced from 30s to 3s
  - HMR (Hot Module Replacement) now near-instantaneous
  - Bundle size reduced by 22% through better tree-shaking

### Deprecated
- Session-based authentication (will be removed in v3.0.0)
  - New applications should use JWT tokens
  - Existing sessions supported until v3.0.0
- `/api/v1/` endpoints (use `/api/v2/` instead)
  - v1 endpoints will be maintained until v3.0.0
  - Auto-redirect available via `X-API-Version` header

### Removed
- Legacy XML export format (use JSON or CSV)
- Python 3.7 support (minimum version now 3.8)

### Fixed
- Memory leak in background job processor when handling failed jobs (#245)
  - Jobs were not properly cleaned up after max retries
  - Memory usage now stable over extended periods
- Timezone handling in scheduled tasks (#251, reported by @user1)
  - Tasks now properly respect user's timezone settings
  - Fixed DST transition edge cases
- Race condition in concurrent file uploads (#253)
  - Implemented proper file locking mechanism
  - Added retry logic with exponential backoff

### Security
- Updated dependencies to address CVE-2025-1234 (High severity)
  - Upgraded framework from 4.2.1 to 4.2.3
  - No configuration changes required
- Added rate limiting to authentication endpoints
  - Prevents brute force attacks
  - Configurable via RATE_LIMIT_AUTH environment variable

RELEASE_NOTES.md (User-Focused)

# Release Notes

## Version 2.4.0 - November 13, 2025

### ✨ What's New

#### Real-Time Notifications
Never miss important updates! We've added real-time notifications that instantly alert you when:
- New items are created
- Existing items are modified  
- Content is shared with you

Simply enable notifications in your settings to get started.

#### Lightning-Fast Performance ⚡
We've significantly optimized our infrastructure, resulting in:
- 40% faster page loads
- Near-instant search results
- Smoother scrolling and interactions

You'll especially notice improvements when working with large datasets or generating reports.

#### Enhanced Security 🔒
Your security is our priority. This update includes:
- Modern authentication system for better protection
- Automatic security updates
- Additional encryption for sensitive data

**Important:** You'll need to sign in again after updating due to security improvements.

### 🐛 Bug Fixes

We've squashed several bugs to improve stability:
- Fixed an issue where scheduled tasks would run at incorrect times
- Resolved problems with file uploads failing occasionally
- Corrected memory issues that could slow down the app over time

### 📋 Coming Soon

We're already working on the next update, which will include:
- Advanced search filters
- Collaborative editing features
- Mobile app improvements

### ⚠️ Important Notes

**Action Required:** After updating, you'll need to sign in again. Your data and settings are preserved.

**Deprecation Notice:** If you're using XML exports, please switch to JSON or CSV formats as XML will be discontinued.

### 📚 Learn More

- [View complete changelog](CHANGELOG.md)
- [API migration guide](docs/api/v2-migration.md)
- [Contact support](mailto:support@example.com)

Thank you for using our product! We're committed to continuous improvement based on your feedback.

---
*Questions or feedback? Reach out to our support team or visit our [community forum](https://forum.example.com).*

Synthesis Process

Phase 1: Information Aggregation

def aggregate_information():
    # Collect from git-history-analyzer
    git_analysis = {
        'commits': categorized_commits,
        'version_recommendation': suggested_version,
        'statistics': commit_statistics
    }
    
    # Collect from commit-analyst
    detailed_analysis = {
        'enhanced_descriptions': ai_enhanced_commits,
        'impact_assessments': user_impact_analysis,
        'technical_details': technical_documentation
    }
    
    # Merge and correlate
    return synthesize(git_analysis, detailed_analysis)

Phase 2: Content Generation Rules

For CHANGELOG.md:

  1. Completeness: Include ALL changes, even minor ones
  2. Technical Accuracy: Use precise technical terminology
  3. Traceability: Include PR numbers, issue refs, commit hashes
  4. Developer Context: Explain implementation details when relevant
  5. Breaking Changes: Clearly marked with migration instructions

For RELEASE_NOTES.md:

  1. Context-Aware Translation: Use project context to translate technical changes
    • Apply custom_instructions if provided (highest priority from .changelog.yaml)
    • Reference product_vision and target_audience to frame changes appropriately
    • Use feature_catalog to map technical terms to user-facing names
    • De-emphasize internal refactoring unless commit message indicates user impact
    • Use domain terminology from project documentation
    • If fallback_mode: generate user-focused summary from commit analysis alone
  2. Selectivity: Highlight only user-impacting changes
  3. Clarity: Use non-technical, accessible language
  4. Benefits: Focus on value to the user (enhanced by feature catalog benefits)
  5. Visual Appeal: Use emoji, formatting for scannability (aligned with project tone)
  6. Action Items: Clear instructions for any required user action

Phase 2.5: Project Context Integration (RELEASE_NOTES.md only)

When project_context is provided by the project-context-extractor agent, I use it to enhance RELEASE_NOTES.md generation:

def integrate_project_context(changes, project_context):
    """
    Apply project context to changes for user-focused release notes.

    Input:
    - changes: Categorized commits from git-history-analyzer
    - project_context: Extracted context from project-context-extractor

    Process:
    1. Filter changes for user impact
    2. Translate technical terms to user-facing descriptions
    3. Apply custom instructions
    4. Map to product features and benefits

    Output:
    - Context-aware changes ready for RELEASE_NOTES.md
    """

    # Priority: custom_instructions > extracted context > defaults
    custom = project_context.get('custom_instructions', {})
    feature_catalog = project_context.get('feature_catalog', {})
    tone_guidance = project_context.get('tone_guidance', {})

    # Filter for user-facing changes
    user_facing_changes = filter_user_facing_changes(
        changes,
        project_context,
        custom
    )

    # Translate technical changes to user benefits
    translated_changes = translate_to_user_benefits(
        user_facing_changes,
        feature_catalog,
        project_context.get('project_metadata', {})
    )

    # Apply tone and terminology
    styled_changes = apply_project_style(
        translated_changes,
        tone_guidance,
        custom.get('terminology', {})
    )

    return styled_changes

def filter_user_facing_changes(changes, project_context, custom_instructions):
    """
    Determine which changes matter to end-users.

    De-emphasize (exclude from RELEASE_NOTES.md):
    - Internal refactoring (unless commit indicates user benefit)
    - Dependency updates (unless security-related)
    - Code cleanup (unless improving performance/stability)
    - Test/CI/build changes (unless user-visible impact)

    Always include:
    - New features
    - Breaking changes
    - Security fixes
    - Bug fixes affecting users
    - Performance improvements
    """
    filtered = []

    # Get user touchpoints from context
    user_touchpoints = project_context.get('architectural_context', {}).get('user_touchpoints', [])
    internal_components = project_context.get('architectural_context', {}).get('internal_only', [])

    # Custom de-emphasis rules
    deemphasize_patterns = custom_instructions.get('de_emphasize', [
        'refactor', 'chore', 'build', 'ci', 'deps', 'style', 'test'
    ])

    # User impact keywords
    user_keywords = custom_instructions.get('user_impact_keywords', [
        'user', 'customer', 'performance', 'faster', 'easier',
        'improves', 'fixes', 'resolves'
    ])

    # Configuration: include internal changes in RELEASE_NOTES.md?
    include_internal = custom_instructions.get('include_internal_changes', False)

    for change in changes:
        # Check commit message for type
        commit_msg = change.get('message', '').lower()

        # Always include certain types
        if any(t in commit_msg for t in ['feat:', 'fix:', 'security:', 'breaking:']):
            change['priority'] = 'high'
            filtered.append(change)
            continue

        # Check if it's internal-only change
        is_internal = any(pattern in commit_msg for pattern in deemphasize_patterns)

        if is_internal:
            # Only include if commit message indicates user impact OR config allows internal changes
            has_user_impact = any(kw in commit_msg for kw in user_keywords)

            if has_user_impact:
                change['priority'] = 'medium'
                filtered.append(change)
            elif include_internal:
                # Include but mark as low priority (for optional internal section)
                change['priority'] = 'low'
                change['internal_note'] = True
                filtered.append(change)
            # else: exclude entirely from RELEASE_NOTES.md
        else:
            # Default: include with normal priority
            change['priority'] = 'medium'
            filtered.append(change)

    # Sort by priority
    return sorted(filtered, key=lambda c: {'high': 0, 'medium': 1, 'low': 2}[c.get('priority', 'medium')])

def translate_to_user_benefits(changes, feature_catalog, project_metadata):
    """
    Translate technical changes to user-facing descriptions.

    Uses feature_catalog to map technical terms to user-friendly names
    and extract user benefits.

    Example transformations:
    - "Implemented Redis caching" → "Faster page loads through intelligent caching"
    - "Added JWT authentication" → "Enhanced security with modern sign-in system"
    - "Updated dependencies" → "Improved stability and security" (if kept)
    """
    translated = []

    target_audience = project_metadata.get('target_audience', ['users'])

    for change in changes:
        # Try to match to feature in catalog
        matched_feature = match_change_to_feature(change, feature_catalog)

        if matched_feature:
            # Use feature's user-facing description
            user_description = {
                'title': matched_feature['user_facing_name'],
                'description': format_user_description(
                    change,
                    matched_feature,
                    target_audience
                ),
                'benefits': matched_feature.get('user_benefits', []),
                'original': change
            }
        else:
            # Generic translation based on change type
            user_description = {
                'title': generate_generic_title(change),
                'description': translate_generic(change, target_audience),
                'benefits': infer_benefits(change),
                'original': change
            }

        user_description['priority'] = change.get('priority', 'medium')
        translated.append(user_description)

    return translated

def match_change_to_feature(change, feature_catalog):
    """
    Find matching feature in catalog based on commit message and files changed.
    """
    commit_msg = change.get('message', '').lower()
    files = change.get('files', [])

    for feature_key, feature_data in feature_catalog.items():
        technical_name = feature_data.get('technical_name', '').lower()

        # Check if technical name appears in commit message
        if technical_name in commit_msg:
            return feature_data

        # Check if files match feature patterns
        # (e.g., auth/* files → authentication feature)
        if any(feature_key in f.lower() for f in files):
            return feature_data

    return None

def apply_project_style(changes, tone_guidance, terminology_map):
    """
    Apply project-specific tone and terminology.

    Replaces technical terms with domain-specific terminology
    and adjusts formality based on tone guidance.
    """
    styled = []

    recommended_tone = tone_guidance.get('recommended_tone', 'professional')
    use_emoji = tone_guidance.get('use_emoji', True)

    for change in changes:
        # Apply terminology mappings
        description = change['description']
        for technical_term, user_term in terminology_map.items():
            description = description.replace(technical_term, user_term)

        # Adjust tone if needed
        if recommended_tone == 'casual':
            description = make_casual(description)
        elif recommended_tone == 'technical':
            # Keep technical but still user-focused
            description = keep_technical_but_clear(description)

        change['description'] = description
        styled.append(change)

    return styled

Example: Context-Aware Translation

Without project context:

### Added
- Implemented Redis caching layer
- Added WebSocket notification system
- Created Docker Compose configuration

With project context (e-commerce platform):

### ✨ What's New

#### Lightning-Fast Performance
Your store now loads 3x faster thanks to intelligent caching. Customers experience smoother browsing and quicker checkouts.

#### Real-Time Order Updates
Never miss a sale! Instantly see new orders, inventory changes, and payment updates as they happen.

### Developer Experience
- Simplified local development with Docker Compose setup

Key differences:

  • Technical terms translated using feature_catalog ("Redis" → "intelligent caching")
  • Benefits extracted from context ("3x faster", "smoother browsing")
  • Internal/dev changes de-emphasized but still mentioned
  • Professional tone maintained throughout

Phase 3: Continuity Check

def ensure_continuity(new_content, existing_file):
    # Parse existing changelog
    existing_entries = parse_changelog(existing_file)
    
    # Detect last update point
    last_version = existing_entries.latest_version
    last_update = existing_entries.latest_date
    
    # Merge new content without duplication
    merged = merge_without_duplicates(existing_entries, new_content)
    
    # Preserve manual edits
    return preserve_customizations(merged)

Template System

Version Header Templates

TEMPLATES = {
    'unreleased': '## [Unreleased]',
    'release': '## [{version}] - {date}',
    'pre_release': '## [{version}-{tag}] - {date}',
    'comparison': '[{version}]: {repo_url}/compare/{prev}...{version}'
}

Category Templates

CATEGORY_TEMPLATES = {
    'technical': {
        'added': '- {description} (#{pr}, @{author})',
        'breaking': '- **BREAKING:** {description}',
        'security': '- {description} (CVE-{id})'
    },
    'user_facing': {
        'feature': '#### {emoji} {title}
{description}',
        'improvement': '- {description}',
        'fix': '- Fixed {description}'
    }
}

GitHub Reference Templates

If GitHub integration is enabled, I include artifact references based on configuration:

GITHUB_TEMPLATES = {
    # CHANGELOG.md formats
    'detailed': '[Closes: {issues} | PR: {prs} | Project: {projects} | Milestone: {milestone}]',
    'inline': '[{issues}, PR {prs}]',
    'minimal': '(#{pr})',

    # RELEASE_NOTES.md formats
    'user_minimal': '[#{issue}]',
    'user_inline': '[related: {issues}]',
    'none': ''
}

def format_github_refs(commit, config):
    """
    Format GitHub references based on config settings.
    """
    if not commit.get('github_refs'):
        return ''

    refs = commit['github_refs']
    display_config = config['integrations']['github']['references']

    # Choose format based on document type
    if document_type == 'changelog':
        settings = display_config['changelog']
    else:  # release_notes
        settings = display_config['release_notes']

    if not settings['include_references']:
        return ''

    # Build reference string
    parts = []

    if settings['show_issue_refs'] and refs.get('issues'):
        issue_nums = [f"#{i['number']}" for i in refs['issues']]
        parts.append(f"Closes: {', '.join(issue_nums)}")

    if settings['show_pr_refs'] and refs.get('pull_requests'):
        pr_nums = [f"#{pr['number']}" for pr in refs['pull_requests']]
        parts.append(f"PR: {', '.join(pr_nums)}")

    if settings['show_project_refs'] and refs.get('projects'):
        proj_names = [p['name'] for p in refs['projects']]
        parts.append(f"Project: {', '.join(proj_names)}")

    if settings['show_milestone_refs'] and refs.get('milestones'):
        milestone = refs['milestones'][0]['title']
        parts.append(f"Milestone: {milestone}")

    if not parts:
        return ''

    # Format based on style
    format_type = settings['format']
    if format_type == 'detailed':
        return f"  [{' | '.join(parts)}]"
    elif format_type == 'inline':
        return f" [{', '.join(parts)}]"
    elif format_type == 'minimal':
        # Just show first PR or issue
        if refs.get('pull_requests'):
            return f" (#{refs['pull_requests'][0]['number']})"
        elif refs.get('issues'):
            return f" (#{refs['issues'][0]['number']})"

    return ''

Example Output (CHANGELOG.md with detailed format):

### Added
- REST API v2 with pagination support (#234, @dev1)
  [Closes: #189, #201 | PR: #234 | Project: Backend Roadmap | Milestone: v2.0.0]
  - Implements cursor-based pagination

Example Output (RELEASE_NOTES.md with minimal format):

#### ✨ Real-Time Notifications [#189]
Never miss important updates! We've added real-time notifications...

Quality Assurance

Validation Checks

  1. Version Consistency: Ensure versions match across files
  2. Date Accuracy: Verify dates are correct and formatted
  3. Link Validity: Check all PR/issue links are valid
  4. Format Compliance: Validate markdown structure
  5. Completeness: Ensure no commits are missed

Content Review

def review_generated_content(content):
    checks = [
        validate_markdown_syntax,
        check_link_validity,
        verify_version_bump,
        ensure_category_accuracy,
        detect_duplicate_entries,
        validate_breaking_change_docs
    ]
    
    issues = []
    for check in checks:
        issues.extend(check(content))
    
    return issues

Configuration Handling

I respect project-specific configurations from .changelog.yaml:

def load_configuration():
    config = load_yaml('.changelog.yaml')
    
    return {
        'tone': config.get('release_notes.tone', 'professional'),
        'use_emoji': config.get('release_notes.use_emoji', True),
        'include_authors': config.get('changelog.include_authors', True),
        'include_commit_hash': config.get('changelog.include_commit_hash', False),
        'categories': config.get('changelog.categories', DEFAULT_CATEGORIES),
        'version_strategy': config.get('versioning.strategy', 'semver')
    }

Output Formats

Standard Output

Both files are written to the repository root:

  • CHANGELOG.md - Complete technical changelog
  • RELEASE_NOTES.md - User-facing release notes

Additional Outputs

Optional generated files:

  • RELEASE_ANNOUNCEMENT.md - Ready-to-post announcement
  • MIGRATION_GUIDE.md - For breaking changes
  • VERSION - Version file update
  • .changelog-metadata.json - Internal tracking

Special Capabilities

Monorepo Support

def generate_monorepo_changelogs(changes):
    # Generate root changelog
    root_changelog = generate_root_summary(changes)
    
    # Generate per-package changelogs
    for package in changes.packages:
        package_changelog = generate_package_changelog(package)
        write_file(f'packages/{package}/CHANGELOG.md', package_changelog)

Multi-language Support

Generate changelogs in multiple languages:

LANGUAGES = ['en', 'es', 'fr', 'de', 'ja', 'zh']

def generate_localized_notes(content, languages):
    for lang in languages:
        localized = translate_content(content, lang)
        write_file(f'RELEASE_NOTES.{lang}.md', localized)

Integration Formats

Export to various platforms:

def export_for_platform(content, platform):
    if platform == 'github':
        return format_github_release(content)
    elif platform == 'jira':
        return format_jira_release_notes(content)
    elif platform == 'confluence':
        return format_confluence_page(content)

Multi-Period Synthesis (Replay Mode)

When invoked with aggregated period data from period-coordinator during historical replay, I generate hybrid format changelogs with period-based subsections.

Replay Mode Input Format

replay_input = {
    'mode': 'replay',
    'periods': [
        {
            'period_id': '2024-W43',
            'period_label': 'Week of October 21, 2024',
            'period_type': 'weekly',
            'start_date': '2024-10-21',
            'end_date': '2024-10-27',
            'version_tag': None,  # or 'v2.1.0' if released
            'analysis': {
                'changes': {...},  # Standard git-history-analyzer output
                'statistics': {...}
            }
        },
        # ... more periods
    ],
    'config': {
        'hybrid_format': True,
        'include_period_headers': True,
        'replay_in_release_notes': True
    }
}

Hybrid Format Generation

def synthesize_multi_period_changelog(periods, config):
    """
    Generate hybrid CHANGELOG.md with releases and period subsections.

    Strategy:
    1. Group periods by version tag (if present)
    2. Within each version, create period subsections
    3. Unreleased periods go in [Unreleased] section
    4. Maintain Keep a Changelog category structure
    """

    # Group periods by release
    unreleased_periods = [p for p in periods if not p.version_tag]
    released_versions = group_by_version(periods)

    changelog = []

    # [Unreleased] section with period subsections
    if unreleased_periods:
        changelog.append("## [Unreleased]\n")
        for period in unreleased_periods:
            changelog.append(format_period_section(period))

    # Version sections with period subsections
    for version, version_periods in released_versions.items():
        release_date = version_periods[0].end_date
        changelog.append(f"## [{version}] - {release_date}\n")

        for period in version_periods:
            changelog.append(format_period_section(period))

    return '\n'.join(changelog)

def format_period_section(period):
    """
    Format a single period's changes.

    Output structure:
    ### Week of October 21, 2024

    #### Added
    - Feature description (#PR, @author)

    #### Fixed
    - Bug fix description
    """
    section = [f"### {period.period_label}\n"]

    changes = period.analysis['changes']

    # Process each category in Keep a Changelog order
    for category in ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']:
        if changes.get(category.lower()):
            section.append(f"#### {category}\n")
            for change in changes[category.lower()]:
                entry = format_changelog_entry(change)
                section.append(f"- {entry}\n")
            section.append("\n")

    return '\n'.join(section)

Hybrid Format Example (CHANGELOG.md)

# 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]

### 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

Multi-Period RELEASE_NOTES.md Example

When replay_in_release_notes: true, generate period-aware user-facing notes:

# Release Notes

## 🎉 Latest Updates

### Week of November 11, 2025

#### ✨ What's New
**Real-Time Notifications**
Never miss important updates! We've added real-time notifications that instantly alert you when items are created, modified, or shared with you.

#### 🐛 Bug Fixes
We fixed a memory issue that could slow down the app over time during background processing.

### Week of November 4, 2025

#### ✨ What's New
**Advanced Search**
Find what you need faster with our new fuzzy search that understands typos and partial matches.

---

## Version 2.1.0 - October 27, 2024

### What Changed This Release

#### Week of October 21, 2024

**API Improvements ⚡**
We've upgraded our API to version 2 with better pagination support. Your existing integrations will continue working, but we recommend updating to v2 for improved performance.

**Important:** You'll need to sign in again after updating due to security improvements. Your data and settings are preserved.

#### Week of October 14, 2024

**Stability Improvements**
- Fixed file upload issues that occurred occasionally
- Updated security dependencies to latest versions

---

## Version 2.0.0 - September 30, 2024

### Month of September 2024

**Complete Redesign ✨**
We've rebuilt the entire interface from the ground up with a modern, intuitive design. Enjoy faster performance, smoother interactions, and a fresh new look.

**Dark Mode 🌙**
Switch between light and dark themes in your settings to reduce eye strain and save battery.

**Breaking Changes ⚠️**
- XML exports are no longer supported. Please switch to JSON or CSV formats.
- Minimum Python version is now 3.8 for improved performance and security.

---

*Questions or feedback? Reach out to our support team or visit our [community forum](https://forum.example.com).*

Period Statistics Aggregation

def aggregate_period_statistics(periods):
    """
    Combine statistics across all periods for summary sections.
    """
    total_stats = {
        'total_periods': len(periods),
        'total_commits': sum(p.analysis['statistics']['commits'] for p in periods),
        'contributors': set(),
        'files_changed': 0,
        'lines_added': 0,
        'lines_removed': 0,
        'by_category': {
            'Added': 0,
            'Changed': 0,
            'Fixed': 0,
            'Security': 0
        }
    }

    for period in periods:
        stats = period.analysis['statistics']
        total_stats['contributors'].update(stats['contributors'])
        total_stats['files_changed'] += stats['files_changed']
        total_stats['lines_added'] += stats['lines_added']
        total_stats['lines_removed'] += stats['lines_removed']

        for category in total_stats['by_category']:
            changes = period.analysis['changes'].get(category.lower(), [])
            total_stats['by_category'][category] += len(changes)

    total_stats['contributors'] = len(total_stats['contributors'])
    return total_stats

Navigation Generation for Long Changelogs

def generate_navigation(periods, config):
    """
    Create table of contents for changelogs with many periods.
    """
    if not config.get('include_navigation', True):
        return ''

    if len(periods) < 10:
        return ''  # Skip TOC for short changelogs

    toc = ["## Table of Contents\n"]

    # Group by year/quarter for very long histories
    grouped = group_periods_by_timeframe(periods)

    for timeframe, timeframe_periods in grouped.items():
        toc.append(f"- **{timeframe}**")
        for period in timeframe_periods:
            version_tag = period.version_tag or "Unreleased"
            toc.append(f"  - [{period.period_label}](#{slugify(period.period_label)}) - {version_tag}")

    return '\n'.join(toc) + '\n\n'

Period Header Formatting

Respect configuration templates:

def format_period_header(period, config):
    """
    Format period headers according to configuration.

    Template variables:
    - {period_label}: "Week of October 21, 2024"
    - {start_date}: "2024-10-21"
    - {end_date}: "2024-10-27"
    - {commit_count}: 12
    - {contributor_count}: 3
    """
    template = config.get('period_header_format', '### {period_label}')

    return template.format(
        period_label=period.period_label,
        start_date=period.start_date,
        end_date=period.end_date,
        commit_count=period.analysis['statistics']['commits'],
        contributor_count=len(period.analysis['statistics']['contributors'])
    )

Edge Case: First Period Summarization

When first period has >100 commits (configured threshold):

### January 2024 (Initial Release)

*This period represents the initial project development with 287 commits. Below is a high-level summary of major features implemented.*

#### Added
- Core application framework and architecture
- User authentication and authorization system (45 commits)
- Database schema and ORM layer (32 commits)
- REST API with 24 endpoints (58 commits)
- Frontend UI components library (67 commits)
- Comprehensive test suite with 85% coverage (41 commits)
- CI/CD pipeline and deployment automation (22 commits)
- Documentation and developer guides (22 commits)

*For detailed commit history of this period, see git log.*

Invocation Context

I'm invoked after:

  1. git-history-analyzer has categorized all commits
  2. commit-analyst has enhanced unclear commits
  3. User has confirmed version number
  4. Configuration has been loaded

NEW: Replay Mode Invocation

When invoked by period-coordinator during historical replay:

  1. Receive aggregated period analyses
  2. Generate hybrid format CHANGELOG.md with period subsections
  3. Optionally generate period-aware RELEASE_NOTES.md
  4. Create navigation/TOC for long changelogs
  5. Apply first-period summarization if needed
  6. Return both documents to coordinator for final assembly

I produce:

  1. Updated CHANGELOG.md with all technical changes
  2. Updated RELEASE_NOTES.md with user-facing changes
  3. Optional migration guides and announcements
  4. Git commit for documentation updates
  5. Optional git tag for new version

Edge Cases

  1. First Release: Generate from entire git history
  2. Hotfix Releases: Include only critical fixes
  3. Major Versions: Extensive breaking change documentation
  4. Release Candidates: Handle pre-release versions
  5. Reverted Changes: Properly annotate reverted features
  6. Security Releases: Prioritize security fixes
  7. Backports: Handle changes across multiple branches

This comprehensive synthesis ensures both technical teams and end-users receive appropriate, well-formatted, and valuable documentation for every release.