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#
| Parameter | Required | Description |
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:
| Pattern | Screen Type | BDD |
| "๋ชฉ๋ก", "๋ฆฌ์คํธ", "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`);
}
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 Step | State | Recovery Method |
| Branch creation | No changes | Retry |
| Implementation | Branch exists, some commits | Continue work |
| Tests | Code complete, tests failed | Manual fix then retry |
| PR creation | Code complete | Create PR manually or retry |
| Merge | PR exists, CI pending | Wait for CI pass then retry |
| Issue close | PR merged | Manual 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#
- Sequential execution: Each step proceeds only after previous step succeeds
- State tracking: Record current state at every step
-
Failure tolerance: Preserve current state on failure and provide clear recovery guide
- Issue linking: Reference issue number in all commits and PRs
- Auto cleanup: Auto-delete branch on success (after merge)
- 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: " ๋จธ์ง ๋๊ธฐ " },
]);
// ๊ฐ ๋จ๊ณ ์๋ฃ ์ฆ์ 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#
| Rule | Description |
| Only 1 in_progress | Only 1 in_progress state allowed at a time |
| Immediate update |
Change to completed immediately on step completion |
| Skip marking | Add "(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