skills/anton-abyzov/specweave/jira-resource-validator

jira-resource-validator

SKILL.md

Jira Resource Validator Skill

Purpose: Validate and auto-create Jira projects and boards, ensuring .env configuration is correct.

Auto-Activation: Triggers when Jira setup or validation is needed.

What This Skill Does

This skill ensures your Jira configuration in .env is valid and all resources exist. It's smart enough to:

  1. Validate Jira projects - Check if JIRA_PROJECT exists
  2. Prompt for action - Select existing project or create new one
  3. Validate Jira boards - Check if boards exist (by ID or name)
  4. Create missing boards - If board names provided, create them automatically
  5. Update .env with IDs - Replace board names with actual board IDs after creation

When This Skill Activates

Automatically activates when:

  • You set up Jira integration for the first time
  • You run /sw-jira:sync and resources are missing
  • Your .env has invalid Jira configuration
  • You mention "jira setup" or "jira validation"

Jira Configuration Structure

Required .env Variables

JIRA_API_TOKEN=your_token_here
JIRA_EMAIL=your_email@company.com
JIRA_DOMAIN=yourcompany.atlassian.net
JIRA_STRATEGY=board-based
JIRA_PROJECT=PROJECTKEY
JIRA_BOARDS=1,2,3  # IDs (if exist) OR names (if creating)

Smart Per-Board Detection (Mixed Mode Support!)

The system is smart enough to handle ANY combination of IDs and names:

All IDs (validate existing boards):

JIRA_BOARDS=1,2,3

→ Validates boards 1, 2, 3 exist

All Names (create new boards):

JIRA_BOARDS=Frontend,Backend,Mobile

→ Creates 3 boards, updates .env with IDs: JIRA_BOARDS=101,102,103

Mixed IDs and Names (smart handling!):

JIRA_BOARDS=101,102,QA,Dashboard

→ Validates 101, 102 exist → Creates "QA" and "Dashboard" boards → Updates .env: JIRA_BOARDS=101,102,103,104 (all IDs!)

How it works: Each entry is checked individually:

  • Numeric (e.g., "123") → Validate ID exists
  • Non-numeric (e.g., "QA") → Create board with that name
  • After creation, .env is updated with ALL board IDs

NEW: Per-Project Configuration (Advanced - Multiple Projects × Boards)

Multiple JIRA projects with their own boards:

# Multiple projects with their own boards
JIRA_STRATEGY=project-per-team
JIRA_PROJECTS=BACKEND,FRONTEND,MOBILE

# Per-project boards (hierarchical naming)
JIRA_BOARDS_BACKEND=123,456         # Sprint + Kanban (IDs)
JIRA_BOARDS_FRONTEND=Sprint,Bug     # Create these boards
JIRA_BOARDS_MOBILE=789,012,345      # iOS + Android + Release (IDs)

→ Validates 3 projects exist: BACKEND, FRONTEND, MOBILE → Validates/creates boards per project:

  • BACKEND: Validates boards 123, 456 exist
  • FRONTEND: Creates "Sprint" and "Bug" boards, updates .env with IDs
  • MOBILE: Validates boards 789, 012, 345 exist

Naming Convention: {PROVIDER}_{RESOURCE_TYPE}_{PROJECT_KEY}

Mixed IDs and Names Per Project:

JIRA_BOARDS_BACKEND=123,NewBoard,456

→ Validates 123, 456 exist → Creates "NewBoard" → Updates .env: JIRA_BOARDS_BACKEND=123,789,456 (all IDs!)

Validation Flow

Step 1: Project Validation

Check if project exists:

# API call to Jira
GET /rest/api/3/project/PROJECTKEY

If project exists:

✅ Project "PROJECTKEY" exists
   ID: 10001
   Name: My Project

If project doesn't exist:

⚠️  Project "PROJECTKEY" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [1]:

Option 1: Select Existing:

Available projects:
1. PROJ1 - Project One
2. PROJ2 - Project Two
3. PROJ3 - Project Three

Select a project [1]:

✅ Updated .env: JIRA_PROJECT=PROJ1

Option 2: Create New:

Enter project name: My New Project

📦 Creating Jira project: PROJECTKEY (My New Project)...
✅ Project created: PROJECTKEY (ID: 10005)

Step 2: Board Validation (Per-Board Smart Detection)

Scenario A: All Board IDs (all numeric):

JIRA_BOARDS=1,2,3

Validation:

Checking boards: 1,2,3...
  ✅ Board 1: Frontend Board (exists)
  ✅ Board 2: Backend Board (exists)
  ⚠️  Board 3: Not found

⚠️  Issues found: 1 board(s)

Scenario B: All Board Names (all non-numeric):

JIRA_BOARDS=Frontend,Backend,Mobile

Auto-creation:

Checking boards: Frontend,Backend,Mobile...
  📦 Creating board: Frontend...
  ✅ Created: Frontend (ID: 101)
  📦 Creating board: Backend...
  ✅ Created: Backend (ID: 102)
  📦 Creating board: Mobile...
  ✅ Created: Mobile (ID: 103)

📝 Updating .env with board IDs...
✅ Updated JIRA_BOARDS: 101,102,103

✅ All boards validated/created successfully

Scenario C: Mixed IDs and Names (SMART!):

JIRA_BOARDS=101,102,QA,Dashboard

Smart handling:

Checking boards: 101,102,QA,Dashboard...
  ✅ Board 101: Frontend Board (exists)
  ✅ Board 102: Backend Board (exists)
  📦 Creating board: QA...
  ✅ Created: QA (ID: 103)
  📦 Creating board: Dashboard...
  ✅ Created: Dashboard (ID: 104)

📝 Updating .env with board IDs...
✅ Updated JIRA_BOARDS: 101,102,103,104

✅ All boards validated/created successfully

Usage Examples

Example 1: Fresh Jira Setup

Scenario: New project, no Jira resources exist yet

Action: Run /sw-jira:sync

What Happens:

🔍 Validating Jira configuration...

Checking project: MINIDOOM...
⚠️  Project "MINIDOOM" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [2]: 2

Enter project name: Mini DOOM Tournament

📦 Creating Jira project: MINIDOOM (Mini DOOM Tournament)...
✅ Project created: MINIDOOM (ID: 10005)

Checking boards: Frontend,Backend,Mobile...
📦 Creating boards from names...

Creating board: Frontend in project MINIDOOM...
✅ Board created: Frontend (ID: 101)

Creating board: Backend in project MINIDOOM...
✅ Board created: Backend (ID: 102)

Creating board: Mobile in project MINIDOOM...
✅ Board created: Mobile (ID: 103)

✅ Updated .env: JIRA_BOARDS=101,102,103

🎉 Jira configuration complete! All resources ready.

Result: .env now has correct project and board IDs

Example 2: Select Existing Project

Scenario: Project already exists in Jira

Action: Run validation

What Happens:

🔍 Validating Jira configuration...

Checking project: PROJ...
⚠️  Project "PROJ" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [1]: 1

Available projects:
1. FRONTEND - Frontend Team
2. BACKEND - Backend Team
3. MOBILE - Mobile Team

Select a project [1]: 2

✅ Updated .env: JIRA_PROJECT=BACKEND
✅ Project "BACKEND" exists

Checking boards: 45,46...
✅ All boards exist

Example 3: Mixed Board IDs (Some Exist, Some Don't)

Scenario: Some board IDs are invalid

Action: Run validation

What Happens:

🔍 Validating Jira configuration...

Checking project: PROJECTKEY...
✅ Project "PROJECTKEY" exists

Checking boards: 1,2,999...

Board 1: ✅ Exists (Frontend Board)
Board 2: ✅ Exists (Backend Board)
Board 999: ❌ Not found

⚠️  Boards not found: 999

Available boards in project PROJECTKEY:
1. Frontend Board (ID: 1)
2. Backend Board (ID: 2)
3. QA Board (ID: 3)
4. DevOps Board (ID: 4)

Would you like to:
1. Remove invalid board (999) from configuration
2. Replace with correct board ID
3. Create new board

Your choice [2]: 2

Enter correct board ID or name: 3

✅ Updated .env: JIRA_BOARDS=1,2,3

CLI Command

Manual validation:

# From TypeScript
npx tsx src/utils/external-resource-validator.ts

# Or via skill activation
"Can you validate my Jira configuration?"

Validation output:

{
  valid: true,
  project: {
    exists: true,
    key: 'PROJECTKEY',
    id: '10001',
    name: 'My Project'
  },
  boards: {
    valid: true,
    existing: [1, 2, 3],
    missing: [],
    created: []
  },
  envUpdated: false
}

Smart Board Creation Logic (Per-Board Detection)

Detection Algorithm

// Parse JIRA_BOARDS from .env
const boardsConfig = "101,102,QA,Dashboard"; // Mixed!
const boardEntries = boardsConfig.split(',').map(b => b.trim());
const finalBoardIds = [];

// Check EACH board individually
for (const entry of boardEntries) {
  const isNumeric = /^\d+$/.test(entry);

  if (isNumeric) {
    // Entry is a board ID - validate it exists
    const boardId = parseInt(entry);
    const board = await checkBoard(boardId);
    if (board) {
      console.log(`✅ Board ${boardId}: ${board.name} (exists)`);
      finalBoardIds.push(boardId);
    } else {
      console.error(`⚠️  Board ${boardId}: Not found`);
    }
  } else {
    // Entry is a board name - create it
    console.log(`📦 Creating board: ${entry}...`);
    const board = await createBoard(entry, projectKey);
    console.log(`✅ Created: ${entry} (ID: ${board.id})`);
    finalBoardIds.push(board.id);
  }
}

// Update .env if any boards were created
if (createdBoardIds.length > 0) {
  updateEnv({ JIRA_BOARDS: finalBoardIds.join(',') });
}

Key improvement: Per-board detection instead of all-or-nothing!

  • JIRA_BOARDS=1,2,3 → Validates all IDs
  • JIRA_BOARDS=A,B,C → Creates all boards
  • JIRA_BOARDS=1,2,C → Validates 1,2, creates C (mixed!)

Board Creation API

Jira REST API (v3):

POST /rest/api/3/board
Content-Type: application/json

{
  "name": "Frontend Board",
  "type": "scrum",
  "filterId": 10000,  # Filter for project issues
  "location": {
    "type": "project",
    "projectKeyOrId": "PROJECTKEY"  # CRITICAL: Associates board with project
  }
}

Response:
{
  "id": 101,
  "name": "Frontend Board",
  "type": "scrum"
}

IMPORTANT: The location field is MANDATORY to associate the board with a project. Without it, Jira creates the board but leaves it detached, requiring manual connection via the UI.

Filter creation (required for board):

POST /rest/api/3/filter
Content-Type: application/json

{
  "name": "PROJECTKEY Issues",
  "jql": "project = PROJECTKEY"
}

Response:
{
  "id": 10000
}

Configuration Examples

Example 1: All Names (Create Boards)

Before (.env):

JIRA_PROJECT=PROJ
JIRA_BOARDS=Frontend,Backend,QA,DevOps

After validation:

JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103,104

What happened:

  • Detected non-numeric values (names)
  • Created 4 boards in Jira
  • Updated .env with actual board IDs

Example 2: All IDs (Validate Existing)

Before (.env):

JIRA_PROJECT=PROJ
JIRA_BOARDS=1,2,3

After validation:

JIRA_PROJECT=PROJ
JIRA_BOARDS=1,2,3

What happened:

  • Detected numeric values (IDs)
  • Validated all boards exist
  • No changes needed

Example 3: Mixed IDs and Names (SMART!)

Before (.env):

JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,QA,Dashboard

After validation:

JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103,104

What happened:

  • Validated boards 101, 102 exist
  • Created "QA" board (got ID 103)
  • Created "Dashboard" board (got ID 104)
  • Updated .env with ALL board IDs
  • This is the key feature - you can mix existing IDs with new board names!

Example 4: Fix Invalid Project

Before (.env):

JIRA_PROJECT=NONEXISTENT
JIRA_BOARDS=1,2

After validation (user selected existing project):

JIRA_PROJECT=EXISTINGPROJ
JIRA_BOARDS=1,2

What happened:

  • Project NONEXISTENT not found
  • User selected EXISTINGPROJ from list
  • Updated .env with correct project key

Error Handling

Error 1: Invalid Credentials

Symptom: API calls fail with 401 Unauthorized

Solution:

❌ Jira API authentication failed

Please check:
1. JIRA_API_TOKEN is correct
2. JIRA_EMAIL matches your Jira account
3. JIRA_DOMAIN is correct (yourcompany.atlassian.net)

Generate new token at:
https://id.atlassian.com/manage-profile/security/api-tokens

Error 2: Insufficient Permissions

Symptom: Cannot create projects/boards (403 Forbidden)

Solution:

❌ Insufficient permissions to create resources

You need:
- Project Creator permission (for projects)
- Board Creator permission (for boards)

Contact your Jira administrator to request permissions.

Error 3: Project Key Already Taken

Symptom: Project creation fails (key exists)

Solution:

❌ Project key "PROJ" already exists

Options:
1. Use a different project key
2. Select the existing project
3. Cancel

Your choice [2]:

Error 4: Network/API Errors

Symptom: API calls timeout or fail

Solution:

❌ Jira API error: Request timeout

Please check:
1. Internet connection
2. Jira domain is correct
3. Jira is not down (check status.atlassian.com)

Retry? [Y/n]:

Integration with SpecWeave Workflow

Automatic Validation

When using /sw-jira:sync, validation runs automatically:

/sw-jira:sync 0014

# Internally calls:
1. validateJiraResources()
2. Fix missing project/boards
3. Proceed with sync

Manual Validation

Run validation independently:

# Via skill
"Validate my Jira configuration"

# Via TypeScript
npx tsx src/utils/external-resource-validator.ts

# Via CLI (future)
specweave validate-jira

Best Practices

Use board names for initial setup:

JIRA_BOARDS=Sprint-1,Sprint-2,Backlog
  • System creates boards automatically
  • Updates .env with IDs
  • One-time setup, then use IDs

Use board IDs after creation:

JIRA_BOARDS=101,102,103
  • Faster validation (no creation needed)
  • More reliable (IDs don't change)

Keep .env in version control (gitignored tokens):

# Commit project/board structure
JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103

# Don't commit sensitive data
JIRA_API_TOKEN=<redacted>
JIRA_EMAIL=<redacted>

Document board mapping (in README):

## Jira Boards

- Board 101: Frontend Team
- Board 102: Backend Team
- Board 103: QA Team

Summary

This skill ensures your Jira configuration is always valid by:

  1. Validating projects - Check if project exists, prompt to select or create
  2. Validating boards - Check if boards exist (IDs) or create them (names)
  3. Auto-updating .env - Replace board names with IDs after creation
  4. Clear error messages - Actionable guidance for all failures
  5. Non-blocking - Graceful degradation with manual fallback

Result: Zero manual Jira setup - system handles everything!


Skill Version: 1.0.0 Introduced: SpecWeave v0.9.5 Last Updated: 2025-11-09

Weekly Installs
10
Installed on
claude-code9
opencode7
cursor7
codex7
antigravity7
gemini-cli7