LogoSkills

/dev:issue

This skill automates the entire development cycle from branch creation to merge for a single ZenHub/GitHub issue.

Execute the full development cycle for a single issue

Overview#

This skill automates the entire development cycle from branch creation to merge for a single ZenHub/GitHub issue.


Usage#

/dev:issue {issue_number}

Parameters#

ParameterRequiredDescription
issue_numberโœ…GitHub issue number

Options#

/dev:issue 25 --no-merge      # PR only, without merge
/dev:issue 25 --skip-tests    # Skip tests (for urgent hotfixes)
/dev:issue 25 --base main     # Change base branch
/dev:issue 25 --bdd           # Force BDD scenario generation
/dev:issue 25 --skip-bdd      # Skip BDD scenarios
/dev:issue 25 --skip-review   # Skip code review (for urgent hotfixes)

Execution Flow#

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    /dev:issue                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                 โ”‚
โ”‚  Step 1: ์ด์Šˆ ์ •๋ณด ์กฐํšŒ                                           โ”‚
โ”‚  โ”œโ”€โ”€ mcp__zenhub__searchLatestIssues                            โ”‚
โ”‚  โ”œโ”€โ”€ ์ด์Šˆ ํƒ€์ž…, ์ œ๋ชฉ, ๋ณธ๋ฌธ ์ถ”์ถœ                                     โ”‚
โ”‚  โ”œโ”€โ”€ ํ™”๋ฉด ํƒ€์ž… ๊ฐ์ง€ (๋ชฉ๋ก/์ƒ์„ธ/ํผ)                                  โ”‚
โ”‚  โ””โ”€โ”€ ๋ถ€๋ชจ/์ž์‹ ๊ด€๊ณ„ ํ™•์ธ                                           โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 2: ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ                                              โ”‚
โ”‚  โ”œโ”€โ”€ Task(subagent_type:  " issue-branch-agent " )                  โ”‚
โ”‚  โ”œโ”€โ”€ issue-state-agent โ†’  " In Progress "   ์ด๋™                      โ”‚
โ”‚  โ””โ”€โ”€ ๊ฒฐ๊ณผ: feature/{number}-{slug}                               โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 3: BDD ์‹œ๋‚˜๋ฆฌ์˜ค ์ž‘์„ฑ (ํ™”๋ฉด ๊ธฐ๋Šฅ ์‹œ) โ† NEW                     โ”‚
โ”‚  โ”œโ”€โ”€ Task(subagent_type:  " bdd-scenario-agent " )                  โ”‚
โ”‚  โ”œโ”€โ”€ Gherkin Feature ํŒŒ์ผ ์ƒ์„ฑ                                    โ”‚
โ”‚  โ”œโ”€โ”€ Step Definition ์ƒ์„ฑ                                        โ”‚
โ”‚  โ””โ”€โ”€ ์ปค๋ฐ‹:  " test({scope}): โœ… BDD ์‹œ๋‚˜๋ฆฌ์˜ค ์ž‘์„ฑ "                      โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 4: ๊ตฌํ˜„ ์ž‘์—…                                                โ”‚
โ”‚  โ”œโ”€โ”€ Task(subagent_type:  " implementation-agent " )                โ”‚
โ”‚  โ”œโ”€โ”€ ์ด์Šˆ ๋‚ด์šฉ ๋ถ„์„ โ†’ ๋ ˆ์ด์–ด ์—์ด์ „ํŠธ ์œ„์ž„                            โ”‚
โ”‚  โ””โ”€โ”€ ์ฆ๋ถ„ ์ปค๋ฐ‹ ์ƒ์„ฑ                                                โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 5: ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋ฐ ๊ฒ€์ฆ (ํ•„์ˆ˜ ๊ฒŒ์ดํŠธ) โš ๏ธ                        โ”‚
โ”‚  โ”œโ”€โ”€ [ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ - ํ•„์ˆ˜]                                      โ”‚
โ”‚  โ”‚   โ”œโ”€โ”€ UseCase ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (unit-test-agent)                     โ”‚
โ”‚  โ”‚   โ””โ”€โ”€ BLoC ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (bloc-test-agent)                        โ”‚
โ”‚  โ”œโ”€โ”€ [๋ฐฑ์—”๋“œ ํ…Œ์ŠคํŠธ - Backend ๋ณ€๊ฒฝ ์‹œ ํ•„์ˆ˜]                           โ”‚
โ”‚  โ”‚   โ”œโ”€โ”€ ์—”๋“œํฌ์ธํŠธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (serverpod-test-agent)               โ”‚
โ”‚  โ”‚   โ”œโ”€โ”€ ์„œ๋น„์Šค ๋กœ์ง ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (serverpod-test-agent)              โ”‚
โ”‚  โ”‚   โ””โ”€โ”€ ์—”๋“œํฌ์ธํŠธ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (serverpod-test-agent)               โ”‚
โ”‚  โ”œโ”€โ”€ BDD Widget ํ…Œ์ŠคํŠธ (ํ™”๋ฉด ๊ธฐ๋Šฅ ์‹œ)                                โ”‚
โ”‚  โ”œโ”€โ”€ test-runner-agent ํ˜ธ์ถœ (require_tests: true)                โ”‚
โ”‚  โ”œโ”€โ”€ โš ๏ธ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ํ•„์ˆ˜ (๊ฒŒ์ดํŠธ ์‹คํŒจ ์‹œ PR ์ƒ์„ฑ ์ฐจ๋‹จ)            โ”‚
โ”‚  โ””โ”€โ”€ ์‹คํŒจ ์‹œ ์ž๋™ ์ˆ˜์ • ์‹œ๋„ (์ตœ๋Œ€ 3ํšŒ)                               โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 6: PR ์ƒ์„ฑ                                                  โ”‚
โ”‚  โ”œโ”€โ”€ gh pr create                                                โ”‚
โ”‚  โ”œโ”€โ”€ Closes #{issue_number} ์ž๋™ ํฌํ•จ                             โ”‚
โ”‚  โ””โ”€โ”€ issue-state-agent โ†’  " Review/QA "   ์ด๋™                        โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 7: ์ฝ”๋“œ ๋ฆฌ๋ทฐ ์ง„ํ–‰ โ† NEW                                      โ”‚
โ”‚  โ”œโ”€โ”€ /code-review ์ž๋™ ์‹คํ–‰                                       โ”‚
โ”‚  โ”œโ”€โ”€ ๋ฆฌ๋ทฐ ํ”ผ๋“œ๋ฐฑ ์ž๋™ ๋ฐ˜์˜ (format, analyze --fix)                  โ”‚
โ”‚  โ”œโ”€โ”€ /checklist:feature-complete ์‹คํ–‰                            โ”‚
โ”‚  โ””โ”€โ”€ ์žฌ๊ฒ€ํ†  ํ•„์š” ์‹œ ๋ฐ˜๋ณต                                            โ”‚
โ”‚                                                                 โ”‚
โ”‚  Step 8: ๋จธ์ง€ ์Šน์ธ ๋Œ€๊ธฐ                                            โ”‚
โ”‚  โ”œโ”€โ”€ ์ตœ์ข… ์ƒํƒœ ์š”์•ฝ ํ‘œ์‹œ                                            โ”‚
โ”‚  โ”œโ”€โ”€ ์‚ฌ์šฉ์ž ์Šน์ธ ์š”์ฒญ (AskUserQuestion)                            โ”‚
โ”‚  โ”œโ”€โ”€ ์Šน์ธ ์‹œ ์Šค์ฟผ์‹œ ๋จธ์ง€ ์‹คํ–‰                                       โ”‚
โ”‚  โ””โ”€โ”€ GitHub  " Closes # "   ํ‚ค์›Œ๋“œ๋กœ ์ด์Šˆ ์ž๋™ Close                    โ”‚
โ”‚                                                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Auto Screen Type Detection#

Detects screen keywords from issue title/body to decide whether to write BDD scenarios:

PatternScreen TypeBDD
"๋ชฉ๋ก", "๋ฆฌ์ŠคํŠธ", "list", "์กฐํšŒ"Listโœ… Generate
"์ƒ์„ธ", "detail", "๋ณด๊ธฐ"Detailโœ… Generate
"์ถ”๊ฐ€", "์ƒ์„ฑ", "๋“ฑ๋ก", "form"Formโœ… Generate
"์ˆ˜์ •", "ํŽธ์ง‘", "edit"Formโœ… Generate
"๋ฆฌํŒฉํ† ๋ง", "๊ฐœ์„ ", "์ตœ์ ํ™”"-โŒ Skip
"์„ค์ •", "ํ™˜๊ฒฝ", "๋นŒ๋“œ"-โŒ Skip

Detailed Implementation#

Step 1: Query Issue Info#

// ์ด์Šˆ ์ •๋ณด ์กฐํšŒ
const issueResult = await mcp__zenhub__searchLatestIssues({
  query: issue_number.toString()
});

const issue = issueResult.find(i = >   i.number === issue_number);

// ์ถ”์ถœํ•  ์ •๋ณด
const issueInfo = {
  id: issue.id,                    // GraphQL ID
  number: issue.number,            // GitHub ๋ฒˆํ˜ธ
  title: issue.title,              // ์ด์Šˆ ์ œ๋ชฉ
  body: issue.body,                // ์ด์Šˆ ๋ณธ๋ฌธ (Acceptance Criteria ํฌํ•จ)
  type: issue.issueType?.name,     // Feature, Task, Bug, Sub-task
  pipeline: issue.pipelineIssue?.pipeline?.name,
  parentIssue: issue.parentIssue,  // ๋ถ€๋ชจ ์ด์Šˆ ์ •๋ณด
  labels: issue.labels,            // ๋ผ๋ฒจ ๋ชฉ๋ก
};

Step 2: Branch Creation#

// ๋ธŒ๋žœ์น˜ ์—์ด์ „ํŠธ ํ˜ธ์ถœ
const branchResult = await Task({
  subagent_type:  " issue-branch-agent " ,
  prompt: `
    issue_number: ${issueInfo.number}
    issue_title: ${issueInfo.title}
    issue_type: ${issueInfo.type}
    base_branch: development

    ์ด ์ด์Šˆ๋ฅผ ์œ„ํ•œ ๋ธŒ๋žœ์น˜๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
  `
});

// Pipeline ์ด๋™: In Progress
await Task({
  subagent_type:  " issue-state-agent " ,
  prompt: `
    issue_number: ${issueInfo.number}
    action: move_pipeline
    target_pipeline:  " In Progress " 
   `
});

Step 3: BDD Scenario Writing (for screen features)#

// ํ™”๋ฉด ํƒ€์ž… ๊ฐ์ง€
const screenKeywords = {
  list: [ " ๋ชฉ๋ก " ,  " ๋ฆฌ์ŠคํŠธ " ,  " list " ,  " ์กฐํšŒ " ,  " ๊ฒ€์ƒ‰ " ],
  detail: [ " ์ƒ์„ธ " ,  " detail " ,  " ๋ณด๊ธฐ " ],
  form: [ " ์ถ”๊ฐ€ " ,  " ์ƒ์„ฑ " ,  " ์ˆ˜์ • " ,  " ํŽธ์ง‘ " ,  " form " ,  " ๋“ฑ๋ก " ],
};

const screenType = detectScreenType(issueInfo.title + issueInfo.body);
const requiresBdd = screenType !== null  & &   !options.skipBdd;

if (requiresBdd || options.bdd) {
  // BDD ์‹œ๋‚˜๋ฆฌ์˜ค ์—์ด์ „ํŠธ ํ˜ธ์ถœ
  await Task({
    subagent_type:  " bdd-scenario-agent " ,
    prompt: `
      feature_name: ${extractFeatureName(issueInfo)}
      entity_name: ${extractEntityName(issueInfo)}
      screen_type: ${screenType ||  " list " }

      ํ™”๋ฉด ํƒ€์ž…์— ๋งž๋Š” BDD ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
    `
  });

  // ์ปค๋ฐ‹
  const scope = extractScope(issueInfo);
  await Bash(`
    git add .
    git commit -m  " test(${scope}): โœ… BDD ์‹œ๋‚˜๋ฆฌ์˜ค ์ž‘์„ฑ

    - ${screenType} ํ™”๋ฉด ์‹œ๋‚˜๋ฆฌ์˜ค ์ถ”๊ฐ€
    - Step Definition ์ƒ์„ฑ

    Co-Authored-By: Claude Opus 4.5  < noreply@anthropic.com > " 
   `);
}

Step 4: Implementation Work#

// ๊ตฌํ˜„ ์—์ด์ „ํŠธ ํ˜ธ์ถœ
const implResult = await Task({
  subagent_type:  " implementation-agent " ,
  prompt: `
    issue_number: ${issueInfo.number}
    issue_body: ${issueInfo.body}
    issue_type: ${issueInfo.type}
    issue_title: ${issueInfo.title}

    ์ด์Šˆ ๋‚ด์šฉ์„ ๋ถ„์„ํ•˜๊ณ  ๊ตฌํ˜„ํ•ด์ฃผ์„ธ์š”.
    ์™„๋ฃŒ๋œ ์ž‘์—…๋งˆ๋‹ค ์ปค๋ฐ‹์„ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
  `
});

// ์ปค๋ฐ‹ ๊ฒฐ๊ณผ ํ™•์ธ
console.log(`์ƒ์„ฑ๋œ ์ปค๋ฐ‹: ${implResult.commits.length}๊ฐœ`);
console.log(`๋ณ€๊ฒฝ๋œ ํŒŒ์ผ: ${implResult.files_changed.length}๊ฐœ`);

Step 5: Test Writing and Verification (Required Gate)#

// Feature๋ช… ์ถ”์ถœ (์ด์Šˆ ์ œ๋ชฉ ๋˜๋Š” ์Šค์ฝ”ํ”„์—์„œ)
const featureName = extractFeatureName(issueInfo);

// Backend ๋ณ€๊ฒฝ ๊ฐ์ง€
const hasBackendChanges = detectBackendChanges(issueInfo);

// ํ…Œ์ŠคํŠธ ์œ ํ˜• ๊ฒฐ์ •
const testTypes = [ " unit " ,  " bloc " ];
if (requiresBdd) testTypes.push( " bdd " );
if (hasBackendChanges) testTypes.push( " backend_unit " ,  " backend_integration " );

// ํ…Œ์ŠคํŠธ ์—์ด์ „ํŠธ ํ˜ธ์ถœ (require_tests: true โ†’ ๋ˆ„๋ฝ ์‹œ ์ž๋™ ์ƒ์„ฑ)
const testResult = await Task({
  subagent_type:  " test-runner-agent " ,
  prompt: `
    feature_name: ${featureName}
    test_types: ${JSON.stringify(testTypes)}
    auto_fix: true
    require_tests: true

    ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•œ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•ด์ฃผ์„ธ์š”.
    โš ๏ธ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•ด์•ผ PR ์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  `
});

// โš ๏ธ ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ PR ์ƒ์„ฑ ์ฐจ๋‹จ
if (!testResult.success) {
  if (testResult.failures.some(f = >   !f.fixable)) {
    throw new Error(`ํ…Œ์ŠคํŠธ ์‹คํŒจ: ${testResult.failures.length}๊ฐœ - PR ์ƒ์„ฑ ์ฐจ๋‹จ`);
  }
}

Step 6: PR Creation#

// PR ์ƒ์„ฑ
const gitmoji = getGitmoji(issueInfo.type);
const scope = extractScope(issueInfo);

await Bash(`
  gh pr create --title  " ${gitmoji} ${scope}: ${issueInfo.title} "   \
    --body  " $(cat  < < ' EOF ' 
 ## Summary
- ${issueInfo.title}

## Test Plan
- [ ] UseCase ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ
- [ ] BLoC ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ
${hasBackendChanges ?  ' - [ ] ๋ฐฑ์—”๋“œ ์—”๋“œํฌ์ธํŠธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ '   :  ' ' }
${hasBackendChanges ?  ' - [ ] ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค ๋กœ์ง ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ '   :  ' ' }
${hasBackendChanges ?  ' - [ ] ๋ฐฑ์—”๋“œ ์—”๋“œํฌ์ธํŠธ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ '   :  ' ' }
${requiresBdd ?  ' - [ ] BDD ์‹œ๋‚˜๋ฆฌ์˜ค ํ†ต๊ณผ '   :  ' ' }

Closes #${issueInfo.number}

๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code)
EOF
) " 
 `);

// Pipeline ์ด๋™: Review/QA
await mcp__zenhub__moveIssueToPipeline({
  issueId: issueInfo.id,
  pipelineId: reviewQaPipelineId,
});

Step 7: Code Review#

if (!options.skipReview) {
  // /code-review ์ž๋™ ์‹คํ–‰
  await Skill({ skill:  " code-review "   });

  // ์ž๋™ ๋ฐ˜์˜ ๊ฐ€๋Šฅํ•œ ํ”ผ๋“œ๋ฐฑ ์ ์šฉ
  await Bash(`melos run format`);
  await Bash(`melos run analyze --fix`);

  // ์ˆ˜์ • ์‚ฌํ•ญ ์žˆ์œผ๋ฉด ์ปค๋ฐ‹
  const hasChanges = await Bash(`git status --porcelain`);
  if (hasChanges.stdout.trim()) {
    await Bash(`
      git add .
      git commit -m  " style(${scope}): ๐ŸŽจ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜

      - ํฌ๋งทํŒ… ์ ์šฉ
      - ๋ฆฐํŠธ ๊ฒฝ๊ณ  ์ˆ˜์ •

      Co-Authored-By: Claude Opus 4.5  < noreply@anthropic.com > " 
     `);
    await Bash(`git push`);
  }

  // /checklist:feature-complete ์‹คํ–‰
  await Skill({ skill:  " checklist:feature-complete "   });
}

Step 8: Wait for Merge Approval#

// ์ตœ์ข… ์ƒํƒœ ์š”์•ฝ ํ‘œ์‹œ
console.log(`
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘  Ready for Merge                                               โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ“‹ Issue: #${issueInfo.number} - ${issueInfo.title}           โ•‘
โ•‘  ๐Ÿ”€ PR: #${prNumber}                                           โ•‘
โ•‘  ๐ŸŒฟ Branch: ${branchResult.branch_name}                        โ•‘
โ•‘                                                                โ•‘
โ•‘  โœ… Tests: ${testResult.summary.passed}/${testResult.summary.total} passed
โ•‘  โœ… Review: All issues resolved                                โ•‘
โ•‘  โœ… Checklist: Passed                                          โ•‘
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ”’ Merge blocked until user approval                         โ•‘
โ•‘                                                                โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
`);

// ์‚ฌ์šฉ์ž ์Šน์ธ ์š”์ฒญ
const approval = await AskUserQuestion({
  questions: [{
    header:  " ๋จธ์ง€ " ,
    question:  " PR์„ ๋จธ์ง€ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? " ,
    options: [
      { label:  " ๋จธ์ง€ ์Šน์ธ " , description:  " ์Šค์ฟผ์‹œ ๋จธ์ง€ ํ›„ ์ด์Šˆ ํด๋กœ์ฆˆ "   },
      { label:  " ์ˆ˜์ • ํ•„์š” " , description:  " Step 4๋กœ ๋Œ์•„๊ฐ€์„œ ์ˆ˜์ • "   },
      { label:  " ์ทจ์†Œ " , description:  " ํ˜„์žฌ ์ƒํƒœ ์œ ์ง€ "   },
    ],
    multiSelect: false,
  }],
});

if (approval ===  " ๋จธ์ง€ ์Šน์ธ " ) {
  // ์Šค์ฟผ์‹œ ๋จธ์ง€ โ†’ GitHub  " Closes # "   ํ‚ค์›Œ๋“œ๋กœ ์ด์Šˆ ์ž๋™ Close
  // Done ํŒŒ์ดํ”„๋ผ์ธ ์ด๋™ ๋ถˆํ•„์š” (๋จธ์ง€ = ์™„๋ฃŒ)
  await Bash(`gh pr merge --squash --delete-branch`);
}

Output Format#

On Success#

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘  Issue Cycle Complete: #25                                     โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ“‹ Issue: feat(community): โœจ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ํ™”๋ฉด ๊ตฌํ˜„              โ•‘
โ•‘  ๐ŸŒฟ Branch: feature/25-community-list                          โ•‘
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ“ Commits:                                                   โ•‘
โ•‘    1. feat(community): โœจ domain layer ๊ตฌํ˜„                     โ•‘
โ•‘    2. feat(community): โœจ data layer ๊ตฌํ˜„                       โ•‘
โ•‘    3. feat(community): โœจ presentation layer ๊ตฌํ˜„               โ•‘
โ•‘                                                                โ•‘
โ•‘  โœ… Tests:                                                     โ•‘
โ•‘    - UseCase Unit: 12/12 passed                                โ•‘
โ•‘    - BLoC Unit: 8/8 passed                                     โ•‘
โ•‘    - Backend Unit: 6/6 (endpoint: 3, service: 3)               โ•‘
โ•‘    - Backend Integration: 4/4 passed                           โ•‘
โ•‘    - BDD: 5/5 scenarios passed                                 โ•‘
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ”€ PR: #42                                                    โ•‘
โ•‘    - URL: https://github.com/owner/repo/pull/42                โ•‘
โ•‘    - Reviews: 2 comments (auto-resolved)                       โ•‘
โ•‘    - Status: Merged โœ…                                         โ•‘
โ•‘                                                                โ•‘
โ•‘  ๐Ÿ“Š Duration: 15m 32s                                          โ•‘
โ•‘  ๐Ÿ Final State: CLOSED (by merge)                             โ•‘
โ•‘                                                                โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

On Failure#

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘  Issue Cycle Failed: #25                                       โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘                                                                โ•‘
โ•‘  โŒ Failed at: Step 4 (ํ…Œ์ŠคํŠธ ์‹คํ–‰)                              โ•‘
โ•‘                                                                โ•‘
โ•‘  Error Details:                                                โ•‘
โ•‘    - Test: post_list_bloc_test.dart                            โ•‘
โ•‘    - Reason: Expected PostLoaded but got PostError             โ•‘
โ•‘    - Fixable: No (logic error)                                 โ•‘
โ•‘                                                                โ•‘
โ•‘  Current State:                                                โ•‘
โ•‘    - Branch: feature/25-community-list (exists)                โ•‘
โ•‘    - Commits: 3 committed                                      โ•‘
โ•‘    - Pipeline: In Progress                                     โ•‘
โ•‘    - PR: Not created                                           โ•‘
โ•‘                                                                โ•‘
โ•‘  Recovery Options:                                             โ•‘
โ•‘    1. Fix the test manually and re-run                         โ•‘
โ•‘    2. /dev:issue 25 --skip-tests                    โ•‘
โ•‘                                                                โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Error Handling#

Step-by-Step Recovery Strategy#

Failed StepStateRecovery Method
Branch creationNo changesRetry
ImplementationBranch exists, some commitsContinue work
TestsCode complete, tests failedManual fix then retry
PR creationCode completeCreate PR manually or retry
MergePR exists, CI pendingWait for CI pass then retry
Issue closePR mergedManual close

Auto Recovery Attempt#

// ์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜
const MAX_RETRIES = 3;

async function executeWithRetry(step, retries = MAX_RETRIES) {
  for (let i = 0; i  <   retries; i++) {
    try {
      return await step();
    } catch (error) {
      if (i === retries - 1) throw error;
      console.log(`์žฌ์‹œ๋„ ${i + 1}/${retries}...`);
      await sleep(5000); // 5์ดˆ ๋Œ€๊ธฐ
    }
  }
}

TodoWrite Integration#

Progress Tracking#

// ์‹œ์ž‘ ์‹œ
TodoWrite([
  { content:  " ์ด์Šˆ ์ •๋ณด ์กฐํšŒ " , status:  " in_progress " , activeForm:  " ์ด์Šˆ ์ •๋ณด ์กฐํšŒ ์ค‘ "   },
  { content:  " ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ " , status:  " pending " , activeForm:  " ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ ๋Œ€๊ธฐ "   },
  { content:  " ๊ตฌํ˜„ ์ž‘์—… " , status:  " pending " , activeForm:  " ๊ตฌํ˜„ ์ž‘์—… ๋Œ€๊ธฐ "   },
  { content:  " ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋ฐ ๊ฒ€์ฆ (ํ•„์ˆ˜ ๊ฒŒ์ดํŠธ) " , status:  " pending " , activeForm:  " ํ…Œ์ŠคํŠธ ์ž‘์„ฑ/๊ฒ€์ฆ ๋Œ€๊ธฐ "   },
  { content:  " PR ์ƒ์„ฑ ๋ฐ ๋จธ์ง€ " , status:  " pending " , activeForm:  " PR ์ƒ์„ฑ ๋Œ€๊ธฐ "   },
  { content:  " ์ด์Šˆ ํด๋กœ์ฆˆ " , status:  " pending " , activeForm:  " ์ด์Šˆ ํด๋กœ์ฆˆ ๋Œ€๊ธฐ "   },
]);

// ๊ฐ ๋‹จ๊ณ„ ์™„๋ฃŒ ์‹œ ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธ
//  " completed " ๋กœ ๋งˆํ‚นํ•˜๊ณ  ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ  " in_progress " ๋กœ ๋ณ€๊ฒฝ

Key Rules#

  1. Sequential execution: Each step proceeds only after previous step succeeds
  2. State tracking: Record current state at every step
  3. Failure tolerance: Preserve current state on failure and provide clear recovery guide
  4. Issue linking: Reference issue number in all commits and PRs
  5. Auto cleanup: Auto-delete branch on success (after merge)
  6. Parent check: Auto-verify parent issue on issue close

Verification Gates (Required)#

Branch Verification (Before Step 2 Start)#

# ํ˜„์žฌ ๋ธŒ๋žœ์น˜ ํ™•์ธ
BRANCH=$(git rev-parse --abbrev-ref HEAD)

# development/main์—์„œ ์ง์ ‘ ์ž‘์—… ์‹œ์ž‘ ๊ธˆ์ง€
if [[ $BRANCH ==  " development "   || $BRANCH ==  " main "   ]]; then
  echo  " โŒ development/main์—์„œ ์ง์ ‘ ์ž‘์—…ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค " 
   echo  " " 
   echo  "     /dev:issue์€ Step 2์—์„œ ๋ธŒ๋žœ์น˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. " 
   echo  "     ํ˜„์žฌ development ๋ธŒ๋žœ์น˜์— ์žˆ๋‹ค๋ฉด ์ •์ƒ์ž…๋‹ˆ๋‹ค. " 
   echo  " " 
   # Step 2๊ฐ€ ๋ธŒ๋žœ์น˜๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ๊ณ„์† ์ง„ํ–‰
fi

Pre-PR Verification (Before Step 6)#

# 1. ๋ธŒ๋žœ์น˜ ํ˜•์‹ ๊ฒ€์ฆ
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ ! $BRANCH =~ ^(feature|fix|refactor|chore)/[0-9]+ ]]; then
  echo  " โŒ ๋ธŒ๋žœ์น˜ ํ˜•์‹ ์˜ค๋ฅ˜: $BRANCH " 
   echo  "     ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹: feature/{issue_number}-description " 
   echo  " " 
   echo  "     Step 2์—์„œ ๋ธŒ๋žœ์น˜๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. " 
   echo  "     /dev:issue์„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”. " 
   exit 1
fi

# 2. development/main ์ง์ ‘ ์ปค๋ฐ‹ ๋ฐฉ์ง€
if [[ $BRANCH ==  " development "   || $BRANCH ==  " main "   ]]; then
  echo  " โŒ development/main์— ์ง์ ‘ PR์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค " 
   exit 1
fi

# 3. ์ปค๋ฐ‹ ์กด์žฌ ํ™•์ธ
COMMITS=$(git rev-list --count origin/development..HEAD)
if [[ $COMMITS -eq 0 ]]; then
  echo  " โŒ ์ปค๋ฐ‹์ด ์—†์Šต๋‹ˆ๋‹ค. " 
   echo  "     Step 4 (๊ตฌํ˜„ ์ž‘์—…)์„ ๋จผ์ € ์™„๋ฃŒํ•ด์ฃผ์„ธ์š”. " 
   exit 1
fi

# 4. Pre-push ๊ฒ€์ฆ + ๋ฆฐํŠธ 0๊ฑด ๊ฒŒ์ดํŠธ
echo  " ๐Ÿ” Pre-push ๊ฒ€์ฆ ์ค‘... " 
 melos run format || { echo  " โŒ ํฌ๋งท ์˜ค๋ฅ˜ " ; exit 1; }
dart fix --apply  # ์ž๋™ ์ˆ˜์ • ๊ฐ€๋Šฅํ•œ ๋ฆฐํŠธ ์ด์Šˆ ์ผ๊ด„ ์ˆ˜์ •
melos run analyze 2 > & 1 | tee /tmp/analyze_output.txt
LINT_ISSUES=$(grep -c -E  ' \s+(info|warning|error)\s+[โ€ขยท-] '   /tmp/analyze_output.txt || true)
if [[ $LINT_ISSUES -gt 0 ]]; then
  echo  " โš ๏ธ flutter analyze ์ด์Šˆ ${LINT_ISSUES}๊ฑด โ€” ์ˆ˜๋™ ์ˆ˜์ • ํ›„ ์žฌ๊ฒ€์ฆ ํ•„์š” " 
   # ์ˆ˜๋™ ์ˆ˜์ • ์‹œ๋„ (์ตœ๋Œ€ 2ํšŒ ๋ฐ˜๋ณต) โ†’ 0๊ฑด ๋‹ฌ์„ฑ ํ•„์ˆ˜
  exit 1
fi
echo  " โœ… Pre-push ๊ฒ€์ฆ ํ†ต๊ณผ (๋ฆฐํŠธ 0๊ฑด) "

TodoWrite Integration (Required)#

Initialization (On Step 1 Start)#

TodoWrite([
  { content:  " Step 1: ์ด์Šˆ ์ •๋ณด ์กฐํšŒ " , status:  " in_progress " , activeForm:  " ์ด์Šˆ ์กฐํšŒ ์ค‘ "   },
  { content:  " Step 2: ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ " , status:  " pending " , activeForm:  " ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ ๋Œ€๊ธฐ "   },
  { content:  " Step 3: BDD ์‹œ๋‚˜๋ฆฌ์˜ค " , status:  " pending " , activeForm:  " BDD ์ž‘์„ฑ ๋Œ€๊ธฐ "   },
  { content:  " Step 4: ๊ตฌํ˜„ ์ž‘์—… " , status:  " pending " , activeForm:  " ๊ตฌํ˜„ ๋Œ€๊ธฐ "   },
  { content:  " Step 5: ํ…Œ์ŠคํŠธ ์‹คํ–‰ " , status:  " pending " , activeForm:  " ํ…Œ์ŠคํŠธ ๋Œ€๊ธฐ "   },
  { content:  " Step 5.5: Pre-push ๊ฒ€์ฆ + ๋ฆฐํŠธ 0๊ฑด ๊ฒŒ์ดํŠธ " , status:  " pending " , activeForm:  " ๊ฒ€์ฆ ๋Œ€๊ธฐ "   },
  { content:  " Step 6: PR ์ƒ์„ฑ " , status:  " pending " , activeForm:  " PR ์ƒ์„ฑ ๋Œ€๊ธฐ "   },
  { content:  " Step 7: ์ฝ”๋“œ ๋ฆฌ๋ทฐ " , status:  " pending " , activeForm:  " ๋ฆฌ๋ทฐ ๋Œ€๊ธฐ "   },
  { content:  " Step 8: ๋จธ์ง€ ์Šน์ธ " , status:  " pending " , activeForm:  " ๋จธ์ง€ ๋Œ€๊ธฐ "   },
]);

Update Immediately on Step Completion#

// ๊ฐ ๋‹จ๊ณ„ ์™„๋ฃŒ ์ฆ‰์‹œ TodoWrite ํ˜ธ์ถœ
// ์˜ˆ: Step 2 ์™„๋ฃŒ ํ›„
TodoWrite([
  { content:  " Step 1: ์ด์Šˆ ์ •๋ณด ์กฐํšŒ " , status:  " completed " , activeForm:  " ์ด์Šˆ ์กฐํšŒ ์™„๋ฃŒ "   },
  { content:  " Step 2: ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ " , status:  " completed " , activeForm:  " ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ ์™„๋ฃŒ "   },
  { content:  " Step 3: BDD ์‹œ๋‚˜๋ฆฌ์˜ค " , status:  " in_progress " , activeForm:  " BDD ์ž‘์„ฑ ์ค‘ "   },
  // ... ๋‚˜๋จธ์ง€ pending ์œ ์ง€
]);

State Tracking Rules#

RuleDescription
Only 1 in_progressOnly 1 in_progress state allowed at a time
Immediate update Change to completed immediately on step completion
Skip markingAdd "(skip)" to content for N/A steps (BDD, etc.)
Keep on failure Keep failed step as in_progress, output error message

  • issue-branch-agent: Branch creation
  • bdd-scenario-agent: BDD scenario generation (for screen features)
  • implementation-agent: Code implementation
  • test-runner-agent: Test execution (including BDD)
  • pr-lifecycle-agent: PR management
  • issue-state-agent: Issue state management
  • /dev:run: Start full cycle with work content
  • /dev:bugfix: Bug fix dedicated cycle
  • /dev:parallel: Parallel processing of multiple issues
  • /dev:sprint: Full Epic orchestration
  • /code-review: Run code review
  • /checklist:feature-complete: Completion checklist
  • /bdd:generate: BDD scenario generation