| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Invoke | /dev:issue |
/dev:issue โ ์ด์ ํ๋, ๋๊น์ง ์๋ ์ฒ๋ฆฌ#
ํ๋ง๋๋ก#
์ด์ ๋ฒํธ ํ๋๋ง ์๋ ค์ฃผ๋ฉด ๋ธ๋์น ๋ง๋ค๊ธฐ โ ์ฝ๋ ๊ตฌํ โ ํ ์คํธ โ PR ์์ฑ โ ์ฝ๋ ๋ฆฌ๋ทฐ โ ๋จธ์ง(์๋ฃ ์ฒ๋ฆฌ) ๊น์ง์ ๊ฐ๋ฐ ๊ณผ์ ์ ์๋์ผ๋ก ์งํํด ์ฃผ๋ ๋ช ๋ น์ ๋๋ค. ๊ณต์ฅ์ ์ปจ๋ฒ ์ด์ด ๋ฒจํธ์ฒ๋ผ, ์์ฌ๋ฃ(์ด์) ํ๋๋ฅผ ์ฌ๋ ค๋์ผ๋ฉด ์์ฑํ(๋จธ์ง๋ ์ฝ๋)์ด ๋์ค๋ ์์ด์์. ๋จ, ๋ง์ง๋ง "์ต์ข ํฉ์น๊ธฐ"๋ ์ฌ๋์ด ์ง์ ์น์ธ ๋ฒํผ์ ๋๋ฌ์ผ ์งํ๋ฉ๋๋ค.
๋๊ฐยท์ธ์ ์ฐ๋์#
- ์ ํด์ง ์ด์(์์ ํญ๋ชฉ) ํ๋๋ฅผ ์ฒ์๋ถํฐ ๋๊น์ง ํ ๋ฒ์ ์ฒ๋ฆฌํ๊ณ ์ถ์ ๊ฐ๋ฐ์
- "25๋ฒ ์ด์ ์์ ํด์ค"์ฒ๋ผ ๋จ์ผ ์์ ๋จ์๋ฅผ ๋งก๊ธฐ๊ณ ์ถ์ ๋
- ๊ธํ ํซํฝ์ค๋ฅผ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํด์ผ ํ ๋ (ํ ์คํธ๋ ๋ฆฌ๋ทฐ๋ฅผ ๊ฑด๋๋ฐ๋ ์ต์ ์ ๊ณต)
์ฌ๋ฌ ์ด์๋ฅผ ํ๊บผ๋ฒ์ ๋๋ฆฌ๊ฑฐ๋, ์์
๋ด์ฉ์ ์๋ก ์ ํด์ ์์ํ๋ ๊ฒฝ์ฐ๋ /dev:runยท/dev:batch ๊ฐ์ ๋ค๋ฅธ ๋ช
๋ น์ ์๋๋ค.
๋ฌด์์ ํด์ฃผ๋์#
- ์ด์ ์ ์ฉ ์์
๋ธ๋์น(
feature/{๋ฒํธ}-{์ค๋ช })๋ฅผ ๋ง๋ค๊ณ , ZenHub ์ํ๋ฅผ "In Progress"๋ก ์ฎ๊น๋๋ค. - ํ๋ฉด ๊ด๋ จ ์ด์๋ฉด BDD ์๋๋ฆฌ์ค(๋์ ๋ช ์ธ์)๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
- ์ด์ ๋ด์ฉ์ ๋ถ์ํด ์ฝ๋๋ฅผ ๊ตฌํํ๊ณ , ์์ ๋จ์๋ง๋ค ์ปค๋ฐ์ ๋จ๊น๋๋ค.
- ํ๋ฉด ๊ธฐ๋ฅ์ด๋ฉด ์๋ฎฌ๋ ์ดํฐยท์ค๊ธฐ๊ธฐ์ ์ฑ์ ๋์ Figma ์์๊ณผ ์ฌ์ง์ผ๋ก ๋์กฐํฉ๋๋ค. ๋ค๋ฅด๋ฉด ๋๊ฐ์์ง ๋๊น์ง ์ฝ๋๋ฅผ ์๋์ผ๋ก ๊ณ ์น๊ณ , ๋๊ตฌ/๊ธฐ๊ธฐ๊ฐ ์๊ฑฐ๋ ๊ทธ๋๋ ์ ๋ง์ผ๋ฉด ์ฌ๋์๊ฒ ํ์ธ์ ์์ฒญํฉ๋๋ค.
- ํ ์คํธ๋ฅผ ์์ฑยท์คํํฉ๋๋ค. ์ด ๊ด๋ฌธ์ ํต๊ณผํ์ง ๋ชปํ๋ฉด PR์ ๋ง๋ค์ง ์์ต๋๋ค(ํ์ง ์์ ์ฅ์น).
- PR(๋ณํฉ ์์ฒญ) ์ ๋ง๋ค๊ณ , ๋ณธ๋ฌธ์
Closes #์ด์๋ฒํธ๋ฅผ ๋ฃ์ด ์ด์์ ์๋์ผ๋ก ์ฐ๊ฒฐํฉ๋๋ค. - ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ์๋ ์คํํ๊ณ , ํฌ๋งทยท๋ฆฐํธ ๊ฐ์ ๊ธฐ๊ณ์ ์ผ๋ก ๊ณ ์น ์ ์๋ ๋ถ๋ถ์ ์๋ ๋ฐ์ํฉ๋๋ค.
-
๋ง์ง๋ง์ ์ฌ๋์ ์น์ธ์ ๋ฐ์ ๋จธ์งํ๊ณ , ์ด์๋ฅผ ๋ซ์ต๋๋ค(GitHub์ ZenHub ์์ชฝ ๋ชจ๋ ํ์ ). ๋จ, ๊ณ์ธต ์์
์ด๋ผ ๋ถ๋ชจ ์์
๋ฒ ์ด์ค ๋ธ๋์น(
story/ยทepic/)๋ก ํฉ์น๋ ๊ฒฝ์ฐ GitHub ์๋ ๋ซํ์ด ๋์ํ์ง ์์ผ๋ฏ๋ก ์ง์ ๋ซ๋ ๊ฒ์ด ๊ธฐ๋ณธ์ ๋๋ค.
์ด๋ป๊ฒ ์ฐ๋์#
# ๊ธฐ๋ณธ: 25๋ฒ ์ด์๋ฅผ ์ฒ์๋ถํฐ ๋๊น์ง ์ฒ๋ฆฌ
/dev:issue 25
# ๋จธ์ง๋ ํ์ง ์๊ณ PR๊น์ง๋ง
/dev:issue 25 --no-merge
# ํ
์คํธ ๊ฑด๋๋ฐ๊ธฐ (๊ธํ ํซํฝ์ค์ฉ)
/dev:issue 25 --skip-tests
# base(๊ธฐ์ค) ๋ธ๋์น ๋ณ๊ฒฝ
/dev:issue 25 --base main
# BDD ์๋๋ฆฌ์ค ๊ฐ์ ์์ฑ
/dev:issue 25 --bdd
# BDD ์๋๋ฆฌ์ค ๊ฑด๋๋ฐ๊ธฐ
/dev:issue 25 --skip-bdd
# ์ฝ๋ ๋ฆฌ๋ทฐ ๊ฑด๋๋ฐ๊ธฐ (๊ธํ ํซํฝ์ค์ฉ)
/dev:issue 25 --skip-review
# ํ๋ฉด ๋์์ธ ๊ฒ์ฆ ๊ฑด๋๋ฐ๊ธฐ (์ฌ์ ํ ํ์ธ ์ ์ฐจ ํ์)
/dev:issue 25 --skip-design-verify
{issue_number}(์ด์ ๋ฒํธ)๋ ๋ฐ๋์ ๋ฃ์ด์ผ ํ๋ ๊ฐ์
๋๋ค. ๋๋จธ์ง -- ์ต์
์ ์ํฉ์ ๋ฐ๋ผ ์ ํํด์ ๋ถ์ด๋ฉด ๋ฉ๋๋ค.
์์์ ๋ฌด์จ ์ผ์ด ๋ฒ์ด์ง๋์#
์ด 9๋จ๊ณ๋ก, ์ ๋จ๊ณ๊ฐ ์ฑ๊ณตํด์ผ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋๋ค.
- ์ด์ ์ ๋ณด ์กฐํ โ ์ด์์ ์ ๋ชฉยท๋ด์ฉยทํ์ ์ ์ฝ๊ณ , ํ๋ฉด ์ข ๋ฅ(๋ชฉ๋ก/์์ธ/ํผ)์ธ์ง ์๋์ผ๋ก ํ๋ณํฉ๋๋ค.
- ๋ธ๋์น ์์ฑ โ ์ด์ ์ ์ฉ ์์ ๊ณต๊ฐ(๋ธ๋์น)์ ๋ง๋ค๊ณ ์ํ๋ฅผ "In Progress"๋ก ์ฎ๊น๋๋ค.
- BDD ์๋๋ฆฌ์ค ์์ฑ โ ํ๋ฉด ๊ธฐ๋ฅ์ด๋ฉด ๋์ ๋ช ์ธ์๋ฅผ ๋ง๋ค์ด ์ปค๋ฐํฉ๋๋ค(์๋๋ฉด ๊ฑด๋๋).
- ๊ตฌํ ์์ โ ์ด์ ๋ด์ฉ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋จ๊ณ๋ณ๋ก ์ปค๋ฐํฉ๋๋ค.
- ํ๋ฉด ์ค๊ธฐ๊ธฐ ๋์กฐ ํ์ธ โ ํ๋ฉด ๊ธฐ๋ฅ์ด๋ฉด ์๋ฎฌ๋ ์ดํฐยท์ค๊ธฐ๊ธฐ์ ์ฑ์ ๋์ Figma ์์๊ณผ ์ฌ์ง์ผ๋ก ๋น๊ตํฉ๋๋ค. ๋ค๋ฅด๋ฉด ๋๊ฐ์์ง ๋๊น์ง ์ฝ๋๋ฅผ ์๋์ผ๋ก ๊ณ ์น๊ณ , ๋๊ตฌ/๊ธฐ๊ธฐ๊ฐ ์๊ฑฐ๋ ๊ทธ๋๋ ์ ๋ง์ผ๋ฉด ์ฌ๋์๊ฒ ํ์ธ์ ์์ฒญํฉ๋๋ค.
- ํ ์คํธ ์์ฑยท๊ฒ์ฆ (ํ์ ๊ด๋ฌธ) โ ๋จ์ยทBDDยท๋ฐฑ์๋ ํ ์คํธ๋ฅผ ๋๋ฆฝ๋๋ค. ์ ๋ถ ํต๊ณผํด์ผ๋ง ๋ค์์ผ๋ก ์งํ๋๋ฉฐ, ์คํจํ๋ฉด ์ต๋ 3๋ฒ๊น์ง ์๋ ์์ ์ ์๋ํฉ๋๋ค.
- PR ์์ฑ โ ๋ณํฉ ์์ฒญ์ ๋ง๋ค๊ณ ์ด์์ ์ฐ๊ฒฐํ ๋ค, ์ํ๋ฅผ "Review/QA"๋ก ์ฎ๊น๋๋ค.
- ์ฝ๋ ๋ฆฌ๋ทฐ โ ์๋ ๋ฆฌ๋ทฐ๋ฅผ ๋๋ฆฌ๊ณ ํฌ๋งทยท๋ฆฐํธ ๋ฑ ๊ณ ์น ์ ์๋ ๋ถ๋ถ์ ๋ฐ์ํ ๋ค, ์๋ฃ ์ฒดํฌ๋ฆฌ์คํธ๋ฅผ ์คํํฉ๋๋ค.
- ๋จธ์ง ์น์ธ ๋๊ธฐ โ ์ต์ข ์์ฝ์ ๋ณด์ฌ์ฃผ๊ณ ์ฌ๋์ ์น์ธ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ์น์ธํ๋ฉด ํฉ์ณ์ง๊ณ ์ด์๊ฐ ์๋์ผ๋ก ๋ซํ๋๋ค.
โ๏ธ ์์ธ ์ต์ ยท์คํ ๋ช ์ธ (๊ฐ๋ฐ์ / AI ์์ด์ ํธ์ฉ)
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)
/dev:issue 25 --skip-design-verify # Skip design verification (still requires AskUserQuestion confirmation)
/dev:issue 25 --design-target=android --design-tolerance pixel=1,color_delta_e=2Execution 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 4.5: ๋์์ธ ๊ฒ์ฆ ๊ฒ์ดํธ (screen feature + Figma ์์ค ์) โ ๏ธ โ
โ โโโ ์์ธ ๋ก์ง์ run.md Step 7.3๊ณผ ๋์ผ โ ์ฌ๊ธฐ์๋ ์์๋ง ํจ โ
โ โโโ flutter run --print-dtd โ pixel-loop:loop โ visual-verify โ
โ โโโ ๋๊ตฌ/๊ธฐ๊ธฐ ๋ถ์ฌยท์์กด ๋ถ์ผ์น ์ AskUserQuestion ํ์ธ (๋ฌด์ ์คํต ๊ธ์ง)โ
โ โโโ ๊ฒฐ๊ณผ๋ฅผ PR body์ " Design Verification " ์น์
์ ๊ธฐ๋ก โ
โ โ
โ 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: ๋จธ์ง ์น์ธ ๋๊ธฐ (๋จธ์ง = Close) โ
โ โโโ ์ต์ข
์ํ ์์ฝ ํ์ โ
โ โโโ ์ฌ์ฉ์ ์น์ธ ์์ฒญ (AskUserQuestion) โ
โ โโโ ์น์ธ ์ ์ค์ฟผ์ ๋จธ์ง ์คํ โ
โ โโโ GitHub " Closes # " ํค์๋๋ก ์ด์ ์๋ Close โ
โ โโโ โญ Close ๊ฒ์ฆ + ํด๋ฐฑ (GitHub closed + ZenHub Closed ํ์ ) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ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#
์ด์๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ค๊ณ ์ ์ ํ๋ฏ๋ก
/dev:run์ Step 1.5(PM ์๊ตฌ์ฌํญ ์ ์ ,pm-spec-agent)๋ ์ฌ๊ธฐ์ ์คํ๋์ง ์๋๋ค. ์กฐํํissue.body๊ฐ FR/AC๋ ์ค์ฝํ ์์ด ํ ์ค๋ฟ์ด๋ฉด, ๋ธ๋์น ์์ฑ(Step 2) ์ ์pm-spec-agent๋ฅผ ์ง์ ํธ์ถํด ์ด์ ๋ณธ๋ฌธ์ ๋ณด๊ฐํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค โ ํ์ ๊ฒ์ดํธ๋ ์๋๋ค(non-blocking). ์์ธํ ๋ด์ฉ์ SKILL.md โ "PM Requirements Refinement Gate" ์ฐธ๊ณ .
// ์ด์ ์ ๋ณด ์กฐํ
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 "
`
});
// ์คํ๋ฆฐํธ ๋ฐฐ์ (ํ์๋ผ์ธ ๊ฐ์์ฑ) โ ๊ธฐ๋ณธ on, --no-sprint opt-out.
// ์
๋ ํฐ: rules/zenhub-conventions.md โ " Sprint Selector Resolution " .
if (!options.noSprint) {
const sprint = options.sprint === " next "
? await mcp__zenhub__getUpcomingSprint()
: await mcp__zenhub__getSprint(); // id ์์ = ํ์ฑ
if (sprint?.id) await mcp__zenhub__addIssuesToSprints({ issueIds: [issueInfo.id], sprintIds: [sprint.id] });
}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 4.5: Design Verification Gate (screen features) โ ๏ธ#
Screen feature(issueInfo์์ ํ๋ฉด ์ข
๋ฅ๊ฐ ๊ฐ์ง๋จ) + Figma ์์ค(.claude/docs/{scope}/figma_analysis.md)๊ฐ ์์ ๋๋ง ์คํ. ์ ์ฒด ๋ก์ง(๋๊ตฌ/๊ธฐ๊ธฐ preflight, flutter run --print-dtd ๊ธฐ๋, pixel-loop:loop ์ ์, visual-verify ๊ฒ์ดํธ, ์คํจ ์ ์ฌ์๋/์ฌ์ฉ์ ํ์ธ, prBodyExtras.designVerification ๊ธฐ๋ก)์ run.md โ Step 7.3: Design Verification Gate๋ฅผ ๊ทธ๋๋ก ์ฌ์ฌ์ฉํ๋ค โ ์ฌ๊ธฐ์ ์ค๋ณต ๊ธฐ์ ํ์ง ์๋๋ค.
- Figma ์์ค๊ฐ ์์ผ๋ฉด not-applicable๋ก ์กฐ์ฉํ skip.
- ๋๊ตฌ/๊ธฐ๊ธฐ(figma-mcp/maestro/dart-mcp/device) ๋ถ์ฌ ๋๋
--skip-design-verify์์๋AskUserQuestionํ์ธ์ ์๋ตํ์ง ์๋๋ค(๋ฌด์ ์คํต ๊ธ์ง). - ๊ฒฐ๊ณผ๋ Step 6 PR ๋ณธ๋ฌธ์ "Design Verification" ์น์ ์ ๋ฐ์๋๋ค.
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 ์๋๋ฆฌ์ค ํต๊ณผ ' : ' ' }
${designVerification ? `
## Design Verification
${designVerification.status === " pass " ? `โ
PASS โ tolerance ${designVerification.tolerance}, target ${designVerification.target}` : ' ' }
${designVerification.status === " skipped " ? `โ ๏ธ ๋์์ธ ๊ฒ์ฆ ๋ฏธ์คํ (${designVerification.reason}) โ ๋์์ด๋ ์๋ ํ์ธ ํ์` : ' ' }
${designVerification.status === " fail-acknowledged " ? `โ ๏ธ ์์กด ๋ถ์ผ์น ${designVerification.diffCount}๊ฑด โ ์ฌ์ฉ์ ํ์ธ ํ ์งํ` : ' ' }
` : ' ' }
Closes #${issueInfo.number}
๐ค Generated with [Claude Code](https://claude.com/claude-code)
EOF
) "
`);
// Pipeline ์ด๋: Review/QA (fail-closed id ํด์ โ undefined silent no-op ๋ฐฉ์ง)
const _ws = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const reviewQa = _ws.pipelines.find(p = > p.name === " Review/QA " );
if (!reviewQa) throw new Error(` ' Review/QA ' ํ์ดํ๋ผ์ธ ์์. ๋ผ์ด๋ธ: ${_ws.pipelines.map(p = > p.name).join( " , " )}`);
await mcp__zenhub__moveIssueToPipeline({ issueId: issueInfo.id, pipelineId: reviewQa.id });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 > "
`);
// โ ๏ธ Per-Push Verification Gate: PR์ด ์ด๋ฏธ ์กด์ฌํด๋ push ์ง์ ์
// Step 5.5 ๊ฒ์ดํธ๋ฅผ ๊ทธ๋๋ก ์ฌ์คํํ๋ค (0๊ฑด ๋ฏธ๋ฌ ์ push ์ฐจ๋จ)
await Bash(`melos run format`); // dcm format
await Bash(`dart fix --apply`);
const recheck = await Bash(`melos run analyze 2 > & 1`);
if (countLintIssues(recheck) > 0) {
throw new Error( " Per-Push Gate blocked: dart analyze ์ด์ ์์กด โ ์์ ํ ์ฌ์๋ " );
}
const dcmRecheck = await Bash(`melos run dcm:analyze 2 > & 1`);
if (countDcmErrors(dcmRecheck) > 0) {
throw new Error( " Per-Push Gate blocked: dcm analyze error ์ด์ ์์กด โ ์์ ํ ์ฌ์๋ " );
}
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 (์ ์ฑ
: ๋จธ์ง = Close)
// Done ํ์ดํ๋ผ์ธ ๋ฏธ์ฌ์ฉ (Done โ closed)
await Bash(`gh pr merge --squash --delete-branch`);
// โญ Close ๊ฒ์ฆ + ํด๋ฐฑ (ZenHub 2-์ํ ๋ชจ๋ธ: Pipeline โ GitHub state)
// `Closes #N` ์๋ close๊ฐ ๋๋ฝ/์ง์ฐ๋ ์ ์์ผ๋ฏ๋ก GitHub state๋ก ๊ฒ์ฆํ๋ค.
const ghState = (await Bash(`gh issue view ${issueInfo.number} --json state -q .state`)).trim();
if (ghState !== " CLOSED " ) {
await Bash(`gh issue close ${issueInfo.number} --reason completed`);
}
const closedOnZh = await mcp__zenhub__searchClosedIssues({ query: `#${issueInfo.number}` });
if (!closedOnZh.find(i = > i.number === issueInfo.number)) {
await mcp__zenhub__updateIssue({ issueId: issueInfo.id, state: " CLOSED " });
}
// โญ Post-merge: base ๋ธ๋์น๋ก ์ด๋ + ์ต์ ํ + ์๋ธ๋ชจ๋ ๋๊ธฐํ (ํ์)
// - gh pr merge --delete-branch ๋ base๋ฅผ ์ฒดํฌ์์ํ์ง๋ง pull ํ์ง ์๋๋ค.
// - git pull ์ superproject์ ์๋ธ๋ชจ๋ ํฌ์ธํฐ๋ง ๊ฐฑ์ ํ ๋ฟ ์๋ธ๋ชจ๋ ์ํนํธ๋ฆฌ๋
// ์ฒดํฌ์์ํ์ง ์์ผ๋ฏ๋ก git submodule update ๋ก base๊ฐ ๊ฐ๋ฆฌํค๋ ์ปค๋ฐ์ ์ ๋ ฌํ๋ค
// (Serverpod/Melos ๋ชจ๋
ธ๋ ํฌ ๋น๋/์ฝ๋์ drift ๋ฐฉ์ง). ์๋ธ๋ชจ๋์ด ์์ผ๋ฉด no-op.
// - baseBranch = PR base (๊ณ์ธต: ๋ถ๋ชจ ๋ธ๋์น, ๋
๋ฆฝ: development).
const baseBranch = branchResult.base_branch ?? " development " ;
await Bash(`
git checkout ${baseBranch}
git pull --ff-only origin ${baseBranch}
git submodule sync --recursive
git submodule update --init --recursive
`);
}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 Step | State | Recovery Method |
|---|---|---|
| Branch creation | No changes | Retry |
| Implementation | Branch exists, some commits | Continue work |
| Design verification (Step 4.5) | Code complete | ๋๊ตฌ/๊ธฐ๊ธฐ ํ์ธ ํ ์ฌ์คํ, ๋๋ --skip-design-verify(ํ์ธ ํ์) โ ์์ธํ ๋ด์ฉ์ run.md Step 7.3 ์ฐธ๊ณ |
| 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๊ฐ ๋ธ๋์น๋ฅผ ์์ฑํ๋ฏ๋ก ๊ณ์ ์งํ
fiPre-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
# 3.5. ๋์์ธ ๊ฒ์ฆ ๊ฒฐ๊ณผ ๊ธฐ๋ก ํ์ธ (screen feature + Figma ์์ค ์ โ Step 4.5 ๊ฒ์ดํธ)
# ๋ฏธ๊ฒ์ฆ ์ํ๋ฅผ pass ๋ก ๊ฐ์ฃผํ์ง ์๋๋ค โ ๋น์ด ์์ผ๋ฉด ์ฐจ๋จ
if [[ " $REQUIRES_BDD " == " true " & & -f " .claude/docs/${SCOPE}/figma_analysis.md " & & -z " $DESIGN_VERIFICATION_STATUS " ]]; then
echo " โ Step 4.5 ๋์์ธ ๊ฒ์ฆ ๊ฒฐ๊ณผ๊ฐ ๊ธฐ๋ก๋์ง ์์์ต๋๋ค โ PR ์์ฑ ์ฐจ๋จ "
exit 1
fi
# 4. Pre-push ๊ฒ์ฆ + ๋ฆฐํธ 0๊ฑด ๊ฒ์ดํธ
# (Per-Push Gate: ์ต์ด push๋ฟ ์๋๋ผ ๋ฆฌ๋ทฐ ํผ๋๋ฐฑ ๋ฑ ์ดํ ๋ชจ๋ push ์ง์ ์ ์ฌ์คํ)
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 4.5: ๋์์ธ ๊ฒ์ฆ ๊ฒ์ดํธ (screen feature ์) " , status: " pending " , activeForm: " ๋์์ธ ๊ฒ์ฆ ๋๊ธฐ " },
{ content: " Step 5: ํ
์คํธ ์คํ " , status: " pending " , activeForm: " ํ
์คํธ ๋๊ธฐ " },
{ content: " Step 5.5: Pre-push ๊ฒ์ฆ + ๋ฆฐํธ 0๊ฑด ๊ฒ์ดํธ (์ดํ ๋ชจ๋ push๋ง๋ค ์ฌ์คํ) " , 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#
| 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 |
Related Agents#
issue-branch-agent: Branch creationbdd-scenario-agent: BDD scenario generation (for screen features)implementation-agent: Code implementationtest-runner-agent: Test execution (including BDD)pr-lifecycle-agent: PR managementissue-state-agent: Issue state management
Related Skills#
/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