
Confluence Expert
- 121 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
Author, structure, and maintain Confluence spaces, pages, macros, and team knowledge bases with consistent templates and navigation.
About
Confluence-expert guides Claude through Atlassian Confluence authoring: space layout, page templates, macros, labels, permissions-aware publishing, and linking engineering docs to product context for SaaS and platform teams.
- Confluence page and space structuring
- Template-driven documentation workflows
- Macro and formatting best practices
- Cross-linking specs, ADRs, and runbooks
- Team knowledge-base maintenance patterns
Confluence Expert by the numbers
- 121 all-time installs (skills.sh)
- Ranked #618 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/borghei/claude-skills --skill confluence-expertAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 121 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Author, structure, and maintain Confluence spaces, pages, macros, and team knowledge bases with consistent templates and navigation.
Files
Atlassian Confluence Expert
Master-level expertise in Confluence space management, documentation architecture, content creation, macros, templates, and collaborative knowledge management.
Core Competencies
Space Architecture
- Design and create space hierarchies
- Organize knowledge by teams, projects, or topics
- Implement documentation taxonomies
- Configure space permissions and visibility
Content Creation
- Create structured pages with layouts
- Use macros for dynamic content
- Build templates for consistency
- Implement version control and change tracking
Collaboration & Governance
- Facilitate team documentation practices
- Implement review and approval workflows
- Manage content lifecycle
- Establish documentation standards
Integration & Automation
- Link Confluence with Jira
- Embed dynamic Jira reports
- Configure page watchers and notifications
- Set up content automation
Workflows
Space Creation
1. Determine space type (Team, Project, Knowledge Base, Personal) 2. Create space with clear name and description 3. Set space homepage with overview 4. Configure space permissions:
- View, Edit, Create, Delete
- Admin privileges
5. Create initial page tree structure 6. Add space shortcuts for navigation 7. HANDOFF TO: Teams for content population
Page Architecture
Best Practices:
- Use page hierarchy (parent-child relationships)
- Maximum 3 levels deep for navigation
- Consistent naming conventions
- Date-stamp meeting notes
Recommended Structure:
Space Home
├── Overview & Getting Started
├── Team Information
│ ├── Team Members & Roles
│ ├── Communication Channels
│ └── Working Agreements
├── Projects
│ ├── Project A
│ │ ├── Overview
│ │ ├── Requirements
│ │ └── Meeting Notes
│ └── Project B
├── Processes & Workflows
├── Meeting Notes (Archive)
└── Resources & ReferencesTemplate Creation
1. Identify repeatable content pattern 2. Create page with structure and placeholders 3. Add instructions in placeholders 4. Format with appropriate macros 5. Save as template 6. Share with space or make global 7. USE: References for advanced template patterns
Documentation Strategy
1. Assess current documentation state 2. Define documentation goals and audience 3. Organize content taxonomy and structure 4. Create templates and guidelines 5. Migrate existing documentation 6. Train teams on best practices 7. Monitor usage and adoption 8. REPORT TO: Senior PM on documentation health
Knowledge Base Management
Article Types:
- How-to guides
- Troubleshooting docs
- FAQs
- Reference documentation
- Process documentation
Quality Standards:
- Clear title and description
- Structured with headings
- Updated date visible
- Owner identified
- Reviewed quarterly
Essential Macros
Content Macros
Info, Note, Warning, Tip:
{info}
Important information here
{info}Expand:
{expand:title=Click to expand}
Hidden content here
{expand}Table of Contents:
{toc:maxLevel=3}Excerpt & Excerpt Include:
{excerpt}
Reusable content
{excerpt}
{excerpt-include:Page Name}Dynamic Content
Jira Issues:
{jira:JQL=project = PROJ AND status = "In Progress"}Jira Chart:
{jirachart:type=pie|jql=project = PROJ|statType=statuses}Recently Updated:
{recently-updated:spaces=@all|max=10}Content by Label:
{contentbylabel:label=meeting-notes|maxResults=20}Collaboration Macros
Status:
{status:colour=Green|title=Approved}Task List:
{tasks}
- [ ] Task 1
- [x] Task 2 completed
{tasks}User Mention:
@usernameDate:
{date:format=dd MMM yyyy}Page Layouts & Formatting
Two-Column Layout:
{section}
{column:width=50%}
Left content
{column}
{column:width=50%}
Right content
{column}
{section}Panel:
{panel:title=Panel Title|borderColor=#ccc}
Panel content
{panel}Code Block:
{code:javascript}
const example = "code here";
{code}Templates Library
Meeting Notes Template
**Date**: {date}
**Attendees**: @user1, @user2
**Facilitator**: @facilitator
## Agenda
1. Topic 1
2. Topic 2
## Discussion
- Key point 1
- Key point 2
## Decisions
{info}Decision 1{info}
## Action Items
{tasks}
- [ ] Action item 1 (@owner, due date)
- [ ] Action item 2 (@owner, due date)
{tasks}
## Next Steps
- Next meeting dateProject Overview Template
{panel:title=Project Quick Facts}
**Status**: {status:colour=Green|title=Active}
**Owner**: @owner
**Start Date**: DD/MM/YYYY
**End Date**: DD/MM/YYYY
**Budget**: $XXX,XXX
{panel}
## Executive Summary
Brief project description
## Objectives
1. Objective 1
2. Objective 2
## Key Stakeholders
| Name | Role | Responsibility |
|------|------|----------------|
| @user | PM | Overall delivery |
## Milestones
{jira:project=PROJ AND type=Epic}
## Risks & Issues
| Risk | Impact | Mitigation |
|------|--------|-----------|
| Risk 1 | High | Action plan |
## Resources
- [Design Docs](#)
- [Technical Specs](#)Decision Log Template
**Decision ID**: PROJ-DEC-001
**Date**: {date}
**Status**: {status:colour=Green|title=Approved}
**Decision Maker**: @decisionmaker
## Context
Background and problem statement
## Options Considered
1. Option A
- Pros:
- Cons:
2. Option B
- Pros:
- Cons:
## Decision
Chosen option and rationale
## Consequences
Expected outcomes and impacts
## Next Steps
- [ ] Action 1
- [ ] Action 2Sprint Retrospective Template
**Sprint**: Sprint XX
**Date**: {date}
**Team**: Team Name
## What Went Well
{info}
- Positive item 1
- Positive item 2
{info}
## What Didn't Go Well
{warning}
- Challenge 1
- Challenge 2
{warning}
## Action Items
{tasks}
- [ ] Improvement 1 (@owner)
- [ ] Improvement 2 (@owner)
{tasks}
## Metrics
**Velocity**: XX points
**Completed Stories**: X/X
**Bugs Found**: XSpace Permissions
Permission Levels
- View: Read-only access
- Edit: Modify existing pages
- Create: Add new pages
- Delete: Remove pages
- Admin: Full space control
Permission Schemes
Public Space:
- All users: View
- Team members: Edit, Create
- Space admins: Admin
Team Space:
- Team members: View, Edit, Create
- Team leads: Admin
- Others: No access
Project Space:
- Stakeholders: View
- Project team: Edit, Create
- PM: Admin
Content Governance
Review Cycles:
- Critical docs: Monthly
- Standard docs: Quarterly
- Archive docs: Annually
Archiving Strategy:
- Move outdated content to Archive space
- Label with "archived" and date
- Maintain for 2 years, then delete
- Keep audit trail
Content Quality Checklist:
- [ ] Clear, descriptive title
- [ ] Owner/author identified
- [ ] Last updated date visible
- [ ] Appropriate labels applied
- [ ] Links functional
- [ ] Formatting consistent
- [ ] No sensitive data exposed
Decision Framework
When to Escalate to Atlassian Admin:
- Need org-wide template
- Require cross-space permissions
- Blueprint configuration
- Global automation rules
- Space export/import
When to Collaborate with Jira Expert:
- Embed Jira queries and charts
- Link pages to Jira issues
- Create Jira-based reports
- Sync documentation with tickets
When to Support Scrum Master:
- Sprint documentation templates
- Retrospective pages
- Team working agreements
- Process documentation
When to Support Senior PM:
- Executive report pages
- Portfolio documentation
- Stakeholder communication
- Strategic planning docs
Handoff Protocols
FROM Senior PM:
- Documentation requirements
- Space structure needs
- Template requirements
- Knowledge management strategy
TO Senior PM:
- Documentation coverage reports
- Content usage analytics
- Knowledge gaps identified
- Template adoption metrics
FROM Scrum Master:
- Sprint ceremony templates
- Team documentation needs
- Meeting notes structure
- Retrospective format
TO Scrum Master:
- Configured templates
- Space for team docs
- Training on best practices
- Documentation guidelines
WITH Jira Expert:
- Jira-Confluence linking
- Embedded Jira reports
- Issue-to-page connections
- Cross-tool workflow
Best Practices
Writing Style:
- Use active voice
- Write scannable content (headings, bullets, short paragraphs)
- Include visuals and diagrams
- Provide examples
- Keep language simple and clear
Organization:
- Consistent naming conventions
- Meaningful labels
- Logical page hierarchy
- Related pages linked
- Clear navigation
Maintenance:
- Regular content audits
- Remove duplication
- Update outdated information
- Archive obsolete content
- Monitor page analytics
Analytics & Metrics
Usage Metrics:
- Page views per space
- Most visited pages
- Search queries
- Contributor activity
- Orphaned pages
Health Indicators:
- Pages without recent updates
- Pages without owners
- Duplicate content
- Broken links
- Empty spaces
Atlassian MCP Integration
Primary Tool: Confluence MCP Server
Key Operations:
- Create and manage spaces
- Create, update, and delete pages
- Apply templates and macros
- Manage page hierarchies
- Configure permissions
- Search content
- Extract documentation for analysis
Integration Points:
- Create documentation for Senior PM projects
- Support Scrum Master with ceremony templates
- Link to Jira issues for Jira Expert
- Provide templates for Template Creator
Troubleshooting
| Problem | Likely Cause | Resolution |
|---|---|---|
| Users cannot find existing documentation | Poor space/page hierarchy, missing labels, or unclear page titles | Restructure to max 3 levels deep; enforce descriptive naming conventions; add labels to all pages and use contentbylabel macro for discovery |
| Confluence search returns irrelevant results | Page titles are generic, content lacks keywords, or spaces have too many orphaned pages | Use specific, descriptive titles; add excerpt macros for search snippets; audit and remove orphaned pages quarterly |
| Pages become stale with outdated information | No content ownership model, no review cadence, or no visible "last updated" date | Assign a page owner to every active page; set quarterly review reminders; add {date} macro to show last update prominently |
| Space permissions are too permissive or too restrictive | Ad-hoc permission changes without a governance model; individual permissions used instead of groups | Reset to group-based permissions; define 3-4 standard permission schemes; audit permissions quarterly |
| Jira macros embedded in pages show errors or no data | JQL references deleted projects, or the viewer lacks Jira permissions for the referenced project | Verify JQL validity; ensure Confluence viewers also have Jira browse permissions for referenced projects |
| Content duplication across multiple spaces | No single source of truth policy; teams copy content instead of linking | Implement excerpt-include pattern for shared content; establish content ownership map; use cross-space linking instead of copying |
| Page tree becomes too deep (>5 levels) creating navigation fatigue | Organic growth without architectural review; no archiving strategy | Flatten hierarchy to max 3 levels; archive completed project pages; use labels and search instead of deep nesting |
Success Criteria
- 90%+ of active pages have a designated owner and a review date within the past 6 months
- Orphaned pages (no parent, no links, no views in 90 days) represent less than 5% of total content
- New team members can find onboarding documentation within 3 clicks from the space homepage
- Content duplication rate stays below 10% (measured by duplicate title or excerpt analysis)
- All spaces follow the standardized page architecture template (overview, team info, projects, processes, resources)
- Confluence adoption measured by monthly active editors exceeds 60% of licensed users
- Knowledge base articles resolve 40%+ of common questions without escalation to a person
Scope & Limitations
In Scope: Space creation and architecture, page hierarchy design, template creation and management, content governance (review cycles, archiving, quality standards), macro usage and dynamic content, documentation strategy, knowledge base management, Jira-Confluence integration, content analytics.
Out of Scope: Global Atlassian administration (hand off to atlassian-admin/), Jira project configuration (hand off to jira-expert/), template design and governance (hand off to atlassian-templates/), sprint execution artifacts (hand off to scrum-master/).
Limitations: Confluence Cloud has storage limits per plan tier that affect attachment-heavy spaces. Advanced analytics (page view trends, contributor activity) require Confluence Premium or marketplace apps. Space-level permissions cannot override more restrictive org-wide security policies set by atlassian-admin/. Content migration between spaces can break internal links and require manual fixup.
Integration Points
| Integration | Direction | What Flows |
|---|---|---|
jira-expert/ | Bidirectional | Jira macros in Confluence pages; Confluence page links in Jira issue descriptions |
atlassian-admin/ | Admin -> Confluence | Global templates, space permission schemes, blueprint configuration |
atlassian-templates/ | Templates -> Confluence | Designed templates deployed to spaces; template usage guidelines |
scrum-master/ | SM -> Confluence | Sprint ceremony documentation needs, team working agreement pages |
senior-pm/ | PM -> Confluence | Executive report pages, portfolio documentation, stakeholder communication |
delivery-manager/ | DM -> Confluence | Post-mortem documentation, runbooks, release notes pages |
Confluence Page Templates
Meeting Notes Template
# [Meeting Title] - [Date]
**Date:** [YYYY-MM-DD]
**Time:** [HH:MM - HH:MM]
**Location:** [Room/Video link]
**Attendees:** @[Name1], @[Name2], @[Name3]
**Note Taker:** @[Name]
## Agenda
1. [Topic 1]
2. [Topic 2]
3. [Topic 3]
## Discussion
### [Topic 1]
**Summary:**
[Key points discussed]
**Decisions:**
- [Decision 1]
- [Decision 2]
**Action Items:**
- [ ] [Action] - @[Owner] - [Due Date]
- [ ] [Action] - @[Owner] - [Due Date]
### [Topic 2]
**Summary:**
[Key points discussed]
**Decisions:**
- [Decision 1]
**Action Items:**
- [ ] [Action] - @[Owner] - [Due Date]
## Parking Lot
- [Item to discuss later]
- [Future topic]
## Next Meeting
**Date:** [YYYY-MM-DD]
**Agenda Topics:**
- [Topic 1]
- [Topic 2]---
Decision Log Template
# [Decision Title]
| Field | Value |
|-------|-------|
| **Status** | 🟢 Accepted / 🟡 Proposed / 🔴 Deprecated |
| **Date** | [YYYY-MM-DD] |
| **Deciders** | @[Name1], @[Name2] |
| **Stakeholders** | @[Name3], @[Name4] |
| **Related Decisions** | [Link to related decisions] |
## Context and Problem Statement
[Describe the context and problem that requires a decision. 2-3 paragraphs explaining:
- What situation led to this decision?
- What problem are we trying to solve?
- What constraints exist?]
## Decision
[Clearly state the decision made in 1-2 sentences]
### Details
[Provide additional details about the decision:
- What exactly will we do?
- How will it be implemented?
- What timeline?]
## Rationale
[Explain why this decision was made:
- What were the key factors?
- What evidence supports this?
- Why is this the best choice?]
## Consequences
### Positive Consequences
- ✅ [Benefit 1]
- ✅ [Benefit 2]
- ✅ [Benefit 3]
### Negative Consequences / Trade-offs
- ⚠️ [Trade-off 1]
- ⚠️ [Trade-off 2]
### Risks
- 🔴 [Risk 1] - Mitigation: [How we'll handle it]
- 🟡 [Risk 2] - Mitigation: [How we'll handle it]
## Alternatives Considered
### Alternative 1: [Name]
**Description:** [What is this alternative?]
**Pros:**
- [Pro 1]
- [Pro 2]
**Cons:**
- [Con 1]
- [Con 2]
**Why Not Chosen:** [Reason]
### Alternative 2: [Name]
[Same structure as above]
## Implementation Plan
1. [Step 1] - @[Owner] - [Date]
2. [Step 2] - @[Owner] - [Date]
3. [Step 3] - @[Owner] - [Date]
## Success Metrics
- [Metric 1]: [Target]
- [Metric 2]: [Target]
## Review Date
**Next Review:** [YYYY-MM-DD]
**Review Notes:** [Link to review page]
## References
- [Link 1]
- [Link 2]
- [Link 3]
---
*Updated: [Date] by @[Name]*---
Technical Specification Template
# [Feature/Component Name] Technical Specification
| Field | Value |
|-------|-------|
| **Status** | 🟡 Draft / 🟢 Approved / 🔴 Archived |
| **Author** | @[Name] |
| **Reviewers** | @[Name1], @[Name2] |
| **Date Created** | [YYYY-MM-DD] |
| **Last Updated** | [YYYY-MM-DD] |
| **JIRA Epic** | [ABC-123](link) |
## Overview
[1-2 paragraph summary of what this spec covers and why it matters]
## Goals and Non-Goals
### Goals
- [Goal 1]
- [Goal 2]
- [Goal 3]
### Non-Goals (Out of Scope)
- [Non-goal 1]
- [Non-goal 2]
## Background
[Context needed to understand this spec:
- What problem are we solving?
- What's the current state?
- Why now?]
## High-Level Design
### Architecture Diagram
[Insert diagram here]
### System Components
1. **[Component 1 Name]**
- Purpose: [What it does]
- Technology: [What it uses]
- Interfaces: [How it connects]
2. **[Component 2 Name]**
- Purpose: [What it does]
- Technology: [What it uses]
- Interfaces: [How it connects]
### Data Flow
[Describe how data flows through the system]
## Detailed Design
### Component 1: [Name]
**Purpose:** [Detailed purpose]
**Responsibilities:**
- [Responsibility 1]
- [Responsibility 2]
**API/Interface:**[API spec or interface definition]
**Data Model:**[Schema or data structure]
**Key Algorithms/Logic:**
[Describe any complex logic]
### Component 2: [Name]
[Same structure as Component 1]
## Database Schema
### Table: [table_name]
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PRIMARY KEY | Unique identifier |
| name | VARCHAR(255) | NOT NULL | Entity name |
| created_at | TIMESTAMP | NOT NULL | Creation timestamp |
### Indexes
- `idx_name` on `name` - For fast lookups
- `idx_created` on `created_at` - For temporal queries
## API Specification
### Endpoint: [Method] /api/path
**Purpose:** [What this endpoint does]
**Request:**{ "param1": "value", "param2": 123 }
**Response:**{ "result": "success", "data": {} }
**Error Handling:**
- 400: [Reason]
- 404: [Reason]
- 500: [Reason]
## Security Considerations
- [Security consideration 1]
- [Security consideration 2]
- [Authentication/Authorization approach]
- [Data encryption requirements]
## Performance Considerations
- [Expected load/throughput]
- [Scalability approach]
- [Caching strategy]
- [Performance targets]
## Testing Strategy
### Unit Tests
- [Test area 1]
- [Test area 2]
### Integration Tests
- [Test scenario 1]
- [Test scenario 2]
### Performance Tests
- [Load test plan]
- [Performance benchmarks]
## Deployment Plan
1. [Deployment step 1]
2. [Deployment step 2]
3. [Deployment step 3]
### Rollback Plan
[How to revert if issues occur]
## Monitoring and Alerting
- [Metric 1] - Alert threshold: [Value]
- [Metric 2] - Alert threshold: [Value]
- [Log tracking]
## Migration Plan (if applicable)
[How to migrate from current system]
## Dependencies
- [Dependency 1] - Why needed
- [Dependency 2] - Why needed
## Open Questions
- [ ] [Question 1] - @[Owner]
- [ ] [Question 2] - @[Owner]
## Future Considerations
- [Future enhancement 1]
- [Future enhancement 2]
## References
- [Link to related specs]
- [Link to design docs]
- [Link to JIRA epics]
---
*For questions, contact @[Author]*---
How-To Guide Template
# How to [Task Name]
## Overview
[1-2 sentences explaining what this guide covers and who it's for]
**Estimated Time:** [X minutes]
**Difficulty:** [Beginner/Intermediate/Advanced]
## Prerequisites
Before you begin, ensure you have:
- [ ] [Prerequisite 1]
- [ ] [Prerequisite 2]
- [ ] [Prerequisite 3]
## Quick Summary (TL;DR)
[One paragraph with the essence of the guide for those who just need a reminder]
## Step-by-Step Instructions
### Step 1: [Action]
[Detailed description of what to do]
**Commands/Code:**command here
**Expected Result:**
[What you should see if it worked]
**Screenshot:**
[Add screenshot if helpful]
### Step 2: [Action]
[Detailed description]
**Tips:**
- 💡 [Helpful tip]
- ⚠️ [Warning about common mistake]
### Step 3: [Action]
[Continue pattern...]
## Verification
To verify everything worked:
1. [Check 1]
2. [Check 2]
## Troubleshooting
### Problem: [Common issue]
**Symptoms:** [What you see]
**Cause:** [Why it happens]
**Solution:**
1. [Fix step 1]
2. [Fix step 2]
### Problem: [Another issue]
[Same structure as above]
## Best Practices
- [Best practice 1]
- [Best practice 2]
- [Best practice 3]
## Related Guides
- [Link to related guide 1]
- [Link to related guide 2]
## Need Help?
- Questions? Ask in #[channel]
- Issues? Create ticket in [JIRA project]
- Contact: @[Expert name]
---
*Last updated: [Date] by @[Name]*---
Requirements Document Template
# [Feature/Project Name] Requirements
| Field | Value |
|-------|-------|
| **Status** | 🟡 Draft / 🟢 Approved / 🔵 In Progress / ✅ Complete |
| **Product Owner** | @[Name] |
| **Stakeholders** | @[Name1], @[Name2] |
| **Target Release** | [Release version] |
| **JIRA Epic** | [ABC-123](link) |
| **Created** | [YYYY-MM-DD] |
| **Last Updated** | [YYYY-MM-DD] |
## Executive Summary
[2-3 sentences describing the feature and its business value]
## Business Goals
- [Goal 1]: [Metric]
- [Goal 2]: [Metric]
- [Goal 3]: [Metric]
## User Stories
### Story 1: [Title]
**As a** [user type]
**I want** [goal]
**So that** [benefit]
**Acceptance Criteria:**
- [ ] [Criterion 1]
- [ ] [Criterion 2]
- [ ] [Criterion 3]
**Priority:** [High/Medium/Low]
**Effort:** [Story points]
### Story 2: [Title]
[Same structure as Story 1]
## Functional Requirements
### FR-001: [Requirement Title]
**Description:** [What the system must do]
**Rationale:** [Why this is needed]
**Acceptance Criteria:**
- [Criterion 1]
- [Criterion 2]
**Priority:** [Must Have / Should Have / Could Have / Won't Have]
### FR-002: [Requirement Title]
[Same structure as FR-001]
## Non-Functional Requirements
### Performance
- [Requirement 1]
- [Requirement 2]
### Security
- [Requirement 1]
- [Requirement 2]
### Scalability
- [Requirement 1]
- [Requirement 2]
### Accessibility
- [Requirement 1]
- [Requirement 2]
## User Experience
### Wireframes
[Insert wireframes or link to Figma]
### User Flow
[Diagram showing user journey]
### UI Requirements
- [UI requirement 1]
- [UI requirement 2]
## Technical Constraints
- [Constraint 1]
- [Constraint 2]
- [Constraint 3]
## Dependencies
| Dependency | Owner | Status | Impact if Blocked |
|------------|-------|--------|-------------------|
| [Dep 1] | @[Name] | 🟢 Ready | [Impact] |
| [Dep 2] | @[Name] | 🟡 In Progress | [Impact] |
## Success Metrics
| Metric | Baseline | Target | How Measured |
|--------|----------|--------|--------------|
| [Metric 1] | [Current] | [Goal] | [Method] |
| [Metric 2] | [Current] | [Goal] | [Method] |
## Risks and Mitigations
| Risk | Impact | Probability | Mitigation |
|------|--------|-------------|------------|
| [Risk 1] | High | Medium | [Strategy] |
| [Risk 2] | Medium | Low | [Strategy] |
## Out of Scope
- [Explicitly excluded 1]
- [Explicitly excluded 2]
## Open Questions
- [ ] [Question 1] - @[Owner] - [Due date]
- [ ] [Question 2] - @[Owner] - [Due date]
## Timeline
| Phase | Start Date | End Date | Deliverables |
|-------|-----------|----------|--------------|
| Design | [Date] | [Date] | [Deliverable] |
| Development | [Date] | [Date] | [Deliverable] |
| Testing | [Date] | [Date] | [Deliverable] |
| Launch | [Date] | [Date] | [Deliverable] |
## Approval
### Reviewers
- [ ] Product Owner: @[Name]
- [ ] Engineering Lead: @[Name]
- [ ] Design Lead: @[Name]
- [ ] Stakeholder: @[Name]
**Approved Date:** [YYYY-MM-DD]
## References
- [Market research]
- [User feedback]
- [Technical specs]
- [Related features]
---
*For questions, contact @[Product Owner]*---
Retrospective Template
# Sprint [N] Retrospective - [Team Name]
**Date:** [YYYY-MM-DD]
**Sprint:** [Sprint N]
**Sprint Dates:** [Start Date] - [End Date]
**Facilitator:** @[Name]
**Participants:** @[Name1], @[Name2], @[Name3]
## Sprint Metrics
- **Velocity:** [X points] (Average: [Y points])
- **Committed:** [X points / N issues]
- **Completed:** [Y points / M issues]
- **Sprint Goal Met:** ✅ Yes / ❌ No
## What Went Well 😊
- [Positive 1]
- [Positive 2]
- [Positive 3]
## What Didn't Go Well 😞
- [Challenge 1]
- [Challenge 2]
- [Challenge 3]
## Action Items from Last Retro
- [✅ / ❌] [Action item 1] - @[Owner]
- Status: [Done / In Progress / Not Done]
- Notes: [Update]
- [✅ / ❌] [Action item 2] - @[Owner]
- Status: [Done / In Progress / Not Done]
- Notes: [Update]
## Discussion Themes
### Theme 1: [Topic]
**What we discussed:**
[Summary of discussion]
**Root cause:**
[What's really causing this issue?]
**Ideas for improvement:**
- [Idea 1]
- [Idea 2]
### Theme 2: [Topic]
[Same structure as Theme 1]
## Action Items for Next Sprint
| Action | Owner | Due Date | Success Criteria |
|--------|-------|----------|------------------|
| [Action 1] | @[Name] | [Date] | [How we know it's done] |
| [Action 2] | @[Name] | [Date] | [How we know it's done] |
| [Action 3] | @[Name] | [Date] | [How we know it's done] |
## Shout-Outs 🎉
- @[Name] for [what they did]
- @[Name] for [what they did]
## Notes
[Any additional notes or observations]
---
*Next Retrospective: [Date]*---
Status Report Template
# [Project Name] Status Report - [Week of Date]
**Report Date:** [YYYY-MM-DD]
**Reporting Period:** [Start Date] - [End Date]
**Project Manager:** @[Name]
**Overall Status:** 🟢 On Track / 🟡 At Risk / 🔴 Off Track
## Executive Summary
[2-3 sentences: What's the current state? What are the key achievements? What needs attention?]
## Project Health
| Metric | Status | Details |
|--------|--------|---------|
| **Scope** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Schedule** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Budget** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Quality** | 🟢 / 🟡 / 🔴 | [Comment] |
| **Team Morale** | 🟢 / 🟡 / 🔴 | [Comment] |
## Key Accomplishments
- ✅ [Accomplishment 1]
- ✅ [Accomplishment 2]
- ✅ [Accomplishment 3]
## Milestones Status
| Milestone | Target Date | Status | Actual/Forecast | Notes |
|-----------|-------------|--------|-----------------|-------|
| [Milestone 1] | [Date] | ✅ Complete | [Date] | [Notes] |
| [Milestone 2] | [Date] | 🔄 In Progress | On track | [Notes] |
| [Milestone 3] | [Date] | ⏳ Not Started | [Forecast] | [Notes] |
## Active Risks
### 🔴 Critical Risks
| Risk | Impact | Mitigation | Owner | Status |
|------|--------|------------|-------|--------|
| [Risk 1] | High | [Strategy] | @[Name] | [Update] |
### 🟡 Medium Risks
| Risk | Impact | Mitigation | Owner | Status |
|------|--------|------------|-------|--------|
| [Risk 2] | Medium | [Strategy] | @[Name] | [Update] |
## Issues & Blockers
### 🚨 Blockers
- [Blocker 1] - @[Owner] - **Escalated to:** [Person]
- Impact: [What's blocked]
- ETA to resolve: [Date]
### ⚠️ Issues
- [Issue 1] - @[Owner]
- Status: [Update]
## Upcoming in Next Period
- [Activity 1]
- [Activity 2]
- [Activity 3]
## Budget Update (if applicable)
- **Total Budget:** [Amount]
- **Spent to Date:** [Amount] ([%])
- **Forecast to Complete:** [Amount]
- **Variance:** [Amount] ([%])
## Decisions Needed
| Decision | Why Needed | Deadline | Stakeholder |
|----------|-----------|----------|-------------|
| [Decision 1] | [Reason] | [Date] | @[Name] |
## Team Update
- **Current Team Size:** [N people]
- **Open Positions:** [N] ([Roles])
- **Recent Additions:** @[Name] - [Role]
- **Upcoming Departures:** [Names/Dates]
## Metrics (if applicable)
| Metric | This Period | Last Period | Trend | Target |
|--------|-------------|-------------|-------|--------|
| [Metric 1] | [Value] | [Value] | ↗️ / ↘️ / → | [Target] |
| [Metric 2] | [Value] | [Value] | ↗️ / ↘️ / → | [Target] |
## Links
- [Jira Project](link)
- [Roadmap](link)
- [Technical Docs](link)
---
*Next Status Report: [Date]*#!/usr/bin/env python3
"""Content Health Auditor - Audit Confluence content for quality and freshness.
Reads page metadata and produces a health report identifying stale content,
orphaned pages, missing owners, and content quality gaps.
Usage:
python content_health_auditor.py --pages pages.json
python content_health_auditor.py --pages pages.json --json
python content_health_auditor.py --example
"""
import argparse
import json
import sys
from datetime import datetime
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def analyze_content(data: dict) -> dict:
space = data.get("space", "Unknown")
pages = data.get("pages", [])
today = datetime.now()
stale = []
orphaned = []
no_owner = []
no_labels = []
low_quality = []
healthy = []
for page in pages:
title = page.get("title", "Untitled")
owner = page.get("owner", "")
last_updated = page.get("last_updated", "")
labels = page.get("labels", [])
has_parent = page.get("has_parent", True)
views_30d = page.get("views_30d", 0)
word_count = page.get("word_count", 0)
has_links = page.get("has_links", False)
issues = []
score = 100
# Freshness
if last_updated:
try:
updated_dt = datetime.strptime(last_updated, "%Y-%m-%d")
days = (today - updated_dt).days
if days > 365:
issues.append("Stale (>12 months)")
stale.append(title)
score -= 30
elif days > 180:
issues.append("Aging (>6 months)")
score -= 15
except ValueError:
pass
else:
issues.append("No update date")
score -= 10
# Orphaned
if not has_parent:
issues.append("Orphaned (no parent page)")
orphaned.append(title)
score -= 20
# Owner
if not owner:
issues.append("No owner assigned")
no_owner.append(title)
score -= 15
# Labels
if not labels:
issues.append("No labels")
no_labels.append(title)
score -= 10
# Content quality
if word_count < 50:
issues.append("Very short content (<50 words)")
score -= 15
if not has_links and word_count > 100:
issues.append("No links to related content")
score -= 5
# Low engagement
if views_30d == 0 and word_count > 0:
issues.append("Zero views in 30 days")
score -= 10
score = max(0, score)
if score >= 80:
rating = "Healthy"
healthy.append(title)
elif score >= 50:
rating = "Needs Attention"
else:
rating = "Poor"
low_quality.append(title)
page["health_score"] = score
page["health_rating"] = rating
page["issues"] = issues
# Aggregate metrics
total = len(pages)
avg_score = round(sum(p["health_score"] for p in pages) / total, 1) if total > 0 else 0
if avg_score >= 75:
overall = "Healthy"
elif avg_score >= 50:
overall = "Needs Improvement"
else:
overall = "Poor"
recs = []
if stale:
recs.append(f"{len(stale)} stale page(s) (>12 months old). Review for archiving or updating.")
if orphaned:
recs.append(f"{len(orphaned)} orphaned page(s). Move under appropriate parent pages or archive.")
if no_owner:
recs.append(f"{len(no_owner)} page(s) without owners. Assign owners for maintenance accountability.")
if no_labels:
recs.append(f"{len(no_labels)} page(s) without labels. Add labels to improve discoverability.")
page_results = sorted(pages, key=lambda x: x["health_score"])
return {
"space": space,
"audit_date": today.strftime("%Y-%m-%d"),
"total_pages": total,
"overall_health": overall,
"avg_health_score": avg_score,
"summary": {
"healthy": len(healthy),
"stale": len(stale),
"orphaned": len(orphaned),
"no_owner": len(no_owner),
"no_labels": len(no_labels),
"low_quality": len(low_quality),
},
"pages": [
{
"title": p.get("title"),
"owner": p.get("owner", "None"),
"health_score": p["health_score"],
"health_rating": p["health_rating"],
"issues": p["issues"],
"last_updated": p.get("last_updated", "Unknown"),
"views_30d": p.get("views_30d", 0),
}
for p in page_results
],
"recommendations": recs,
}
def print_report(result: dict) -> None:
print(f"\nContent Health Audit: {result['space']}")
print(f"Date: {result['audit_date']} | Pages: {result['total_pages']}")
print("=" * 65)
print(f"Overall Health: {result['overall_health']} (avg score: {result['avg_health_score']:.0f}/100)")
s = result["summary"]
print(f" Healthy: {s['healthy']} | Stale: {s['stale']} | Orphaned: {s['orphaned']} | No Owner: {s['no_owner']}")
print(f"\nPage Details (sorted by score):")
print(f" {'Title':<30} {'Score':>6} {'Rating':<16} {'Issues'}")
print(f" {'-'*30} {'-'*6} {'-'*16} {'-'*30}")
for p in result["pages"]:
title = p["title"][:28] + ".." if len(p["title"]) > 30 else p["title"]
issues = "; ".join(p["issues"][:2]) if p["issues"] else "None"
print(f" {title:<30} {p['health_score']:>5}% {p['health_rating']:<16} {issues}")
if result["recommendations"]:
print(f"\nRecommendations:")
for i, r in enumerate(result["recommendations"], 1):
print(f" {i}. {r}")
print()
def print_example() -> None:
example = {
"space": "Engineering Team",
"pages": [
{"title": "Onboarding Guide", "owner": "Alice", "last_updated": "2026-03-01", "labels": ["onboarding", "guide"], "has_parent": True, "views_30d": 45, "word_count": 500, "has_links": True},
{"title": "Old Architecture Doc", "owner": "", "last_updated": "2024-06-15", "labels": [], "has_parent": True, "views_30d": 2, "word_count": 1200, "has_links": True},
{"title": "Untitled Draft", "owner": "Bob", "last_updated": "2026-01-10", "labels": [], "has_parent": False, "views_30d": 0, "word_count": 30, "has_links": False},
{"title": "API Reference", "owner": "Carol", "last_updated": "2026-02-20", "labels": ["api", "reference"], "has_parent": True, "views_30d": 120, "word_count": 2000, "has_links": True},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Audit Confluence content health.")
parser.add_argument("--pages", type=str, help="Path to pages JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.pages:
parser.error("--pages is required")
data = load_data(args.pages)
result = analyze_content(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Label Taxonomy Analyzer - Analyze Confluence label usage and recommend taxonomy.
Reads label data across pages and identifies inconsistencies, unused labels,
and suggests a standardized taxonomy.
Usage:
python label_taxonomy_analyzer.py --labels labels.json
python label_taxonomy_analyzer.py --labels labels.json --json
python label_taxonomy_analyzer.py --example
"""
import argparse
import json
import re
import sys
from collections import Counter
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def analyze_labels(data: dict) -> dict:
space = data.get("space", "Unknown")
pages = data.get("pages", [])
all_labels = []
pages_with_labels = 0
pages_without_labels = 0
label_page_map = {}
for page in pages:
labels = page.get("labels", [])
if labels:
pages_with_labels += 1
else:
pages_without_labels += 1
for label in labels:
all_labels.append(label)
if label not in label_page_map:
label_page_map[label] = []
label_page_map[label].append(page.get("title", "Unknown"))
label_counts = Counter(all_labels)
total_unique = len(label_counts)
total_uses = len(all_labels)
coverage_pct = round(pages_with_labels / len(pages) * 100, 1) if pages else 0
# Identify issues
issues = []
# Inconsistent casing
lower_map = {}
for label in label_counts:
key = label.lower()
if key not in lower_map:
lower_map[key] = []
lower_map[key].append(label)
case_conflicts = {k: v for k, v in lower_map.items() if len(v) > 1}
if case_conflicts:
for key, variants in case_conflicts.items():
issues.append({
"type": "case_conflict",
"description": f"Case variants: {', '.join(variants)}",
"suggestion": f"Standardize to: {key}",
})
# Inconsistent separators
separator_issues = []
for label in label_counts:
if " " in label:
separator_issues.append(label)
elif "_" in label and "-" in str(label_counts):
separator_issues.append(label)
if separator_issues:
issues.append({
"type": "separator_inconsistency",
"description": f"Labels with spaces (use hyphens instead): {', '.join(separator_issues[:5])}",
"suggestion": "Use lowercase-hyphen-separated labels consistently.",
})
# Rarely used labels (only 1 page)
rare_labels = [l for l, c in label_counts.items() if c == 1]
# Very popular labels (might be too broad)
popular_labels = [(l, c) for l, c in label_counts.most_common(5)]
# Label categories (heuristic grouping)
categories = {
"status": [], "type": [], "team": [], "project": [], "other": [],
}
status_words = {"draft", "review", "approved", "archived", "deprecated", "active", "done", "wip"}
type_words = {"guide", "how-to", "faq", "reference", "process", "template", "meeting", "retro", "sprint"}
team_words = {"engineering", "product", "design", "marketing", "sales", "support", "hr", "finance"}
for label in label_counts:
lower = label.lower().replace("-", " ").replace("_", " ")
words = set(lower.split())
if words & status_words:
categories["status"].append(label)
elif words & type_words:
categories["type"].append(label)
elif words & team_words:
categories["team"].append(label)
else:
categories["other"].append(label)
# Recommendations
recs = []
if coverage_pct < 70:
recs.append(f"Label coverage is {coverage_pct:.0f}% (target: 90%+). Add labels to {pages_without_labels} unlabeled pages.")
if case_conflicts:
recs.append(f"Fix {len(case_conflicts)} label case conflict(s). Standardize to lowercase-hyphen format.")
if len(rare_labels) > total_unique * 0.5:
recs.append(f"{len(rare_labels)} labels used only once. Consolidate into a curated taxonomy of 20-30 standard labels.")
if separator_issues:
recs.append("Replace spaces and underscores in labels with hyphens for consistency.")
return {
"space": space,
"total_pages": len(pages),
"pages_with_labels": pages_with_labels,
"pages_without_labels": pages_without_labels,
"coverage_pct": coverage_pct,
"total_unique_labels": total_unique,
"total_label_uses": total_uses,
"top_labels": [{"label": l, "count": c} for l, c in label_counts.most_common(10)],
"rare_labels": rare_labels[:20],
"case_conflicts": {k: v for k, v in list(case_conflicts.items())[:5]},
"categories": {k: v for k, v in categories.items() if v},
"issues": issues,
"recommendations": recs,
}
def print_report(result: dict) -> None:
print(f"\nLabel Taxonomy Analysis: {result['space']}")
print(f"Pages: {result['total_pages']} | Unique Labels: {result['total_unique_labels']}")
print("=" * 55)
print(f"Coverage: {result['coverage_pct']:.0f}% ({result['pages_with_labels']} labeled / {result['pages_without_labels']} unlabeled)")
print(f"\nTop Labels:")
for tl in result["top_labels"]:
bar = "#" * min(tl["count"], 30)
print(f" {tl['label']:<25} {tl['count']:>4} {bar}")
if result["case_conflicts"]:
print(f"\nCase Conflicts:")
for key, variants in result["case_conflicts"].items():
print(f" '{key}': {', '.join(variants)}")
if result["categories"]:
print(f"\nLabel Categories:")
for cat, labels in result["categories"].items():
print(f" {cat.title()}: {', '.join(labels[:5])}")
if result["rare_labels"]:
print(f"\nRarely Used Labels (1 page): {', '.join(result['rare_labels'][:10])}")
if result["recommendations"]:
print(f"\nRecommendations:")
for i, r in enumerate(result["recommendations"], 1):
print(f" {i}. {r}")
print()
def print_example() -> None:
example = {
"space": "Engineering Team",
"pages": [
{"title": "Onboarding Guide", "labels": ["onboarding", "guide", "engineering"]},
{"title": "API Reference", "labels": ["api", "reference", "Engineering"]},
{"title": "Sprint 23 Retro", "labels": ["sprint", "retro"]},
{"title": "Old Design Doc", "labels": ["design doc"]},
{"title": "Quick Notes", "labels": []},
{"title": "Architecture Overview", "labels": ["architecture", "reference"]},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Analyze Confluence label taxonomy.")
parser.add_argument("--labels", type=str, help="Path to label data JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.labels:
parser.error("--labels is required")
data = load_data(args.labels)
result = analyze_labels(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Space Structure Analyzer - Analyze Confluence space architecture against best practices.
Evaluates page hierarchy depth, naming consistency, and structural patterns
to recommend improvements for navigation and discoverability.
Usage:
python space_structure_analyzer.py --space space.json
python space_structure_analyzer.py --space space.json --json
python space_structure_analyzer.py --example
"""
import argparse
import json
import sys
from collections import Counter
def load_data(path: str) -> dict:
with open(path, "r") as f:
return json.load(f)
def analyze_structure(data: dict) -> dict:
space_name = data.get("space", "Unknown")
pages = data.get("pages", [])
# Build hierarchy
page_map = {p.get("id"): p for p in pages}
children = {}
root_pages = []
for p in pages:
parent_id = p.get("parent_id")
if parent_id:
if parent_id not in children:
children[parent_id] = []
children[parent_id].append(p["id"])
else:
root_pages.append(p["id"])
# Calculate depths
def get_depth(page_id, depth=0):
max_depth = depth
for child_id in children.get(page_id, []):
child_depth = get_depth(child_id, depth + 1)
max_depth = max(max_depth, child_depth)
return max_depth
max_depth = 0
depth_distribution = Counter()
for page in pages:
page_id = page.get("id")
# Calculate this page's depth
depth = 0
current = page
while current.get("parent_id") and current["parent_id"] in page_map:
depth += 1
current = page_map[current["parent_id"]]
depth_distribution[depth] += 1
max_depth = max(max_depth, depth)
# Root page analysis
recommended_roots = ["Overview", "Team Information", "Projects", "Processes", "Meeting Notes", "Resources"]
# Naming analysis
titles = [p.get("title", "") for p in pages]
short_titles = [t for t in titles if len(t) < 5]
long_titles = [t for t in titles if len(t) > 60]
duplicate_titles = [t for t, count in Counter(titles).items() if count > 1]
# Score
score = 100
issues = []
recs = []
if max_depth > 5:
issues.append(f"Page hierarchy too deep ({max_depth} levels). Recommended max: 3-4 levels.")
recs.append("Flatten deep hierarchies. Use labels and search instead of deep nesting.")
score -= 20
elif max_depth > 3:
issues.append(f"Page hierarchy is {max_depth} levels deep. Consider flattening to 3.")
score -= 10
if len(root_pages) > 10:
issues.append(f"Too many root pages ({len(root_pages)}). Creates cluttered navigation.")
recs.append("Consolidate root pages into 5-7 top-level categories.")
score -= 15
elif len(root_pages) < 3:
issues.append(f"Only {len(root_pages)} root page(s). Consider adding standard sections.")
score -= 5
if short_titles:
issues.append(f"{len(short_titles)} page(s) with very short titles (<5 chars).")
recs.append("Use descriptive page titles. Short titles are hard to find in search.")
score -= 5
if duplicate_titles:
issues.append(f"{len(duplicate_titles)} duplicate title(s): {', '.join(duplicate_titles[:3])}")
recs.append("Rename duplicate pages to be unique and descriptive.")
score -= 10
# Wide pages (too many children)
wide_pages = []
for page_id, child_list in children.items():
if len(child_list) > 15:
page = page_map.get(page_id, {})
wide_pages.append({"title": page.get("title", "Unknown"), "children": len(child_list)})
if wide_pages:
issues.append(f"{len(wide_pages)} page(s) with >15 children. Creates scrolling navigation.")
recs.append("Group child pages under subcategories. Target 5-10 children per page.")
score -= 10
score = max(0, score)
if score >= 80:
rating = "Well Structured"
elif score >= 60:
rating = "Needs Improvement"
else:
rating = "Poorly Structured"
return {
"space": space_name,
"total_pages": len(pages),
"score": score,
"rating": rating,
"max_depth": max_depth,
"root_pages": len(root_pages),
"depth_distribution": dict(depth_distribution),
"naming": {
"short_titles": len(short_titles),
"long_titles": len(long_titles),
"duplicates": duplicate_titles,
},
"wide_pages": wide_pages,
"issues": issues,
"recommendations": recs,
}
def print_report(result: dict) -> None:
print(f"\nSpace Structure Analysis: {result['space']}")
print(f"Pages: {result['total_pages']}")
print("=" * 55)
print(f"Score: {result['score']}/100 ({result['rating']})")
print(f"Max Depth: {result['max_depth']} | Root Pages: {result['root_pages']}")
print(f"\nDepth Distribution:")
for depth in sorted(result["depth_distribution"].keys()):
count = result["depth_distribution"][depth]
bar = "#" * min(count, 40)
print(f" Level {depth}: {count:>4} pages {bar}")
if result["naming"]["duplicates"]:
print(f"\nDuplicate Titles: {', '.join(result['naming']['duplicates'])}")
if result["wide_pages"]:
print(f"\nWide Pages (>15 children):")
for wp in result["wide_pages"]:
print(f" - {wp['title']}: {wp['children']} children")
if result["issues"]:
print(f"\nIssues:")
for issue in result["issues"]:
print(f" ! {issue}")
if result["recommendations"]:
print(f"\nRecommendations:")
for i, r in enumerate(result["recommendations"], 1):
print(f" {i}. {r}")
print()
def print_example() -> None:
example = {
"space": "Engineering Team",
"pages": [
{"id": "1", "title": "Overview", "parent_id": None},
{"id": "2", "title": "Team Members", "parent_id": "1"},
{"id": "3", "title": "Projects", "parent_id": None},
{"id": "4", "title": "Project Alpha", "parent_id": "3"},
{"id": "5", "title": "Design Docs", "parent_id": "4"},
{"id": "6", "title": "API Spec", "parent_id": "5"},
{"id": "7", "title": "v2 Changes", "parent_id": "6"},
{"id": "8", "title": "Meeting Notes", "parent_id": None},
{"id": "9", "title": "test", "parent_id": None},
{"id": "10", "title": "test", "parent_id": None},
],
}
print(json.dumps(example, indent=2))
def main():
parser = argparse.ArgumentParser(description="Analyze Confluence space structure.")
parser.add_argument("--space", type=str, help="Path to space structure JSON file")
parser.add_argument("--json", action="store_true", help="Output as JSON")
parser.add_argument("--example", action="store_true", help="Print example and exit")
args = parser.parse_args()
if args.example:
print_example()
return
if not args.space:
parser.error("--space is required")
data = load_data(args.space)
result = analyze_structure(data)
if args.json:
print(json.dumps(result, indent=2))
else:
print_report(result)
if __name__ == "__main__":
main()