plugins/jira/skills/status-analysis/SKILL.md
Shared engine for analyzing Jira issue activity and generating status summaries
npx skillsauth add openshift-eng/ai-helpers status-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill provides the core analysis logic shared by status-related commands (/jira:status-rollup and /jira:update-weekly-status). 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 fieldDo 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 |
|-----------|---------------|----------------------|
| data_source | MCP API calls | Pre-gathered JSON files |
| root_issues | Single issue key | Multiple (from manifest.json) |
| date_range.start | User-specified or issue creation | today - 7 days |
| date_range.end | User-specified or today | today |
| output_format | markdown_comment | ryg_field |
| output_target | Comment on root issue | Status Summary field |
| external_links | Via gh CLI | Pre-gathered in JSON |
| user_review | Yes (before posting comment) | Yes (approve/modify/skip per issue) |
| caching | Temp file for refinement | JSON files in .work/ |
Both commands use the same traversal mechanism via parent = KEY JQL with BFS recursion (Atlassian Cloud compatible — childIssuesOf() is not supported on Cloud):
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 per level: parent = FEATURE-123 → [EPIC-456, EPIC-789]
parent = EPIC-456 → [Story 1.1, Story 1.2]
... (BFS until no more children)
Returns: ALL descendants at any depth via recursive BFS
Note: childIssuesOf() is not available on Atlassian Cloud. The data gatherer script uses parent = KEY with BFS to traverse the full hierarchy.
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" or "ryg_field"
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:
parent = {root-issue} JQL with BFS recursion to get full hierarchy (Cloud-compatible; childIssuesOf() is not supported on Atlassian Cloud)AND updated >= {start-date}maxResults=100 per page; handle cursor pagination via nextPageTokenFor 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")
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
testing
Snapshot OpenShift payload data (release controller, PR diffs, comments, CI jobs, JUnit results, regression tracking) to a local directory for offline analysis
development
Analyze a payload snapshot to identify root causes of blocking job failures, score candidate PRs, and produce an HTML report with revert recommendations
tools
Create TRT JIRA bugs, open revert PRs, and trigger payload jobs for high-confidence revert candidates
data-ai
State management for agentic payload triage actions — you must use this skill whenever reading or writing the payload results YAML file