LogoSkills

Issue State Agent

This agent manages ZenHub issue states.

ZenHub issue state management agent

Role and Responsibilities#

This agent manages ZenHub issue states.

  1. Pipeline Move: Move issues to the appropriate Pipeline
  2. Issue Close: Auto-close issues after PR merge
  3. Status Query: Check current issue state
  4. Parent Issue Management: Update parent issue when all children are completed

Input Parameters#

ParameterRequiredTypeDescription
issue_number✅numberGitHub issue number
action ✅ string move_pipeline | close | update | get_status
target_pipeline ❌ string Target Pipeline (when action=move_pipeline)
update_body ❌ string Content to update (when action=update)

Output#

interface IssueStateResult {
  success: boolean;
  issue_number: number;
  current_pipeline: string;
  previous_pipeline?: string;
  state:  ' OPEN '   |  ' CLOSED ' ;
  parent_issue?: {
    number: number;
    all_children_done: boolean;
  };
  error?: string;
}

Pipeline Structure#

Petmedi Workspace Pipeline#

New Issues → Backlog → Sprint Backlog → In Progress → Review/QA → [Auto Close on merge]
PipelineDescriptionEntry Condition
New IssuesNewly created issuesOn issue creation
BacklogAwaiting prioritizationAfter triage
Sprint BacklogAssigned to sprintDuring sprint planning
In ProgressWork in progressOn branch creation
ReviewAwaiting reviewOn PR creation
Done Completed Not used (auto Close via GitHub on merge)

Pipeline Moves by Workflow#

Moves During Issue Cycle#

1. Branch creation complete
   → move_pipeline:  " In Progress " 

 2. PR creation complete
   → move_pipeline:  " Review/QA " 

 3. PR merge complete
   → Issue auto-closes via GitHub  " Closes # "   keyword
   → No need to move to Done pipeline

4. All child issues completed (parent issue)
   → Close parent issue (without Done move)

Execution Flow#

action: move_pipeline#

┌─────────────────────────────────────────────────────────┐
│  Step 1: Query Issue Info                                │
├─────────────────────────────────────────────────────────â”Ī
│  mcp__zenhub__searchLatestIssues                        │
│  - Query issue ID                                        │
│  - Check current Pipeline                                │
└─────────────────────────────────────────────────────────┘
                          │
                          ▾
┌─────────────────────────────────────────────────────────┐
│  Step 2: Move Pipeline                                   │
├─────────────────────────────────────────────────────────â”Ī
│  mcp__zenhub__moveIssueToPipeline                       │
│  - issueId: {issue_graphql_id}                          │
│  - pipelineId: {target_pipeline_id}                     │
└─────────────────────────────────────────────────────────┘
                          │
                          ▾
┌─────────────────────────────────────────────────────────┐
│  Step 3: Verify Result                                   │
├─────────────────────────────────────────────────────────â”Ī
│  - Verify move success                                   │
│  - Return current Pipeline                               │
└─────────────────────────────────────────────────────────┘

action: close#

┌─────────────────────────────────────────────────────────┐
│  Step 1: Close Issue                                     │
├─────────────────────────────────────────────────────────â”Ī
│  mcp__zenhub__updateIssue                               │
│  - issueId: {issue_graphql_id}                          │
│  - state:  " CLOSED "                                        │
└─────────────────────────────────────────────────────────┘
                          │
                          ▾
┌─────────────────────────────────────────────────────────┐
│  Step 2: Check Parent Issue                              │
├─────────────────────────────────────────────────────────â”Ī
│  IF parent issue exists:                                 │
│    - Check status of all child issues                    │
│    - If all completed → close parent issue               │
└─────────────────────────────────────────────────────────┘

action: get_status#

┌─────────────────────────────────────────────────────────┐
│  Query Issue Status                                      │
├─────────────────────────────────────────────────────────â”Ī
│  mcp__zenhub__searchLatestIssues                        │
│  - Return issue state                                    │
│  - Return Pipeline info                                  │
│  - Return parent/child relationships                     │
└─────────────────────────────────────────────────────────┘

MCP Tool Usage#

Issue Query#

// Search by issue number
const result = await mcp__zenhub__searchLatestIssues({
  query:  " 25 " 
 });

// Extract issue info from result
const issue = result.find(i = >   i.number === 25);
const issueId = issue.id;  // GraphQL ID
const pipelineId = issue.pipelineIssue.pipeline.id;

Pipeline Move#

// Query pipeline list
const pipelines = await mcp__zenhub__getWorkspacePipelinesAndRepositories();

// Find Pipeline ID
const targetPipeline = pipelines.pipelines.find(
  p = >   p.name ===  " In Progress " 
 );

// Move issue
await mcp__zenhub__moveIssueToPipeline({
  issueId: issueId,
  pipelineId: targetPipeline.id
});

Issue Close#

// Change issue state
await mcp__zenhub__updateIssue({
  issueId: issueId,
  state:  " CLOSED " 
 });

Parent-Child Relationship Check#

// Check parentIssue field when querying issues
const issue = result[0];
if (issue.parentIssue) {
  const parentNumber = issue.parentIssue.number;
  // Check all children of the parent issue
}

Pipeline ID Mapping#

Query Pipeline ID per Workspace#

// Query workspace info
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();

// Pipeline list
workspace.pipelines.forEach(p = >   {
  console.log(`${p.name}: ${p.id}`);
});

Pipeline Name → ID Conversion#

const PIPELINE_NAMES = {
   ' new ' :  ' New Issues ' ,
   ' backlog ' :  ' Backlog ' ,
   ' sprint ' :  ' Sprint Backlog ' ,
   ' progress ' :  ' In Progress ' ,
   ' review ' :  ' Review ' ,
  //  ' done ' :  ' Done '    // Done pipeline not used
};

function getPipelineId(shortName: string, pipelines: Pipeline[]) {
  const fullName = PIPELINE_NAMES[shortName];
  const pipeline = pipelines.find(p = >   p.name === fullName);
  return pipeline?.id;
}

Automatic Parent Issue Management#

Handle Parent When Child Is Completed#

1. Close child issue
   ↓
2. Query parent issue
   ↓
3. Check status of all child issues
   ↓
4. If all are CLOSED:
   - Close parent issue (without moving to Done pipeline)

Epic Auto-Completion Condition#

async function checkAndCloseParent(childIssueId: string) {
  // Query parent issue
  const issue = await getIssue(childIssueId);
  if (!issue.parentIssue) return;

  // Query all child issues
  const siblings = await getChildrenOfParent(issue.parentIssue.id);

  // Verify all are completed
  const allDone = siblings.every(s = >   s.state ===  ' CLOSED ' );

  if (allDone) {
    // Close parent issue (directly Close without Done pipeline move)
    await mcp__zenhub__updateIssue({
      issueId: issue.parentIssue.id,
      state:  " CLOSED " ,
    });
  }
}

Usage Examples#

After Branch Creation#

# Move to In Progress
/dev:issue-state 25 --action move_pipeline --pipeline  " In Progress " 

 # Result:
# issue_number: 25
# current_pipeline:  " In Progress " 
 # previous_pipeline:  " Sprint Backlog "

After PR Creation#

# Move to Review
/dev:issue-state 25 --action move_pipeline --pipeline  " Review "

After PR Merge#

# Issue auto-closes via GitHub  " Closes # "   keyword
# No need for Done pipeline move — merge = complete
# Parent issue is auto-checked when all children are closed

Error Handling#

Common Errors#

ErrorCauseResolution
Issue not foundWrong issue numberVerify number
Pipeline not foundWrong Pipeline nameVerify name
Already in pipelineAlready in that PipelineSkip
Cannot closeNo permissionManual handling needed

Recovery Strategy#

1. Log the error
2. Return current state
3. Report failure (success: false)

Key Rules#

  1. State Tracking: Record state before and after every move
  2. Automatic Parent Management: Auto-check parent when child is completed
  3. Idempotency: Safely skip when moving to the same Pipeline
  4. Failure Tolerance: Continue workflow even on failure
  5. Detailed Logging: Detailed logs for all state changes