Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:51:34 +08:00
commit acde81dcfe
59 changed files with 22282 additions and 0 deletions

235
skills/jira/README.md Normal file
View File

@@ -0,0 +1,235 @@
# Jira Integration Skill
Quick reference for using the Jira integration skill in PRISM.
## Quick Start
### 1. Setup (First Time Only)
Generate your Jira API token:
1. Visit: https://id.atlassian.com/manage-profile/security/api-tokens
2. Click "Create API token"
3. Name it (e.g., "PRISM Local Dev")
4. Copy the token
Configure credentials:
```bash
# Create .env file in repository root
cp .env.example .env
# Add your credentials to .env
JIRA_EMAIL=your.email@resolve.io
JIRA_API_TOKEN=your_token_here
```
### 2. Usage
**Automatic Detection**:
```
User: "Let's work on PLAT-456"
# Skill automatically detects and fetches PLAT-456
```
**Explicit Command**:
```
User: "jira PLAT-789"
# Fetches and displays PLAT-789 details
```
**Proactive Inquiry**:
```
User: "Implement login feature"
Agent: "Do you have a JIRA ticket number so I can get more context?"
User: "PLAT-123"
# Fetches and displays context
```
## Features
- ✅ Automatic issue key detection (`PLAT-123`, `PROJ-456`)
- ✅ Fetch full issue details with acceptance criteria
- ✅ Show recent comments and context
- ✅ Display linked issues and dependencies
- ✅ Epic → Story → Task hierarchy
- ✅ Session caching (fetch once, use multiple times)
- ✅ Graceful degradation (continues if Jira unavailable)
- ✅ Read-only (safe, non-invasive)
## Commands
| Command | Description |
|---------|-------------|
| `jira {key}` | Fetch and display issue details |
| `jira-epic {key}` | Fetch epic with all child stories |
| `jira-search {jql}` | Search issues with JQL query |
## Integration with Other Skills
The Jira skill enhances all PRISM skills:
- **Story Master (sm)**: Fetch epics for decomposition
- **Developer (dev)**: Get story context for implementation
- **Product Owner (po)**: Validate stories against tickets
- **QA (qa)**: Get acceptance criteria for testing
- **Support (support)**: Investigate bugs with full context
- **Architect (architect)**: Review epic technical requirements
- **Peer (peer)**: Verify implementation against AC
## Examples
### Decomposing an Epic
```
User: "Decompose PLAT-789"
# Jira skill automatically:
# 1. Fetches epic details
# 2. Shows epic goal and AC
# 3. Lists existing child stories (to avoid duplication)
# 4. Provides context to Story Master skill
```
### Implementing a Story
```
User: "Implement PLAT-456"
# Jira skill automatically:
# 1. Fetches story details
# 2. Shows acceptance criteria
# 3. Displays technical notes from comments
# 4. Lists blocking issues
# 5. Provides context to Developer skill
```
### Investigating a Bug
```
User: "Investigate bug PLAT-999"
# Jira skill automatically:
# 1. Fetches bug details
# 2. Shows reproduction steps
# 3. Displays customer comments
# 4. Lists related bugs
# 5. Provides context to Support skill
```
## Troubleshooting
### "Jira authentication failed"
**Problem**: Invalid or missing credentials
**Solution**:
1. Verify `.env` file exists in repository root
2. Check `JIRA_EMAIL` is correct Atlassian email
3. Generate new API token and update `JIRA_API_TOKEN`
4. Restart terminal/IDE to reload environment
### "Access denied to PLAT-123"
**Problem**: You lack permission to view issue
**Solution**:
1. Verify you can view issue in Jira web UI
2. Request access from Jira administrator
3. Check issue key spelling
### "Issue PLAT-123 not found"
**Problem**: Issue doesn't exist
**Solution**:
1. Verify issue key spelling (uppercase, correct number)
2. Check if issue was deleted or moved
3. Try viewing in Jira web UI
### "Rate limit exceeded"
**Problem**: Too many requests in short time
**Solution**:
1. Wait 60 seconds before retrying
2. Use cached data from earlier in conversation
3. Avoid fetching same issue multiple times
## Configuration
Configuration in [core-config.yaml](../../core-config.yaml):
```yaml
jira:
enabled: true # Master switch
baseUrl: https://resolvesys.atlassian.net # Your Jira instance
email: ${JIRA_EMAIL} # From .env file
token: ${JIRA_API_TOKEN} # From .env file
defaultProject: PLAT # Default project key
issueKeyPattern: "[A-Z]+-\\d+" # Issue key regex
```
## Security
**Best Practices**:
- ✅ Use environment variables (`.env` file)
- ✅ Each developer has their own API token
-`.env` file is gitignored (never commit!)
- ✅ Rotate tokens every 90 days
- ✅ Revoke unused tokens immediately
**Never**:
- ❌ Hardcode credentials in code
- ❌ Commit credentials to git
- ❌ Share API tokens with teammates
- ❌ Use passwords (API tokens only!)
- ❌ Embed credentials in URLs
## Documentation
**Detailed Guides**:
- [SKILL.md](./SKILL.md) - Complete skill overview
- [API Reference](./reference/api-reference.md) - Jira REST API details
- [Extraction Format](./reference/extraction-format.md) - Issue formatting standards
- [Authentication](./reference/authentication.md) - Security and setup
- [Error Handling](./reference/error-handling.md) - Troubleshooting guide
**Quick Links**:
- [Generate API Token](https://id.atlassian.com/manage-profile/security/api-tokens)
- [Jira Status](https://status.atlassian.com/)
- [JQL Documentation](https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/)
## FAQ
**Q: Is this read-only?**
A: Yes! The skill only fetches data, never creates or modifies issues.
**Q: Does this work automatically?**
A: Yes! Just mention an issue key (PLAT-123) and it fetches automatically.
**Q: Can I disable auto-detection?**
A: Yes, use `auto-detect off` command.
**Q: What if Jira is down?**
A: The skill gracefully degrades. It informs you and continues without Jira context.
**Q: Do I need a Jira license?**
A: You need access to view issues in Jira. A basic Jira Software license is sufficient.
**Q: Can I search for issues?**
A: Yes! Use `jira-search "project = PLAT AND type = Bug"`
## Support
**Issues**:
- Check [Error Handling Guide](./reference/error-handling.md)
- Verify [Authentication Setup](./reference/authentication.md)
- Review `.env` configuration
**Enhancement Requests**:
- Propose in team wiki or project documentation
- Consider custom field mappings for your Jira instance
---
**Skill Version**: 1.0.0
**Last Updated**: 2025-11-20

433
skills/jira/SKILL.md Normal file
View File

@@ -0,0 +1,433 @@
---
name: jira
description: Jira integration for fetching issue context (Epics, Stories, Bugs) to enhance development workflows. Use for automatic issue detection, retrieving ticket details, acceptance criteria, and linked dependencies.
version: 1.1.0
---
# Jira Integration
## When to Use
- User mentions a Jira issue key (e.g., "PLAT-123")
- Need to fetch Epic details for decomposition
- Retrieve story context for implementation
- Get bug details and reproduction steps
- Check acceptance criteria from tickets
- Review linked issues and dependencies
- Fetch customer comments and context
## What This Skill Does
**Provides read-only Jira integration** to enrich development workflows:
- **Automatic Detection**: Recognizes issue keys in conversation (PLAT-123, ISSUE-456)
- **Context Fetching**: Retrieves full issue details via Jira REST API using curl
- **Structured Formatting**: Presents issue data in clear, development-ready format
- **Linked Issues**: Follows Epic → Story → Task relationships
- **Comment History**: Shows recent comments and customer feedback
- **Acceptance Criteria**: Extracts AC from description or custom fields
- **Dependency Tracking**: Identifies blockers and related issues
## Core Principles
### 🎫 The Jira Integration Mindset
**Automated context retrieval** without leaving your workflow:
- **Proactive Detection**: Automatically spots issue keys in conversation
- **Read-Only**: Safe, non-intrusive access to Jira data
- **Privacy Respecting**: Only fetches explicitly mentioned or approved issues
- **Session Caching**: Stores fetched data for conversation duration
- **Graceful Degradation**: Continues without Jira if unavailable
- **Security First**: Credentials via environment variables only
## Implementation Method
The skill uses **curl via Bash tool** to fetch Jira data:
```bash
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
"https://resolvesys.atlassian.net/rest/api/3/issue/{issueKey}"
```
**Why curl instead of WebFetch:**
- WebFetch doesn't support custom authentication headers
- curl can read credentials directly from environment variables
- Direct API access with Basic Authentication
- Reliable and proven approach
## Quick Start
### Fetch an Issue
**When user mentions issue key:**
1. Detect issue key pattern `[A-Z]+-\d+`
2. Use curl with Bash tool to fetch from Jira API
3. Parse JSON response
4. Format and display structured summary
**Example workflow:**
```
User: "jira PLAT-3213"
Agent executes:
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-3213"
Parses response and displays formatted issue details
```
### Automatic Issue Detection
**Standard workflow:**
1. User mentions issue key (e.g., "Let's work on PLAT-456")
2. Skill detects pattern matching `[A-Z]+-\d+`
3. Fetches issue details via curl
4. Displays formatted summary
5. Proceeds with requested task using context
### Proactive Inquiry
**When user describes work without ticket:**
```
User: "I need to implement the login feature"
Agent: "Great! Do you have a JIRA ticket number so I can get more context?"
User: "PLAT-456"
Agent: Fetches and displays issue details via curl
```
## Available Commands
All Jira capabilities (when using this skill):
| Command | Purpose |
|---------|---------|
| **Issue Retrieval** | |
| `jira {issueKey}` | Fetch and display full issue details |
| `jira-epic {epicKey}` | Fetch epic and all child stories/tasks |
| `jira-search {jql}` | Search issues using JQL query |
| **Workflow Integration** | |
| `auto-detect` | Enable/disable automatic issue key detection |
→ [API Reference](./reference/api-reference.md)
## Issue Detection Patterns
The skill automatically detects these patterns:
- **Primary Project**: `PLAT-123` (from core-config.yaml defaultProject)
- **Any Project**: `[A-Z]+-\d+` format (e.g., JIRA-456, DEV-789)
- **Multiple Issues**: Detects all issue keys in single message
## Fetching Issues - Implementation
### Step 1: Detect Issue Key
Extract issue key from user message using regex:
```regex
[A-Z]+-\d+
```
### Step 2: Fetch via curl
Use Bash tool to execute curl command:
```bash
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
"https://resolvesys.atlassian.net/rest/api/3/issue/{ISSUE_KEY}" \
2>&1
```
**Critical points:**
- Use `$JIRA_EMAIL` and `$JIRA_TOKEN` environment variables
- Use `-u` flag for Basic Authentication
- Use `-s` for silent mode (no progress bar)
- Redirect stderr with `2>&1` to catch errors
### Step 3: Parse JSON Response
Use Python one-liner to extract key fields:
```bash
curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123" | \
python -c "
import json, sys
data = json.load(sys.stdin)
fields = data['fields']
print('Key:', data['key'])
print('Type:', fields['issuetype']['name'])
print('Summary:', fields['summary'])
print('Status:', fields['status']['name'])
print('Assignee:', fields.get('assignee', {}).get('displayName', 'Unassigned'))
"
```
### Step 4: Format and Display
Format the extracted data as structured markdown:
```markdown
## 📋 [{ISSUE_KEY}](https://resolvesys.atlassian.net/browse/{ISSUE_KEY})
**Type:** {Type} | **Status:** {Status} | **Priority:** {Priority}
**Assignee:** {Assignee} | **Reporter:** {Reporter}
### Description
{Description text}
### Acceptance Criteria
{Extracted AC or "Not specified"}
### Related Issues
- Blocks: {list}
- Blocked by: {list}
- Parent: [{PARENT}](link)
### Additional Context
- Labels: {labels}
- Components: {components}
- Updated: {date}
[View in Jira](https://resolvesys.atlassian.net/browse/{ISSUE_KEY})
```
## Extracted Information
When fetching issues, the skill extracts:
- **Core Details**: Issue Key, Type (Epic/Story/Bug/Task), Summary, Description
- **Status**: Current status, Priority, Resolution
- **People**: Assignee, Reporter
- **Hierarchy**: Epic Link (for stories), Parent (for subtasks)
- **Estimation**: Story Points, Original/Remaining Estimate
- **Acceptance Criteria**: From description or custom fields
- **Comments**: Last 3 most recent comments with authors
- **Links**: Blocks, is blocked by, relates to, duplicates
- **Metadata**: Labels, Components, Fix Versions
→ [Extraction Details](./reference/extraction-format.md)
## Integration with PRISM Skills
The Jira skill enhances other PRISM skills:
### Story Master (sm)
- Fetch epic details when decomposing
- Retrieve all child stories to avoid duplication
- Extract epic acceptance criteria and goals
### Developer (dev)
- Fetch story/bug implementation context
- Review technical notes in comments
- Check blocking/blocked issues
### Product Owner (po)
- Fetch story details for validation
- Check acceptance criteria completeness
- Review linked dependencies
### QA (qa)
- Fetch story acceptance criteria
- Review test requirements from description
- Check linked test issues
### Support (support)
- Fetch bug details and reproduction steps
- Check existing comments for customer info
- Identify related bugs and patterns
### Architect (architect)
- Fetch epic scope and technical requirements
- Review architectural decisions in comments
- Check component relationships
### Peer (peer)
- Fetch story context for code review
- Verify implementation matches acceptance criteria
- Check for architectural alignment
## Authentication & Security
**Configuration:**
Credentials are configured via Windows environment variables:
```
JIRA_EMAIL=your.email@resolve.io
JIRA_TOKEN=your-jira-api-token
```
**Core config reference** ([core-config.yaml](../../core-config.yaml)):
```yaml
jira:
enabled: true
baseUrl: https://resolvesys.atlassian.net
email: ${JIRA_EMAIL}
token: ${JIRA_TOKEN}
defaultProject: PLAT
```
**Security Best Practices:**
- Credentials read from system environment variables
- Never hardcode credentials in code
- Basic Authentication via curl `-u` flag
- Credentials passed securely to curl
**Setup:**
1. Set Windows environment variables (System level):
- `JIRA_EMAIL` = your Atlassian email
- `JIRA_TOKEN` = your API token
2. Generate API token at: https://id.atlassian.com/manage-profile/security/api-tokens
3. Restart terminal/IDE after setting variables
→ [Authentication Reference](./reference/authentication.md)
## Error Handling
**Authentication Failed:**
```bash
# Response: "Client must be authenticated to access this resource."
# Action: Verify JIRA_EMAIL and JIRA_TOKEN are set correctly
```
**Issue Not Found (404):**
```bash
# Response: {"errorMessages":["Issue does not exist or you do not have permission to see it."]}
# Action: Verify issue key spelling and user has permission
```
**Network Error:**
```bash
# Response: curl connection error
# Action: Check network connectivity and Jira availability
```
**Graceful Degradation:**
- Display error message to user
- Offer to proceed without Jira context
- Never block workflow on Jira failures
→ [Error Handling Guide](./reference/error-handling.md)
## Best Practices
### Fetching Issues
**DO:**
- Always use environment variables for credentials
- Format output in clear, structured markdown
- Cache fetched issue data for the conversation session
- Include clickable Jira links
- Handle missing fields gracefully
- Check authentication before attempting fetch
**DON'T:**
- Hardcode credentials in commands
- Expose credentials in error messages
- Skip error handling
- Fetch entire project data at once
- Ignore API rate limits
### Workflow Integration
**DO:**
- Proactively detect issue keys in user messages
- Display issue summary before proceeding with task
- Use issue context to inform implementation decisions
- Reference Jira tickets in commit messages
**DON'T:**
- Skip issue detection to save time
- Assume issue data is always current
- Modify Jira issues (read-only integration)
→ [Best Practices Guide](../../shared/reference/best-practices.md#jira-integration)
## Example Implementation
### Complete Issue Fetch
```bash
# Step 1: Fetch issue data
ISSUE_DATA=$(curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" \
"https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-3213")
# Step 2: Check for errors
if echo "$ISSUE_DATA" | grep -q "errorMessages"; then
echo "Error fetching issue"
exit 1
fi
# Step 3: Extract and format
echo "$ISSUE_DATA" | python -c "
import json, sys
data = json.load(sys.stdin)
fields = data['fields']
print(f\"## 📋 [{data['key']}](https://resolvesys.atlassian.net/browse/{data['key']})\")
print(f\"**Type:** {fields['issuetype']['name']} | **Status:** {fields['status']['name']}\")
print(f\"**Assignee:** {fields.get('assignee', {}).get('displayName', 'Unassigned')}\")
print(f\"\n### Summary\")
print(fields['summary'])
"
```
## Reference Documentation
Core references (loaded as needed):
- **[API Reference](./reference/api-reference.md)** - Jira REST API endpoints and curl usage
- **[Extraction Format](./reference/extraction-format.md)** - Issue data formatting and structure
- **[Authentication](./reference/authentication.md)** - Security and credential management
- **[Error Handling](./reference/error-handling.md)** - Handling API errors gracefully
Shared references:
- **[Commands (All Skills)](../../shared/reference/commands.md)** - Complete command reference
- **[Dependencies (All Skills)](../../shared/reference/dependencies.md)** - Integration and file structure
- **[Examples](../../shared/reference/examples.md)** - Real-world Jira integration workflows
- **[Best Practices](../../shared/reference/best-practices.md)** - Security, privacy, and workflow practices
## Common Questions
**Q: Why use curl instead of WebFetch?**
A: WebFetch doesn't support custom authentication headers needed for Jira API. curl with `-u` flag provides reliable Basic Authentication.
**Q: Do I need to manually invoke this skill?**
A: No! The skill automatically activates when it detects Jira issue keys in conversation.
**Q: Is this read-only?**
A: Yes. This integration only fetches data from Jira, it never creates or modifies issues.
**Q: What if I don't have credentials configured?**
A: The skill gracefully degrades. It will inform you that Jira integration is unavailable and proceed without it.
**Q: How do I verify credentials are working?**
A: Test with: `curl -s -u "$JIRA_EMAIL:$JIRA_TOKEN" "https://resolvesys.atlassian.net/rest/api/3/myself"`
**Q: Can I search for issues using JQL?**
A: Yes! Use `jira-search "project = PLAT AND type = Bug"` to search using Jira Query Language.
## Triggers
This skill activates when you mention:
- Jira issue keys (e.g., "PLAT-123", "JIRA-456")
- "jira" command explicitly
- "get issue" or "fetch ticket"
- "check Jira" or "look up issue"
- When other skills need issue context (SM decomposing epic, Dev implementing story)
---
**Skill Version**: 1.1.0
**Integration Type**: Read-Only (curl + Bash)
**Icon**: 🎫
**Last Updated**: 2025-11-20
**Method**: curl via Bash tool with Basic Authentication

View File

@@ -0,0 +1,417 @@
# Jira REST API Reference
## Overview
This document provides detailed information about using the Jira REST API v3 for fetching issue context in PRISM workflows.
## Base Configuration
From [core-config.yaml](../../../core-config.yaml):
```yaml
jira:
enabled: true
baseUrl: https://resolvesys.atlassian.net
email: ${JIRA_EMAIL}
token: ${JIRA_API_TOKEN}
defaultProject: PLAT
issueKeyPattern: "[A-Z]+-\\d+"
```
## Authentication
All API requests require Basic Authentication:
```
Authorization: Basic base64(email:token)
```
Where:
- `email`: Your Atlassian account email (from `JIRA_EMAIL` env var)
- `token`: Your Jira API token (from `JIRA_API_TOKEN` env var)
**Security Notes:**
- Never hardcode credentials in code
- Never embed credentials in URLs
- WebFetch tool handles authentication securely
- Credentials are read from environment variables via core-config.yaml
## API Endpoints
### 1. Get Issue Details
**Endpoint:**
```
GET /rest/api/3/issue/{issueKey}
```
**URL Example:**
```
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
```
**Response Fields:**
- `key`: Issue key (e.g., "PLAT-123")
- `fields.summary`: Issue title
- `fields.description`: Full description (Atlassian Document Format)
- `fields.issuetype.name`: Type (Epic, Story, Bug, Task, Subtask)
- `fields.status.name`: Current status
- `fields.priority.name`: Priority level
- `fields.assignee`: Assignee details
- `fields.reporter`: Reporter details
- `fields.parent`: Parent issue (for Subtasks)
- `fields.customfield_xxxxx`: Epic Link (custom field ID varies)
- `fields.timetracking`: Original/remaining estimates
- `fields.customfield_xxxxx`: Story Points (custom field ID varies)
- `fields.comment.comments[]`: Array of comments
- `fields.issuelinks[]`: Linked issues
- `fields.labels[]`: Labels
- `fields.components[]`: Components
- `fields.fixVersions[]`: Fix versions
**Usage with WebFetch:**
```
WebFetch:
url: https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
prompt: |
Extract and format the following information from this Jira issue:
- Issue Key and Type (Epic/Story/Bug/Task)
- Summary and Description
- Status and Priority
- Assignee and Reporter
- Epic Link (if applicable)
- Story Points (if applicable)
- Acceptance Criteria (from description or custom field)
- Comments (last 3 most recent)
- Linked Issues (blocks, is blocked by, relates to)
- Labels and Components
Format as a clear, structured summary for development context.
```
### 2. Search Issues (JQL)
**Endpoint:**
```
GET /rest/api/3/search?jql={query}
```
**URL Example:**
```
https://resolvesys.atlassian.net/rest/api/3/search?jql=project=PLAT+AND+type=Epic
```
**Common JQL Queries:**
**Get all epics in project:**
```jql
project = PLAT AND type = Epic
```
**Get all child stories of an epic:**
```jql
parent = PLAT-789
```
**Get all open bugs:**
```jql
project = PLAT AND type = Bug AND status != Done
```
**Get issues assigned to me:**
```jql
project = PLAT AND assignee = currentUser()
```
**Get recently updated issues:**
```jql
project = PLAT AND updated >= -7d
```
**Response Structure:**
```json
{
"total": 25,
"maxResults": 50,
"startAt": 0,
"issues": [
{
"key": "PLAT-123",
"fields": { ... }
}
]
}
```
**Usage with WebFetch:**
```
WebFetch:
url: https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
prompt: |
List all issues returned from this search.
For each issue, extract:
- Issue Key
- Type
- Summary
- Status
- Assignee
Format as a numbered list.
```
### 3. Get Epic Issues
**Endpoint:**
```
GET /rest/api/3/search?jql=parent={epicKey}
```
**URL Example:**
```
https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
```
**Purpose:**
Retrieves all Stories, Tasks, and Subtasks that belong to a specific Epic.
**Usage:**
Essential for Story Master when decomposing epics to:
- See existing child stories
- Avoid duplication
- Understand epic scope
- Identify gaps in decomposition
**Usage with WebFetch:**
```
WebFetch:
url: https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789
prompt: |
List all child stories/tasks for this epic.
For each, extract:
- Issue Key
- Summary
- Status
- Story Points (if available)
Calculate total story points across all children.
```
### 4. Get Issue Comments
**Endpoint:**
```
GET /rest/api/3/issue/{issueKey}/comment
```
**URL Example:**
```
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123/comment
```
**Response:**
```json
{
"comments": [
{
"id": "12345",
"author": {
"displayName": "John Doe",
"emailAddress": "john@example.com"
},
"body": { ... },
"created": "2025-01-15T10:30:00.000+0000",
"updated": "2025-01-15T10:30:00.000+0000"
}
]
}
```
**Note:** Comments are included in issue details response by default. Use this endpoint only if you need ALL comments (issue details returns recent comments only).
### 5. Get Issue Transitions
**Endpoint:**
```
GET /rest/api/3/issue/{issueKey}/transitions
```
**Note:** This is a read-only integration. We do not modify issues, so transition endpoints are informational only.
## Rate Limiting
Jira Cloud enforces rate limits:
**Limits:**
- **Per-user**: 300 requests per minute
- **Per-app**: Based on your plan
**Best Practices:**
- Cache issue data for the conversation session
- Avoid fetching same issue multiple times
- Use search queries to fetch multiple issues in one request
- Batch operations when possible
**Handling Rate Limits:**
If you receive 429 (Too Many Requests):
```
Display: "Jira rate limit reached. Please wait a moment before fetching more issues."
Action: Wait and retry, or proceed without additional Jira data
```
## Custom Fields
Many Jira fields are custom and vary by instance:
**Common Custom Fields:**
- **Epic Link**: `customfield_10014` (varies by instance)
- **Story Points**: `customfield_10016` (varies by instance)
- **Sprint**: `customfield_10020` (varies by instance)
- **Epic Name**: `customfield_10011` (for Epic issues)
**Finding Custom Field IDs:**
1. Fetch any issue and examine the response
2. Look for `customfield_*` entries
3. Match field names to IDs in your instance
**Usage Tip:**
Use the WebFetch extraction prompt to handle custom fields generically:
```
Extract story points if available (may be in customfield_10016 or similar)
```
The AI extraction will find the relevant field without hardcoding IDs.
## Response Formats
### Atlassian Document Format (ADF)
Jira descriptions and comments use ADF (JSON structure):
```json
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is the description"
}
]
}
]
}
```
**Handling ADF:**
Use WebFetch's AI extraction to convert ADF to readable text:
```
prompt: "Extract the description text from this issue and format as plain markdown"
```
## Error Codes
**400 Bad Request:**
- Invalid JQL syntax
- Malformed request
**401 Unauthorized:**
- Missing or invalid credentials
- Expired API token
**403 Forbidden:**
- User lacks permission to view issue
- Issue is in restricted project
**404 Not Found:**
- Issue key does not exist
- Issue was deleted
**429 Too Many Requests:**
- Rate limit exceeded
- Wait and retry
**500 Internal Server Error:**
- Jira service issue
- Retry or proceed without Jira data
## Example WebFetch Usage
### Fetch Single Issue
```javascript
// In Claude Code workflow
WebFetch({
url: "https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123",
prompt: `
Extract and format this Jira issue:
**[PLAT-123]**: {summary}
**Type**: {type}
**Status**: {status}
**Priority**: {priority}
**Description**:
{description as markdown}
**Acceptance Criteria**:
{extract AC from description if present}
**Assignee**: {assignee name}
**Reporter**: {reporter name}
**Linked Issues**:
- {list linked issues with relationship type}
**Comments** (last 3):
- {author}: {comment text}
`
})
```
### Search for Epic Children
```javascript
WebFetch({
url: "https://resolvesys.atlassian.net/rest/api/3/search?jql=parent=PLAT-789",
prompt: `
List all child stories for this epic:
1. [PLAT-XXX] {summary} - {status} - {story points}
2. [PLAT-YYY] {summary} - {status} - {story points}
Total Story Points: {sum of all story points}
Completed: {count of Done stories}
In Progress: {count of In Progress stories}
Todo: {count of To Do stories}
`
})
```
## Testing
**Verify Configuration:**
```bash
# Check environment variables
echo $JIRA_EMAIL
echo $JIRA_API_TOKEN
# Test API connection
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
https://resolvesys.atlassian.net/rest/api/3/myself
```
**Test Issue Fetch:**
```bash
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123
```
## References
- [Jira REST API v3 Documentation](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/)
- [JQL (Jira Query Language)](https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/)
- [Atlassian Document Format](https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/)

View File

@@ -0,0 +1,385 @@
# Jira Authentication Guide
## Overview
The Jira integration uses Basic Authentication with API tokens to securely access Jira Cloud. This document covers setup, security best practices, and troubleshooting.
## Authentication Method
**Jira Cloud REST API v3** uses Basic Authentication:
```
Authorization: Basic base64(email:api_token)
```
**NOT** username/password (deprecated and insecure).
## Setup Instructions
### Step 1: Generate API Token
1. Log in to your Atlassian account
2. Visit: https://id.atlassian.com/manage-profile/security/api-tokens
3. Click **"Create API token"**
4. Give it a name (e.g., "PRISM Local Development")
5. Copy the generated token (you won't see it again!)
### Step 2: Configure Environment Variables
1. Navigate to your project repository root
2. Copy the example environment file:
```bash
cp .env.example .env
```
3. Edit `.env` and add your credentials:
```env
JIRA_EMAIL=your.email@resolve.io
JIRA_API_TOKEN=your_generated_api_token_here
```
4. Verify `.env` is in `.gitignore` (it should be!)
### Step 3: Verify Configuration
Test your credentials:
```bash
# Unix/Linux/Mac
curl -u $JIRA_EMAIL:$JIRA_API_TOKEN \
https://resolvesys.atlassian.net/rest/api/3/myself
# Windows PowerShell
$env:JIRA_EMAIL
$env:JIRA_API_TOKEN
curl.exe -u "${env:JIRA_EMAIL}:${env:JIRA_API_TOKEN}" `
https://resolvesys.atlassian.net/rest/api/3/myself
```
**Expected Response**: JSON with your user details
**Error Response**: 401 Unauthorized (check credentials)
## core-config.yaml Configuration
The Jira configuration in [core-config.yaml](../../../core-config.yaml):
```yaml
jira:
enabled: true
baseUrl: https://resolvesys.atlassian.net
email: ${JIRA_EMAIL}
token: ${JIRA_API_TOKEN}
defaultProject: PLAT
issueKeyPattern: "[A-Z]+-\\d+"
```
**Field Descriptions**:
- `enabled`: Master switch for Jira integration
- `baseUrl`: Your Jira Cloud instance URL
- `email`: Environment variable reference for email
- `token`: Environment variable reference for API token
- `defaultProject`: Default project key for issue detection
- `issueKeyPattern`: Regex pattern for detecting issue keys
**Placeholders** (`${VARIABLE}`):
- Automatically replaced with environment variable values
- Keeps secrets out of version control
- Allows per-developer configuration
## Security Best Practices
### ✅ DO
**Store Credentials Securely:**
- Use environment variables (`JIRA_EMAIL`, `JIRA_API_TOKEN`)
- Use `.env` file for local development (gitignored)
- Use secure secrets management for production (if applicable)
**Protect API Tokens:**
- Treat API tokens like passwords
- Never commit to version control
- Rotate tokens periodically (every 90 days recommended)
- Use descriptive token names (e.g., "PRISM Dev - John Laptop")
- Revoke unused tokens immediately
**Limit Token Scope:**
- Use account with read-only Jira access if possible
- Create dedicated "service account" for integrations
- Request minimum necessary permissions
**In Code:**
- Never hardcode credentials in source files
- Never embed credentials in URLs (`https://user:pass@domain.com`)
- Use WebFetch tool which handles auth headers securely
- Never log credentials in debug output
### ❌ DON'T
**Never:**
- Commit `.env` file to git
- Hardcode credentials in code
- Share API tokens in chat, email, or docs
- Use passwords (use API tokens only)
- Embed credentials in URLs
- Log credentials in debug output
- Share credentials between developers (each gets their own)
**Avoid:**
- Using personal accounts for shared integrations
- Storing tokens in plaintext outside `.env`
- Reusing tokens across multiple projects
- Leaving old tokens active after switching machines
## WebFetch Authentication
Claude Code's WebFetch tool handles authentication automatically:
### How It Works
1. WebFetch reads `core-config.yaml`
2. Resolves `${JIRA_EMAIL}` and `${JIRA_API_TOKEN}` from environment
3. Constructs `Authorization: Basic base64(email:token)` header
4. Includes header in all Jira API requests
5. Credentials never exposed in logs or output
### Usage Example
```javascript
// You don't need to handle auth manually!
WebFetch({
url: "https://resolvesys.atlassian.net/rest/api/3/issue/PLAT-123",
prompt: "Extract issue details"
})
// WebFetch automatically:
// 1. Reads JIRA_EMAIL and JIRA_API_TOKEN from env
// 2. Adds Authorization header
// 3. Makes authenticated request
```
### What You Don't Need to Do
**Don't do this** (WebFetch handles it):
```javascript
// WRONG - Don't manually construct auth
const auth = btoa(`${email}:${token}`);
const headers = { Authorization: `Basic ${auth}` };
```
**Do this** (let WebFetch handle it):
```javascript
// RIGHT - Just provide the URL
WebFetch({ url: jiraUrl, prompt: "..." })
```
## Environment Variable Loading
### Local Development
**.env File** (in repository root):
```env
# Jira Integration
JIRA_EMAIL=john.doe@resolve.io
JIRA_API_TOKEN=ATATT3xFfGF0abc123xyz...
# Other services
GITHUB_TOKEN=ghp_abc123...
```
**Loading Priority**:
1. System environment variables (if set)
2. `.env` file in current directory
3. `.env` file in parent directories (searches up)
**dotenv Support**:
PRISM uses dotenv-style loading. Ensure your environment supports it.
### CI/CD / Production
For automated environments:
**GitHub Actions**:
```yaml
env:
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
```
**Docker**:
```bash
docker run \
-e JIRA_EMAIL=$JIRA_EMAIL \
-e JIRA_API_TOKEN=$JIRA_API_TOKEN \
your-image
```
**AWS/Cloud**:
Use secure secrets management (AWS Secrets Manager, etc.)
## Troubleshooting
### 401 Unauthorized
**Symptoms**:
- "Invalid credentials" error
- API returns 401 status code
**Causes**:
1. Incorrect email address
2. Incorrect or expired API token
3. Token revoked in Atlassian account
4. Using password instead of API token
**Solutions**:
1. Verify `JIRA_EMAIL` matches your Atlassian account email
2. Generate new API token and update `.env`
3. Check token is active at https://id.atlassian.com/manage-profile/security/api-tokens
4. Ensure using API token, not password
### 403 Forbidden
**Symptoms**:
- "Access denied" error
- API returns 403 status code
**Causes**:
1. Account lacks permission to view issue
2. Issue in restricted project
3. Account lacks Jira license
**Solutions**:
1. Verify you can view the issue in Jira web UI
2. Request access to the project from Jira admin
3. Ensure account has Jira Software license
### Environment Variables Not Found
**Symptoms**:
- `${JIRA_EMAIL}` not replaced in config
- Undefined variable errors
**Causes**:
1. `.env` file missing
2. `.env` in wrong location
3. Environment variables not exported
4. Typo in variable names
**Solutions**:
1. Create `.env` file in repository root
2. Verify `.env` contains `JIRA_EMAIL=...` and `JIRA_API_TOKEN=...`
3. Restart terminal/IDE to reload environment
4. Check variable names match exactly (case-sensitive)
**Test Variables**:
```bash
# Unix/Linux/Mac
echo $JIRA_EMAIL
echo $JIRA_API_TOKEN
# Windows PowerShell
echo $env:JIRA_EMAIL
echo $env:JIRA_API_TOKEN
# Windows CMD
echo %JIRA_EMAIL%
echo %JIRA_API_TOKEN%
```
### Rate Limiting (429)
**Symptoms**:
- "Rate limit exceeded" error
- API returns 429 status code
**Causes**:
- Too many requests in short time
- Exceeded 300 requests/minute limit
**Solutions**:
- Wait 60 seconds before retrying
- Implement session caching to reduce duplicate requests
- Batch operations when possible
## Permissions Required
**Minimum Jira Permissions**:
- **Browse Projects**: View issues in project
- **View Issues**: Read issue details
- **View Comments**: Read issue comments
**NOT Required**:
- Create/Edit issues (read-only integration)
- Assign issues
- Transition issues
- Admin permissions
**Recommended Setup**:
- Use account with "Jira Software" license
- Ensure access to all projects you need to integrate
- Consider dedicated "integration" account for team use
## Token Management
### Rotation Schedule
**Recommended**:
- Rotate tokens every 90 days
- Rotate immediately if:
- Token potentially exposed
- Developer leaves team
- Device lost or stolen
**Rotation Process**:
1. Generate new token in Atlassian
2. Update `.env` with new token
3. Test integration
4. Revoke old token in Atlassian
5. Document rotation in team wiki
### Multiple Tokens
You can create multiple tokens for different purposes:
**Example**:
- "PRISM Dev - Laptop" (local development)
- "PRISM Dev - Desktop" (work machine)
- "PRISM CI/CD" (automated testing)
**Benefits**:
- Revoke specific token without affecting others
- Identify which integration is making requests
- Isolate security incidents
## Team Collaboration
### Individual Credentials
**Each developer should**:
1. Generate their own API token
2. Configure their own `.env` file
3. Never share tokens with teammates
**Why**:
- Audit trail (know who accessed what)
- Security (revoke individual access)
- Accountability (track API usage per person)
### Shared Documentation
**Team wiki should include**:
1. Link to this authentication guide
2. Link to generate API tokens
3. Where to put `.env` file
4. Who to contact for access issues
5. Jira projects available for integration
**Do NOT include**:
- Actual API tokens
- Actual email/password combinations
- Shared credentials
## References
- [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
- [Jira Cloud REST API Authentication](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#authentication)
- [Basic Authentication RFC 7617](https://tools.ietf.org/html/rfc7617)

View File

@@ -0,0 +1,771 @@
# Jira Error Handling Guide
## Overview
This document provides comprehensive guidance on handling errors when integrating with Jira REST API, including error detection, graceful degradation, and user communication.
## Error Handling Principles
### 1. Graceful Degradation
**Never halt the entire workflow** due to Jira issues:
- Inform user of Jira unavailability
- Offer to proceed without Jira context
- Log error details for troubleshooting
- Continue with requested task when possible
### 2. User-Friendly Messages
**Avoid technical jargon** in user-facing messages:
- ❌ "HTTP 403 Forbidden - Insufficient scopes"
- ✅ "Access denied to PLAT-123. Please check Jira permissions."
### 3. Actionable Guidance
**Tell users what to do next**:
- Verify issue key spelling
- Check Jira permissions
- Contact Jira admin
- Proceed without Jira context
- Retry after waiting
### 4. Privacy & Security
**Never expose sensitive details**:
- Don't show API tokens in error messages
- Don't log credentials in debug output
- Don't reveal internal system details to users
## HTTP Status Codes
### 400 Bad Request
**Meaning**: Invalid request syntax or parameters
**Common Causes**:
- Invalid JQL syntax in search queries
- Malformed JSON in request body (not applicable for read-only)
- Invalid issue key format
**Example Scenarios**:
**Invalid JQL**:
```
URL: /rest/api/3/search?jql=invalid syntax here
Error: JQL query is invalid
```
**User Message**:
```markdown
❌ Invalid search query. Please check your JQL syntax.
You searched for: "invalid syntax here"
Common JQL format:
- project = PLAT AND type = Bug
- assignee = currentUser()
- status != Done
```
**Handling Code**:
```javascript
if (response.status === 400) {
displayMessage(`
Invalid Jira search query. The JQL syntax may be incorrect.
Would you like to:
1. Try a simpler search
2. View JQL examples
3. Proceed without searching
`);
// Offer alternatives, don't halt
}
```
### 401 Unauthorized
**Meaning**: Missing, invalid, or expired credentials
**Common Causes**:
- API token not set in environment
- Incorrect email address
- Expired or revoked API token
- Using password instead of API token
**Example Scenarios**:
**Missing Credentials**:
```
Error: JIRA_EMAIL or JIRA_API_TOKEN not found in environment
```
**User Message**:
```markdown
❌ Jira integration not configured.
To enable Jira integration:
1. Generate API token: https://id.atlassian.com/manage-profile/security/api-tokens
2. Add to .env file:
```
JIRA_EMAIL=your.email@resolve.io
JIRA_API_TOKEN=your_token_here
```
3. Restart your terminal/IDE
For now, I'll proceed without Jira context.
```
**Invalid Credentials**:
```
Error: HTTP 401 from Jira API
```
**User Message**:
```markdown
❌ Jira authentication failed. Your credentials may be incorrect or expired.
Please verify:
- JIRA_EMAIL matches your Atlassian account email
- JIRA_API_TOKEN is a valid, active API token
- Token hasn't been revoked
Generate new token: https://id.atlassian.com/manage-profile/security/api-tokens
Proceeding without Jira context for now.
```
**Handling Code**:
```javascript
if (response.status === 401) {
// Check if credentials are configured at all
if (!hasJiraCredentials()) {
displayMessage("Jira integration not configured. See setup instructions.");
} else {
displayMessage("Jira authentication failed. Please verify your credentials.");
}
// Continue workflow without Jira
return null; // Indicate no Jira data available
}
```
### 403 Forbidden
**Meaning**: Authenticated but lacks permission
**Common Causes**:
- User lacks permission to view issue
- Issue in restricted project
- User lacks Jira license
- Project permissions changed
**Example Scenarios**:
**Issue in Restricted Project**:
```
Error: You do not have permission to view this issue
Issue: PLAT-123
```
**User Message**:
```markdown
❌ Access denied to [PLAT-123](https://resolvesys.atlassian.net/browse/PLAT-123).
This could mean:
- The issue is in a restricted project
- You don't have permission to view this issue
- The project permissions recently changed
Please:
- Verify you can access the issue in Jira web UI
- Request access from your Jira administrator
- Double-check the issue key
Would you like to proceed without this issue's context?
```
**Handling Code**:
```javascript
if (response.status === 403) {
displayMessage(`
Access denied to ${issueKey}.
You may not have permission to view this issue.
You can still view it in Jira web UI if accessible:
${jiraUrl}/browse/${issueKey}
Proceed without Jira context? (y/n)
`);
// Wait for user decision
// Continue without Jira or halt if user requests
}
```
### 404 Not Found
**Meaning**: Issue does not exist
**Common Causes**:
- Typo in issue key
- Issue was deleted
- Issue moved to different project (key changed)
- Wrong Jira instance
**Example Scenarios**:
**Non-Existent Issue**:
```
Error: Issue does not exist
Issue: PLAT-9999
```
**User Message**:
```markdown
❌ Could not find Jira issue [PLAT-9999](https://resolvesys.atlassian.net/browse/PLAT-9999).
Possible reasons:
- Typo in issue key (check spelling and number)
- Issue was deleted or moved
- Issue is in a different project
Would you like to:
1. Search for similar issues
2. Verify the issue key
3. Proceed without Jira context
```
**Typo Detection**:
```javascript
if (response.status === 404) {
// Suggest likely corrections
const suggestions = findSimilarIssueKeys(issueKey);
displayMessage(`
Issue ${issueKey} not found.
Did you mean:
${suggestions.map(s => `- ${s}`).join('\n')}
Or proceed without Jira context?
`);
}
```
### 429 Too Many Requests
**Meaning**: Rate limit exceeded
**Common Causes**:
- Exceeded 300 requests per minute (per user)
- Multiple rapid fetches in short time
- Shared API token hitting combined limits
**Example Scenarios**:
**Rate Limit Hit**:
```
Error: Rate limit exceeded
Retry-After: 60 seconds
```
**User Message**:
```markdown
⏱️ Jira rate limit reached. Please wait a moment.
Jira Cloud limits requests to 300 per minute per user.
I'll automatically retry in 60 seconds, or you can:
- Wait and try again manually
- Proceed without fetching additional Jira issues
- Use cached issue data if available
```
**Handling Code**:
```javascript
if (response.status === 429) {
const retryAfter = response.headers['Retry-After'] || 60;
displayMessage(`
Jira rate limit exceeded.
Waiting ${retryAfter} seconds before retry...
`);
// Implement exponential backoff
await sleep(retryAfter * 1000);
// Retry request
return retryRequest(url, maxRetries - 1);
}
```
**Prevention**:
- Cache fetched issues for conversation session
- Batch operations when possible
- Avoid fetching same issue multiple times
- Use search queries to fetch multiple issues at once
### 500 Internal Server Error
**Meaning**: Jira service error
**Common Causes**:
- Jira service temporarily down
- Database issues on Jira side
- Unexpected server error
- Maintenance window
**Example Scenarios**:
**Service Outage**:
```
Error: HTTP 500 Internal Server Error
```
**User Message**:
```markdown
⚠️ Jira service error. The Jira server may be temporarily unavailable.
This is typically a temporary issue on Jira's side.
You can:
- Check Jira status: https://status.atlassian.com/
- Retry in a few minutes
- Proceed without Jira context for now
I'll continue with your request using available information.
```
**Handling Code**:
```javascript
if (response.status >= 500) {
displayMessage(`
Jira service is temporarily unavailable.
Check status: https://status.atlassian.com/
Proceeding without Jira context.
`);
// Log error for troubleshooting
logError('Jira 500 error', { issueKey, timestamp: new Date() });
// Continue workflow without Jira
return null;
}
```
### 502/503/504 Gateway/Service Errors
**Meaning**: Jira proxy or gateway issues
**Common Causes**:
- Network connectivity issues
- Jira proxy/gateway timeout
- Temporary service degradation
**User Message**:
```markdown
⚠️ Unable to reach Jira. Network or service issue detected.
This is usually temporary. You can:
- Retry in a few moments
- Check your network connection
- Check Jira status: https://status.atlassian.com/
- Proceed without Jira context
Continuing with available information...
```
## Network Errors
### Connection Timeout
**Meaning**: Request took too long to complete
**User Message**:
```markdown
⏱️ Jira request timed out. The service may be slow or unreachable.
You can:
- Retry the request
- Check your network connection
- Proceed without Jira context
Continuing without Jira data...
```
**Handling Code**:
```javascript
try {
const response = await fetchWithTimeout(url, 30000); // 30s timeout
} catch (error) {
if (error.name === 'TimeoutError') {
displayMessage('Jira request timed out. Proceeding without Jira context.');
return null;
}
throw error;
}
```
### Connection Refused
**Meaning**: Cannot connect to Jira server
**User Message**:
```markdown
❌ Cannot connect to Jira. Network issue detected.
Please check:
- Your internet connection
- VPN connection (if required)
- Firewall settings
- Jira base URL in core-config.yaml
Proceeding without Jira integration.
```
### DNS Resolution Failed
**Meaning**: Cannot resolve Jira hostname
**User Message**:
```markdown
❌ Cannot resolve Jira hostname.
Please verify:
- Jira base URL in core-config.yaml: https://resolvesys.atlassian.net
- DNS settings
- Network connectivity
Proceeding without Jira context.
```
## Configuration Errors
### Missing Configuration
**Scenario**: Jira not configured in core-config.yaml
**Detection**:
```javascript
if (!config.jira || !config.jira.enabled) {
// Jira integration disabled or not configured
}
```
**User Message**:
```markdown
Jira integration is not enabled.
To enable:
1. Set `jira.enabled: true` in core-config.yaml
2. Configure JIRA_EMAIL and JIRA_API_TOKEN in .env
3. See: .prism/skills/jira/reference/authentication.md
Proceeding without Jira integration.
```
### Invalid Base URL
**Scenario**: Malformed Jira base URL
**User Message**:
```markdown
❌ Invalid Jira base URL in configuration.
Current: {current_url}
Expected format: https://your-domain.atlassian.net
Please correct in core-config.yaml.
```
### Missing Environment Variables
**Scenario**: JIRA_EMAIL or JIRA_API_TOKEN not set
**Detection**:
```javascript
if (!process.env.JIRA_EMAIL || !process.env.JIRA_API_TOKEN) {
// Credentials not configured
}
```
**User Message**:
```markdown
❌ Jira credentials not configured.
Required environment variables:
- JIRA_EMAIL
- JIRA_API_TOKEN
Setup instructions: .prism/skills/jira/reference/authentication.md
Proceeding without Jira integration.
```
## Issue-Specific Errors
### Invalid Issue Key Format
**Scenario**: Issue key doesn't match expected pattern
**Detection**:
```javascript
const issueKeyPattern = /^[A-Z]+-\d+$/;
if (!issueKeyPattern.test(issueKey)) {
// Invalid format
}
```
**User Message**:
```markdown
❌ Invalid issue key format: "{issueKey}"
Jira issue keys follow this pattern:
- PROJECT-123
- ABC-456
- PLAT-789
Format: {PROJECT_KEY}-{NUMBER}
All letters uppercase, hyphen, then numbers.
```
### Custom Field Not Found
**Scenario**: Expected custom field missing from issue
**Handling**:
```javascript
const storyPoints = issue.fields.customfield_10016 ||
issue.fields.storyPoints ||
null;
if (!storyPoints) {
// Handle gracefully - don't error, just note missing
displayField('Story Points', 'Not set');
}
```
**User Message**:
```markdown
## [PLAT-123] Story Title
...
- **Story Points**: Not set
...
```
## Error Recovery Strategies
### 1. Retry with Exponential Backoff
For transient errors (429, 500, 503):
```javascript
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.ok) {
return response;
}
// Retry on 429, 500, 503
if ([429, 500, 503].includes(response.status)) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await sleep(delay);
continue;
}
// Don't retry on 401, 403, 404
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}
```
### 2. Fallback to Cached Data
If fresh fetch fails, use cached data:
```javascript
try {
const freshData = await fetchIssue(issueKey);
cacheIssue(issueKey, freshData);
return freshData;
} catch (error) {
const cached = getCachedIssue(issueKey);
if (cached) {
displayMessage('⚠️ Using cached issue data (Jira temporarily unavailable)');
return cached;
}
// No cached data, proceed without Jira
return null;
}
```
### 3. Partial Success
For batch operations, handle individual failures:
```javascript
async function fetchMultipleIssues(issueKeys) {
const results = [];
const failed = [];
for (const key of issueKeys) {
try {
const issue = await fetchIssue(key);
results.push(issue);
} catch (error) {
failed.push({ key, error: error.message });
}
}
if (failed.length > 0) {
displayMessage(`
⚠️ Failed to fetch ${failed.length} issues:
${failed.map(f => `- ${f.key}: ${f.error}`).join('\n')}
Continuing with ${results.length} successfully fetched issues.
`);
}
return results;
}
```
### 4. Degrade Feature
If Jira unavailable, continue with reduced functionality:
```javascript
if (!jiraAvailable) {
displayMessage(`
Jira integration unavailable. Continuing with limited context.
Please provide issue details manually if needed:
- Summary
- Acceptance Criteria
- Technical requirements
`);
// Continue workflow, prompt user for manual input
return promptForManualIssueDetails();
}
```
## Logging & Debugging
### User-Facing Messages
**Keep concise and actionable**:
```markdown
✅ Good: "Access denied to PLAT-123. Please check permissions."
❌ Bad: "HTTPError: 403 Forbidden - insufficient_scope - user lacks jira.issue.read"
```
### Debug Logging
**Log details for troubleshooting** (not shown to user):
```javascript
function logJiraError(error, context) {
console.error('[Jira Integration Error]', {
timestamp: new Date().toISOString(),
issueKey: context.issueKey,
url: context.url,
status: error.status,
message: error.message,
// Never log credentials!
});
}
```
### Error Telemetry
**Track error patterns** for improvement:
```javascript
function trackJiraError(errorType) {
// Increment error counter
// Store in session metrics
// Help identify systemic issues
}
```
## Testing Error Scenarios
### Manual Testing
Test each error condition:
```bash
# 401 - Invalid credentials
JIRA_EMAIL=wrong@email.com JIRA_API_TOKEN=invalid jira PLAT-123
# 403 - Access denied (use issue you don't have access to)
jira RESTRICTED-999
# 404 - Not found
jira PLAT-99999999
# Invalid format
jira plat-123
jira PLAT123
jira 123
```
### Automated Testing
Mock error responses:
```javascript
describe('Jira Error Handling', () => {
test('401 shows auth help message', async () => {
mockFetch.mockResolvedValue({ status: 401 });
const result = await fetchIssue('PLAT-123');
expect(result).toBeNull();
expect(displayedMessage).toContain('authentication failed');
});
test('404 offers to search', async () => {
mockFetch.mockResolvedValue({ status: 404 });
await fetchIssue('PLAT-999');
expect(displayedMessage).toContain('search for similar issues');
});
});
```
## Best Practices Summary
### ✅ DO
- Provide clear, actionable error messages
- Degrade gracefully (never halt entire workflow)
- Offer alternatives (search, manual input, proceed without)
- Cache data to reduce API calls and handle failures
- Log errors for debugging (without exposing credentials)
- Retry transient errors with exponential backoff
- Respect rate limits
### ❌ DON'T
- Expose API tokens or credentials in errors
- Show technical jargon to users
- Halt workflow on Jira errors
- Retry non-transient errors (401, 403, 404)
- Ignore errors silently
- Spam API with rapid retries
- Assume Jira is always available
## References
- [Jira REST API Errors](https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#error-responses)
- [HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
- [Atlassian Status Page](https://status.atlassian.com/)

View File

@@ -0,0 +1,448 @@
# Issue Extraction Format
## Overview
This document defines the standard format for extracting and presenting Jira issue data in PRISM workflows.
## Standard Issue Summary Format
When fetching any Jira issue, use this consistent format:
```markdown
## [{ISSUE-KEY}] {Summary}
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/{ISSUE-KEY})
### Details
- **Type**: {Epic|Story|Bug|Task|Subtask}
- **Status**: {Status Name}
- **Priority**: {Priority Level}
- **Assignee**: {Assignee Name or "Unassigned"}
- **Reporter**: {Reporter Name}
### Description
{Description text formatted as markdown}
### Acceptance Criteria
{Extracted AC from description or custom field, formatted as checklist}
- [ ] Criterion 1
- [ ] Criterion 2
- [ ] Criterion 3
### Estimation
- **Story Points**: {Points or "Not estimated"}
- **Original Estimate**: {Hours or "Not set"}
- **Remaining**: {Hours or "Not set"}
### Linked Issues
- **Blocks**: [{KEY}] {Summary}
- **Is Blocked By**: [{KEY}] {Summary}
- **Relates To**: [{KEY}] {Summary}
- **Duplicates**: [{KEY}] {Summary}
### Components & Labels
- **Components**: {Component list or "None"}
- **Labels**: {Label list or "None"}
- **Fix Versions**: {Version list or "None"}
### Recent Comments (Last 3)
1. **{Author}** ({Date}):
{Comment text}
2. **{Author}** ({Date}):
{Comment text}
3. **{Author}** ({Date}):
{Comment text}
```
## Epic-Specific Format
When fetching an Epic, include additional hierarchy information:
```markdown
## [EPIC-KEY] {Epic Name}
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/EPIC-KEY)
### Epic Overview
- **Type**: Epic
- **Status**: {Status}
- **Epic Name**: {Epic custom field name}
- **Total Child Stories**: {Count}
- **Total Story Points**: {Sum of child story points}
### Epic Goal
{Epic description/goal}
### Acceptance Criteria
{Epic-level acceptance criteria}
### Child Stories
1. [[STORY-1]] {Summary} - {Status} - {Story Points} SP
2. [[STORY-2]] {Summary} - {Status} - {Story Points} SP
3. [[STORY-3]] {Summary} - {Status} - {Story Points} SP
**Progress**:
- ✅ Done: {count} ({percentage}%)
- 🔄 In Progress: {count}
- 📋 To Do: {count}
### Epic Dependencies
{Linked issues that block or are blocked by this epic}
### Components & Scope
- **Components**: {List}
- **Fix Version**: {Target release}
```
## Story-Specific Format
When fetching a Story:
```markdown
## [STORY-KEY] {Story Title}
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/STORY-KEY)
### Story Details
- **Type**: Story
- **Epic**: [[EPIC-KEY]] {Epic Name}
- **Status**: {Status}
- **Priority**: {Priority}
- **Assignee**: {Assignee}
- **Story Points**: {Points} SP
### User Story
{As a [user], I want [feature] so that [benefit]}
### Acceptance Criteria
- [ ] {Criterion 1}
- [ ] {Criterion 2}
- [ ] {Criterion 3}
### Technical Notes
{Extracted from description or comments}
### Subtasks
- [[SUBTASK-1]] {Summary} - {Status}
- [[SUBTASK-2]] {Summary} - {Status}
### Implementation Dependencies
- **Blocks**: {List}
- **Is Blocked By**: {List}
- **Related Stories**: {List}
### Development Context
{Any relevant technical comments, implementation notes, or decisions}
```
## Bug-Specific Format
When fetching a Bug:
```markdown
## [BUG-KEY] {Bug Summary}
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/BUG-KEY)
### Bug Details
- **Type**: Bug
- **Severity**: {Priority}
- **Status**: {Status}
- **Assignee**: {Assignee}
- **Reporter**: {Reporter}
- **Environment**: {Affected environment}
### Description
{Bug description}
### Steps to Reproduce
1. {Step 1}
2. {Step 2}
3. {Step 3}
### Expected Behavior
{What should happen}
### Actual Behavior
{What actually happens}
### Screenshots/Logs
{Reference to attachments or inline log snippets}
### Related Issues
- **Duplicates**: {Similar bugs}
- **Related Bugs**: {Potentially related issues}
### Customer Impact
{Extracted from comments or description}
### Investigation Notes
{Recent comments from developers}
```
## Extraction Prompt Templates
### General Issue Extraction
```
Extract and format the following information from this Jira issue:
- Issue Key and Type (Epic/Story/Bug/Task)
- Summary and Description
- Status and Priority
- Assignee and Reporter
- Epic Link (if applicable)
- Story Points (if applicable)
- Acceptance Criteria (from description or custom field)
- Comments (last 3 most recent)
- Linked Issues (blocks, is blocked by, relates to)
- Labels and Components
Format as a clear, structured markdown summary for development context.
```
### Epic with Children Extraction
```
Extract and format this Epic with all child stories:
**Epic Details**:
- Key, Name, Status
- Description and Goal
- Acceptance Criteria
**Child Stories**:
- List all child issues with key, summary, status, story points
- Calculate total story points
- Show completion progress (Done/In Progress/To Do)
**Dependencies**:
- Linked issues that affect this epic
Format as structured markdown with progress metrics.
```
### Story for Development Extraction
```
Extract and format this Story for implementation:
**Story Overview**:
- Key, Title, Epic Link
- Status, Priority, Assignee
**Requirements**:
- User story (As a... I want... So that...)
- Acceptance Criteria (as checklist)
**Technical Context**:
- Technical notes from description
- Implementation comments
- Blocked by / Blocking issues
**Subtasks**:
- List all subtasks with status
Format clearly for developer to start implementation.
```
### Bug Investigation Extraction
```
Extract and format this Bug for investigation:
**Bug Summary**:
- Key, Title, Severity, Status
**Reproduction**:
- Steps to reproduce
- Expected vs Actual behavior
**Customer Impact**:
- Who reported it
- How many affected
- Business impact
**Investigation**:
- Recent comments from team
- Related bugs or patterns
**Environment**:
- Where it occurs
- Version information
Format for support/developer to investigate.
```
## Field Mapping
### Standard Jira Fields to Display Names
| Jira API Field | Display Name |
|----------------|--------------|
| `fields.issuetype.name` | Type |
| `fields.status.name` | Status |
| `fields.priority.name` | Priority |
| `fields.assignee.displayName` | Assignee |
| `fields.reporter.displayName` | Reporter |
| `fields.summary` | Title/Summary |
| `fields.description` | Description |
| `fields.parent.key` | Parent Issue |
| `fields.comment.comments` | Comments |
| `fields.issuelinks` | Linked Issues |
| `fields.labels` | Labels |
| `fields.components` | Components |
| `fields.fixVersions` | Fix Versions |
| `fields.timetracking.originalEstimate` | Original Estimate |
| `fields.timetracking.remainingEstimate` | Remaining Estimate |
### Custom Fields (Instance-Specific)
| Custom Field | Typical ID | Display Name |
|--------------|------------|--------------|
| Epic Link | `customfield_10014` | Epic |
| Story Points | `customfield_10016` | Story Points |
| Sprint | `customfield_10020` | Sprint |
| Epic Name | `customfield_10011` | Epic Name |
| Acceptance Criteria | `customfield_xxxxx` | Acceptance Criteria |
**Note**: Custom field IDs vary by Jira instance. Use AI extraction to find relevant fields generically.
## Acceptance Criteria Extraction
Acceptance Criteria can appear in multiple places:
### From Description
Look for markers in description text:
- "Acceptance Criteria:"
- "AC:"
- "Success Criteria:"
- Lists that follow these markers
### From Custom Field
Some instances have dedicated AC custom field:
- `customfield_xxxxx` (varies by instance)
- Usually contains structured list
### Extraction Strategy
```
1. Check for dedicated AC custom field first
2. If not found, scan description for AC markers
3. Extract list items following markers
4. Format as checklist:
- [ ] Criterion 1
- [ ] Criterion 2
5. If no explicit AC found, note: "No explicit acceptance criteria defined"
```
## Handling Missing Data
Not all issues have all fields. Handle gracefully:
```markdown
### Field Display Rules
- **Missing Assignee**: Display "Unassigned"
- **No Story Points**: Display "Not estimated"
- **No Epic Link**: Omit Epic section entirely
- **No Comments**: Display "No comments"
- **No Linked Issues**: Display "No linked issues"
- **No Labels**: Display "None"
- **No Description**: Display "No description provided"
- **No Acceptance Criteria**: Display "No explicit acceptance criteria defined"
```
## Clickable Links
Always include clickable Jira links:
```markdown
**🔗 Link**: [View in Jira](https://resolvesys.atlassian.net/browse/PLAT-123)
**Epic**: [[PLAT-789]](https://resolvesys.atlassian.net/browse/PLAT-789) Authentication System
**Blocked By**: [[PLAT-456]](https://resolvesys.atlassian.net/browse/PLAT-456) Database schema update
```
## Session Caching
When an issue is fetched, cache it for the conversation session:
```markdown
## Cached Issue Data
Store in memory for current conversation:
- Issue key → Full issue data
- Last fetched timestamp
- TTL: End of conversation session
Reuse cached data when:
- Same issue referenced again in conversation
- Reduces API calls
- Ensures consistency during session
Refetch when:
- User explicitly requests refresh
- Cached data is from previous session
- User mentions issue status changed
```
## Formatting Best Practices
### Markdown Elements
**Use**:
- Headers (`##`, `###`) for sections
- Bullet lists for non-sequential items
- Numbered lists for sequential items (steps)
- Checkboxes (`- [ ]`) for acceptance criteria
- Bold (`**text**`) for field names
- Links (`[text](url)`) for Jira references
- Code blocks (` ``` `) for logs or JSON
**Avoid**:
- Excessive nested lists (max 2 levels)
- Tables for small data (use lists instead)
- All-caps text
- Emojis (except standard status icons: ✅ 🔄 📋 🔗)
### Readability
- Keep line length reasonable (~80-100 chars)
- Use blank lines to separate sections
- Indent nested content consistently
- Format dates consistently (YYYY-MM-DD or relative "3 days ago")
- Truncate very long descriptions (show first ~500 chars + "...")
### Context Awareness
Adjust verbosity based on use case:
**For Story Master (Epic Decomposition)**:
- Emphasize epic goal and scope
- Show all child stories
- Highlight gaps or missing stories
**For Developer (Implementation)**:
- Emphasize acceptance criteria
- Show technical notes prominently
- Include blocking issues
**For Support (Bug Investigation)**:
- Emphasize reproduction steps
- Show customer comments
- Highlight related bugs
**For QA (Test Planning)**:
- Emphasize acceptance criteria
- Show expected behavior
- List related test issues
## Examples
See [Examples](../../../shared/reference/examples.md#jira-workflows) for complete real-world extraction examples.