From jira
Analyzes Jira issue activity and generates status summaries for weekly updates, rollups, and feature updates.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jira:status-analysisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill provides the core analysis logic shared by status-related commands (`/jira:status-rollup`, `/jira:update-weekly-status`, and `/jira:generate-feature-updates`). It handles data collection, activity analysis, and status generation in a unified way.
This skill provides the core analysis logic shared by status-related commands (/jira:status-rollup, /jira:update-weekly-status, and /jira:generate-feature-updates). It handles data collection, activity analysis, and status generation in a unified way.
IMPORTANT FOR AI: This is a procedural skill - when invoked by a command, you should execute the implementation steps defined in this document and its sub-modules. The calling command determines the configuration parameters.
This skill is invoked automatically by:
/jira:status-rollup - Single root issue, outputs as Jira comment/jira:update-weekly-status - Multiple root issues (batch), outputs to Status Summary field/jira:generate-feature-updates - Multiple root issues (batch), outputs as markdown to stdoutDo NOT invoke this skill directly. Use the commands above.
┌─────────────────────────────────────────────────────────────────┐
│ /jira:update-weekly-status │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Python Data Gatherer │
│ (gather_status_data.py) │
│ │
│ • Async HTTP requests (aiohttp) │
│ • Jira: issues, descendants, changelogs │
│ • GitHub: PRs via GraphQL (batched) │
│ • Output: .work/weekly-status/{date}/issues/*.json │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Status Analysis Engine │
│ ┌───────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Read JSON │ │ Activity │ │ PR Activity │ │
│ │ (pre-gathered)│─▶│ Analysis │─▶│ (pre-gathered) │ │
│ └───────────────┘ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Formatting │ │
│ │ (formatting.md) │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Status Summary field (R/Y/G template) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ /jira:status-rollup │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Status Analysis Engine │
│ (SKILL.md) │
│ ┌───────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Data │ │ Activity │ │ External │ │
│ │ Collection │─▶│ Analysis │─▶│ Links │ │
│ │ (data- │ │ (activity- │ │ (external- │ │
│ │ collection.md)│ │ analysis.md) │ │ links.md) │ │
│ └───────────────┘ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Formatting │ │
│ │ (formatting.md) │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Jira comment (markdown) │
└─────────────────────────────────────────────────────────────────┘
This skill is composed of four sub-modules. Read each when executing the analysis:
| Module | File | Purpose |
|---|---|---|
| Data Collection | data-collection.md | Reading pre-gathered JSON or fetching via MCP |
| Activity Analysis | activity-analysis.md | Detecting blockers, progress, risks, completion |
| External Links | external-links.md | GitHub PR and GitLab MR integration |
| Formatting | formatting.md | Output templates for different modes |
| Data Gatherer | scripts/gather_status_data.py | Async batch data collection (update-weekly-status) |
Both commands share the same engine with different configuration:
| Parameter | status-rollup | update-weekly-status | generate-feature-updates |
|---|---|---|---|
data_source | MCP API calls | Pre-gathered JSON files | Pre-gathered JSON files |
root_issues | Single issue key | Multiple (from manifest.json) | Multiple (from manifest.json) |
date_range.start | User-specified or issue creation | today - 7 days | today - 7 days |
date_range.end | User-specified or today | today | today |
output_format | markdown_comment | ryg_field | feature_markdown |
output_target | Comment on root issue | Status Summary field | stdout |
external_links | Via gh CLI | Pre-gathered in JSON | Pre-gathered in JSON |
user_review | Yes (before posting comment) | Yes (approve/modify/skip per issue) | Yes (full-section review) |
caching | Temp file for refinement | JSON files in .work/ | JSON files in .work/ |
Both commands use the same traversal mechanism via childIssuesOf() JQL:
Root Issue (FEATURE-123)
│
├── Epic 1 (EPIC-456)
│ ├── Story 1.1
│ │ └── Subtask 1.1.1
│ └── Story 1.2
│
└── Epic 2 (EPIC-789)
└── Story 2.1
JQL: issue in childIssuesOf(FEATURE-123)
Returns: ALL descendants at any depth (EPIC-456, Story 1.1, Subtask 1.1.1, Story 1.2, EPIC-789, Story 2.1)
Key benefit: childIssuesOf() is already recursive - a single JQL query returns the entire hierarchy regardless of depth. No manual recursion needed.
The difference between commands is not in traversal but in:
Configuration passed from calling command:
{
"root_issues": ["OCPSTRAT-1234"],
"date_range": {
"start": "2025-01-06",
"end": "2025-01-13"
},
"output_format": "markdown_comment",
"output_target": "comment",
"external_links_enabled": true,
"cache_to_file": true,
"filters": {
"component": null,
"label": null,
"assignees": [],
"excluded_assignees": []
}
}
The core data structure for each analyzed issue:
{
"issue_key": "OCPSTRAT-1234",
"summary": "Implement feature X",
"status": "In Progress",
"assignee": "[email protected]",
"issue_type": "Story",
"date_range": {
"start": "2025-01-06",
"end": "2025-01-13"
},
"changelog": {
"status_transitions": [
{"from": "To Do", "to": "In Progress", "date": "2025-01-07", "author": "[email protected]"}
],
"field_changes": [],
"last_status_summary_update": "2025-01-05T10:30:00Z"
},
"comments": [
{"author": "[email protected]", "date": "2025-01-08", "body": "Started work on PR #123", "is_bot": false}
],
"descendants": [
{"key": "OCPSTRAT-1235", "summary": "Sub-task 1", "status": "Done", "updated_in_range": true}
],
"external_links": {
"github_prs": [
{"url": "https://github.com/org/repo/pull/123", "state": "MERGED", "title": "Add feature X"}
],
"gitlab_mrs": []
},
"analysis": {
"health": "green",
"blockers": [],
"risks": [],
"achievements": ["PR #123 merged", "Sub-task 1 completed"],
"in_progress": ["Sub-task 2 under review"],
"metrics": {
"total_descendants": 3,
"completed": 1,
"in_progress": 1,
"blocked": 0,
"completion_percentage": 33
}
}
}
When a command invokes this skill, follow this sequence:
The calling command provides an AnalysisConfig. Parse and validate:
REQUIRED parameters:
- root_issues: Array of issue keys to analyze
- date_range: {start, end} in YYYY-MM-DD format
- output_format: "markdown_comment", "ryg_field", or "feature_markdown"
OPTIONAL parameters:
- external_links_enabled: boolean (default: true)
- cache_to_file: boolean (default: false)
- filters: component, label, assignee filters
Follow data-collection.md which supports two modes:
Option A: Pre-Gathered Data (update-weekly-status)
Data has already been collected by the Python script (gather_status_data.py):
.work/weekly-status/{date}/manifest.json.work/weekly-status/{date}/issues/{ISSUE-KEY}.jsonOption B: Direct MCP Calls (status-rollup)
For each root issue:
fields=summary,status,assignee,issuelinks,comment,{custom-fields}expand=changelogDiscover all descendants:
issue in childIssuesOf({root-issue}) to get full hierarchyAND updated >= {start-date}limit=100 (increase if needed for large hierarchies)For each descendant issue:
Build IssueActivityData for root and all descendants
Optionally cache to temp file (for refinement workflows)
Follow activity-analysis.md to:
Filter to date range:
Identify key events:
Analyze comment content:
Determine health status:
Calculate metrics:
Follow external-links.md to:
Extract GitHub PR URLs:
issuelinks field (remote links)Fetch PR metadata (if gh CLI available):
gh pr view {PR-NUMBER} --repo {REPO} --json state,updatedAt,mergedAt,title
Track PR activity:
Handle GitLab MRs:
glab if availableFollow formatting.md to generate output based on output_format:
For markdown_comment (status-rollup):
## Status Rollup From: {start-date} to {end-date}
**Overall Status:** [Health assessment]
**This Week:**
- Completed:
1. [ISSUE-KEY] - [Achievement]
- In Progress:
1. [ISSUE-KEY] - [Current state]
- Blocked:
1. [ISSUE-KEY] - [Blocker reason]
**Next Week:**
- [Planned items]
**Metrics:** X/Y issues complete (Z%)
Note: When posting via addCommentToJiraIssue, always include contentFormat: "markdown".
For ryg_field (update-weekly-status):
* Color Status: {Red, Yellow, Green}
* Status summary:
** Thing 1 that happened since last week
** Thing 2 that happened since last week
* Risks:
** Risk 1 (or "None at this time")
For feature_markdown (generate-feature-updates):
- [ISSUE-KEY](https://issues.redhat.com/browse/ISSUE-KEY): Issue summary
- 1-3 sentences of executive prose. No metrics, no R/Y/G.
- [ISSUE-KEY-2](https://issues.redhat.com/browse/ISSUE-KEY-2): Issue summary
- Prose focusing on significant progress, deliveries, blockers, or risks.
Return structured result:
{
"issues_analyzed": [...IssueActivityData],
"formatted_outputs": {
"OCPSTRAT-1234": "formatted status text..."
},
"summary": {
"total": 5,
"by_health": {"green": 3, "yellow": 1, "red": 1}
},
"cache_file": "/tmp/jira-status-{issue-id}-{timestamp}.md"
}
The calling command then handles:
All modules should handle these error cases:
| Error | Handling |
|---|---|
| Issue not found | Log warning, skip issue, continue with others |
| Permission denied | Display clear error, suggest checking MCP config |
| No activity in date range | Generate summary based on current state |
| GitHub CLI not available | Skip PR analysis, note in output |
| Rate limiting | Display error with retry guidance |
| Large hierarchies (100+ issues) | Show progress indicators |
| Missing JSON file | Log warning: "Data file for {key} not found, skipping" |
expand=changelog in getJiraIssue callsparent = KEY per level with recursive BFS (Cloud-compatible replacement for childIssuesOf())| Field Name | Field ID | Type | Purpose |
|---|---|---|---|
| Status Summary | customfield_10814 | String | Stores R/Y/G status text for update-weekly-status |
aiohttp packageJIRA_API_TOKEN: Atlassian API token (create at https://id.atlassian.com/manage-profile/security/api-tokens)JIRA_USERNAME: Atlassian account emailGITHUB_TOKEN or authenticated gh CLICheck setup:
python3 -c "import aiohttp; print('aiohttp OK')"
echo $JIRA_API_TOKEN
gh auth token
gh) installed and authenticated (optional but recommended)glab) installed and authenticated (optional)Check for tools:
which gh && gh auth status
which glab && glab auth status # optional
npx claudepluginhub openshift-eng/ai-helpers --plugin jiraSummarizes Jira ticket activity and child tickets to detect stale backlog items. Analyzes hierarchy, comments, and changelog to produce a staleness report.
Generates project status reports from Jira issues and publishes them to Confluence. Queries Jira, categorizes issues, and creates formatted reports for delivery managers and executives.
Gathers recent Jira activity for assigned/watched issues and classifies events into attention tiers (needs attention, unsure, noise).