LogoSkills

dev:batch

ZenHub issue sequential processing automation (hierarchical branch strategy)

ํ•ญ๋ชฉ๋‚ด์šฉ
Invoke/dev:batch
Categorykobic-workflow
MCP Serverszenhub, sequential

/dev:batch โ€” Epic ํ•œ ๋ฐฉ์— ์ž๋™ ์ฒ˜๋ฆฌ#

ํ•œ๋งˆ๋””๋กœ#

Epic(ํฐ ์ž‘์—… ๋ฌถ์Œ) ํ•˜๋‚˜๋ฅผ ๋˜์ ธ์ฃผ๋ฉด, ๊ทธ ์•„๋ž˜์— ๋งค๋‹ฌ๋ฆฐ StoryยทSub-task๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์ž๋™์œผ๋กœ ๊ฐœ๋ฐœยท๊ฒ€ํ† ยท๋ณ‘ํ•ฉํ•ด ์ฃผ๋Š” ์ž๋™ํ™” ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ํฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์ž‘์€ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ  ํ•œ ์กฐ๊ฐ์”ฉ ๋๋‚ด๊ณ , ๋งˆ์ง€๋ง‰์— ์ „์ฒด๋ฅผ ํ•œ ๋ฉ์–ด๋ฆฌ๋กœ ํ•ฉ์ณ ๋ณด๊ณ ํ•˜๋Š” "์กฐ๋ฆฝ ๋ผ์ธ"์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ยท์–ธ์ œ ์“ฐ๋‚˜์š”#

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•˜์œ„ ์ž‘์—…(Story, Sub-task)์ด ๋”ธ๋ฆฐ Epic ํ•˜๋‚˜๋ฅผ ํ†ต์งธ๋กœ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  • ์ž‘์—… ํ•˜๋‚˜ํ•˜๋‚˜ ์ง์ ‘ ๋ธŒ๋žœ์น˜๋ฅผ ๋งŒ๋“ค๊ณ  PR์„ ์˜ฌ๋ฆฌ๊ณ  ๋ณ‘ํ•ฉํ•˜๋Š” ๋ฐ˜๋ณต ์ž‘์—…์„ ์‚ฌ๋žŒ์ด ์ผ์ผ์ด ์ฑ™๊ธฐ์ง€ ์•Š๊ณ  ์ž๋™์œผ๋กœ ๋Œ๋ฆฌ๊ณ  ์‹ถ์„ ๋•Œ
  • ๋งˆ์ง€๋ง‰์— ์‚ฌ๋žŒ์ด ํ•œ ๋ฒˆ๋งŒ ์ตœ์ข… ์Šน์ธํ•˜๋ฉด ๋˜๋Š”, ์†์ด ๋œ ๊ฐ€๋Š” ์ผ๊ด„ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์›ํ•  ๋•Œ

๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”#

  • Epic ์ „์šฉ ์ž‘์—… ๊ณต๊ฐ„(epic/{๋ฒˆํ˜ธ}-{์ด๋ฆ„} ๋ธŒ๋žœ์น˜)์„ ๋จผ์ € ๋งŒ๋“ค๊ณ , ๊ทธ ์•ˆ์—์„œ Story๋“ค์„ ์ฐจ๋ก€๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ StoryยทSub-task๋งˆ๋‹ค ๊ฐœ๋ฐœ โ†’ ํ…Œ์ŠคํŠธ โ†’ ๊ฒ€ํ† (Code Review) โ†’ PR ์ƒ์„ฑ โ†’ ๋ณ‘ํ•ฉ์„ ์ž๋™์œผ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ‘ํ•ฉ์ด ๋๋‚˜๋ฉด ํ•ด๋‹น ZenHub ์ด์Šˆ๋ฅผ ์ž๋™์œผ๋กœ "์™„๋ฃŒ(Close)" ์ฒ˜๋ฆฌํ•˜๊ณ , ์ œ๋Œ€๋กœ ๋‹ซํ˜”๋Š”์ง€๊นŒ์ง€ ๋‹ค์‹œ ํ™•์ธ(๊ฒ€์ฆ)ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  Story๊ฐ€ ๋๋‚˜๋ฉด Epic ์ „์ฒด๋ฅผ ๋ฌถ์€ ์ตœ์ข… PR์„ ๋งŒ๋“ค์–ด development(๊ฐœ๋ฐœ ํ†ตํ•ฉ ๋ธŒ๋žœ์น˜)๋กœ ํ•ฉ์น  ์ค€๋น„๋ฅผ ๋งˆ์นฉ๋‹ˆ๋‹ค. ์ด ๋งˆ์ง€๋ง‰ ๋ณ‘ํ•ฉ๋งŒ ์‚ฌ๋žŒ์˜ ์Šน์ธ์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์“ฐ๋‚˜์š”#

/dev:batch {epic_number}
# ์˜ˆ: 1234๋ฒˆ Epic์„ ํ†ต์งธ๋กœ ์ฒ˜๋ฆฌ
/dev:batch 1234
  • {epic_number} ์ž๋ฆฌ์—๋Š” ์ฒ˜๋ฆฌํ•  Epic์˜ ์ด์Šˆ ๋ฒˆํ˜ธ๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ ๋’ค๋กœ๋Š” ๋ช…๋ น์ด ์•Œ์•„์„œ Epic ์•„๋ž˜์˜ StoryยทSub-task๋ฅผ ์ฐพ์•„ ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ, ์ถ”๊ฐ€๋กœ ์ž…๋ ฅํ•  ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

์•ˆ์—์„œ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”#

์ „์ฒด ํ๋ฆ„์€ ํฌ๊ฒŒ ์„ธ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

  1. (์„ ํƒ) ๊ธฐํš ๋ช…์„ธ ์ •๋ ฌ ์ ๊ฒ€ โ€” docs/seed-spec-*.md(ํ™•์ •/LOCKED) ๊ฐ€ ์žˆ์œผ๋ฉด, ๋ฐฐ์น˜๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „๊ณผ ๋งˆ์ง€๋ง‰ ๋ณ‘ํ•ฉ ์งํ›„์— "์ง€๊ธˆ ์ฒ˜๋ฆฌํ•˜๋ ค๋Š”(๋˜๋Š” ๋๋‚ธ) ์ž‘์—… ๋ฌถ์Œ์ด ์›๋ž˜ ๊ธฐํš ๋ชฉํ‘œยทํ•ฉ๊ฒฉ ๊ธฐ์ค€๊ณผ ๊ฐ™์€ ๋ฐฉํ–ฅ์ธ๊ฐ€"๋ฅผ ์˜๋ฏธ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋ฒˆ์”ฉ ๋Œ€์กฐํ•ฉ๋‹ˆ๋‹ค(์ฝ๊ธฐ ์ „์šฉ, /spec:status ์žฌ์‚ฌ์šฉ). ๋ฐฉํ–ฅ์ด ํฌ๊ฒŒ ์–ด๊ธ‹๋‚˜๋ฉด(MAJOR-DRIFT) ๊ฒฝ๊ณ ๋ฅผ ๋„์šฐ๊ณ  "๊ทธ๋ž˜๋„ ๊ณ„์†ํ• ๊นŒ์š”?"๋ฅผ ๋ฌผ์–ด ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. ํ™•์ •๋œ ๊ธฐํš ๋ช…์„ธ๊ฐ€ ์—†์œผ๋ฉด ์ด ์ ๊ฒ€์€ ์กฐ์šฉํžˆ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค(์„œ๋ธŒ๋ชจ๋“ˆ ์—†์„ ๋•Œ์ฒ˜๋Ÿผ ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•จ โ€” ๊ธฐํš ์—†์ด๋„ ์ •์ƒ ์ง„ํ–‰).
  2. Epic ์ž‘์—… ๊ณต๊ฐ„ ๋งŒ๋“ค๊ธฐ (Phase 1) โ€” Epic ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๊ณ , ์ตœ์‹  ์ƒํƒœ์˜ development์—์„œ Epic ์ „์šฉ ๋ธŒ๋žœ์น˜๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. Epic์„ "์ง„ํ–‰ ์ค‘(In Progress)"์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  3. Story ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๊ธฐ (Phase 2) โ€” Story๋งˆ๋‹ค ๊ฐœ๋ฐœยทํ…Œ์ŠคํŠธยท๊ฒ€ํ† ยทPRยท๋ณ‘ํ•ฉ์„ ์ฐจ๋ก€๋กœ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. Story ์•„๋ž˜์— Sub-task๊ฐ€ ๋˜ ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ๋“ค๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋จผ์ € ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋ณ‘ํ•ฉ ํ›„์—๋Š” ์ด์Šˆ๋ฅผ ์ž๋™์œผ๋กœ ๋‹ซ๊ณ , ๋‹ซํ˜”๋Š”์ง€ ๊ฒ€์ฆํ•œ ๋’ค, ์ž‘์—… ๊ธฐ์ค€ ๋ธŒ๋žœ์น˜๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ๋งž์ถฅ๋‹ˆ๋‹ค.
  4. Epic ๋งˆ๋ฌด๋ฆฌ (Phase 3) โ€” ๋ชจ๋“  Story๊ฐ€ ํ•ฉ์ณ์กŒ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , Epic ์ „์ฒด๋ฅผ ๋ฌถ์€ ์ตœ์ข… PR์„ development๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ์˜ ์ตœ์ข… ์Šน์ธ์„ ๋ฐ›์€ ๋’ค ๋ณ‘ํ•ฉํ•˜๋ฉด Epic ์ด์Šˆ๊ฐ€ ์ž๋™์œผ๋กœ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

โš™๏ธ ์ƒ์„ธ ์˜ต์…˜ยท์‹คํ–‰ ๋ช…์„ธ (๊ฐœ๋ฐœ์ž / AI ์—์ด์ „ํŠธ์šฉ)

Usage#

/dev:batch {epic_number}

Hierarchical Branch Strategy#

development
 โ””โ”€โ”€ epic/{epic_number}-{slug}            โ† Created in Phase 1
      โ”œโ”€โ”€ story/{story_1}-{slug}          โ† Sequentially processed in Phase 2
      โ”‚    โ”œโ”€โ”€ task/{subtask_1}-{slug}    โ† Sub-tasks processed sequentially within Story
      โ”‚    โ””โ”€โ”€ task/{subtask_2}-{slug}
      โ”œโ”€โ”€ story/{story_2}-{slug}
      โ””โ”€โ”€ story/{story_3}-{slug}
                                           โ† Epic โ†’ development PR in Phase 3

Workflow#

Phase 0: Tooling Preflight & Recoverability (GD-02)#

Epic ๋ฃจํ”„๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ํ•œ ๋ฒˆ ํ•„์ˆ˜ ๋„๊ตฌ๋ฅผ ์ ๊ฒ€ํ•˜๊ณ , ์ค‘๋‹จ ์‹œ ์žฌ๊ฐœ ๋ฐฉ๋ฒ•์„ ๋ช…์‹œํ•œ๋‹ค.

1. Tooling preflight (loop ์ง„์ž… ์ „ 1ํšŒ):
   - command -v gh  & &   gh auth status   โ†’ ๋ฏธ์ธ์ฆ์ด๋ฉด ์ฆ‰์‹œ ์ค‘๋‹จ(๋จธ์ง€ ์ „์— ์‹คํŒจ, Epic ์ค‘๊ฐ„ ์•„๋‹˜)
   - command -v melos / dart / flutter  โ†’ ๋ถ€์žฌ ์‹œ /dev:run  " Step 0 Degradation Contract "   ๋ฅผ ๋”ฐ๋ฅธ๋‹ค(์šฐํšŒ + ๊ฒฝ๊ณ )
2. Resume ๊ณ„์•ฝ (๋ฉฑ๋“ฑ):
   - ์ด๋ฏธ Closed ์ธ Story ๋Š” ๊ฑด๋„ˆ๋›ด๋‹ค(Phase 2์—์„œ ์ƒํƒœ ํ™•์ธ).
   - ์ค‘๊ฐ„ ์‹คํŒจ ์‹œ `/dev:batch {epic}` ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ๋งˆ์ง€๋ง‰์œผ๋กœ ๋จธ์ง€๋œ Story ๋‹ค์Œ๋ถ€ํ„ฐ ์ด์–ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.
   - ๋”ฐ๋ผ์„œ ํ•œ Story ์‹คํŒจ๊ฐ€ Epic ์ „์ฒด๋ฅผ  " ์ ˆ๋ฐ˜-๋จธ์ง€ "   ๋กœ ์˜๊ตฌ ๊ณ ์ฐฉ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.

๋ฐฐ๊ฒฝ: ๊ณผ๊ฑฐ batch ๋Š” /dev:run ์˜ ํ•˜๋“œํŽ˜์ผ์„ ๊ทธ๋Œ€๋กœ ์ƒ์†ํ•˜๊ณ  post-merge git/gh/submodule ํ˜ธ์ถœ๋„ ๊ฐ€๋“œ๊ฐ€ ์—†์–ด, ๋„๊ตฌ 1๊ฐœ ๋ถ€์žฌ๋‚˜ ํ•œ Story ์‹คํŒจ๊ฐ€ Epic ์„ ์ค‘๊ฐ„์— ์ขŒ์ดˆ์‹œ์ผฐ๋‹ค(GD-02). ์•„๋ž˜ Phase 2 ์˜ post-merge ๋™๊ธฐํ™” ์‹คํŒจ๋Š” ๊ฒฝ๊ณ  ํ›„ ๊ณ„์†ํ•œ๋‹ค(์ค‘๋‹จ ์•„๋‹˜).

Phase 0.5: Optional Seed-Alignment Checkpoint (D4 โ€” opt-in, no-op on absence)#

Epic ๋ฐฐ์น˜๋Š” ๊ธธ๊ฒŒ ๋„๋Š” ์ž๋™ํ™”๋ผ, ์ž‘์—… ๋ฌถ์Œ์ด ์›๋ž˜ ๊ธฐํš์—์„œ ์กฐ๊ธˆ์”ฉ ํ‘œ๋ฅ˜(drift) ํ•˜๊ธฐ ์‰ฝ๋‹ค. ๊ทธ๋ž˜์„œ docs/seed-spec-*.md ๊ฐ€ ์กด์žฌํ•˜๊ณ  Status: LOCKED ์ผ ๋•Œ์— ํ•œํ•ด, ๋ฐฐ์น˜ ์‹œ์ž‘ ์ง์ „(pre-batch) ๊ณผ Phase 3 ์ตœ์ข… ๋ณ‘ํ•ฉ ์งํ›„(post-batch) ์— ์ •๋ ฌ ์ ๊ฒ€์„ ํ•œ ๋ฒˆ์”ฉ ์‹คํ–‰ํ•œ๋‹ค. ์ด ์ ๊ฒ€์€ /spec:status ํ”„๋กœํ† ์ฝœ์„ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•œ๋‹ค โ€” ์ฝ๊ธฐ ์ „์šฉ(์•„๋ฌด ํŒŒ์ผ๋„ ์“ฐ์ง€ ์•Š์Œ), ์ตœ์‹  LOCKED docs/seed-spec-*.md ๋กœ๋“œ, ์„ ํƒ์  --against {file|dir|PR}.

0.5-1. Seed ํƒ์ง€ (๊ฒŒ์ดํŠธ):
   - SEED=$(ls -1 docs/seed-spec-*.md 2 > /dev/null | tail -1)
   - SEED ๊ฐ€ ์—†์œผ๋ฉด โ†’ **no-op (์กฐ์šฉํžˆ skip)**. ๊ฒฝ๊ณ ๋„ ์ฐจ๋‹จ๋„ ์—†์Œ.
   - SEED ๊ฐ€ ์žˆ์œผ๋‚˜ ๋จธ๋ฆฌ๊ธ€์ด `Status: LOCKED` ๊ฐ€ ์•„๋‹ˆ๋ฉด(DRAFT) โ†’ **no-op + 1์ค„ ์•ˆ๋‚ด**( " ๊ธฐํš ๋ช…์„ธ ๋ฏธํ™•์ • โ†’ ์ •๋ ฌ ์ ๊ฒ€ skip " ). DRAFT ๋ฅผ ๊ฐ•์ œ๋กœ ์ž ๊ทธ์ง€ ์•Š๋Š”๋‹ค.
   - โ†’ ์ฆ‰, ์‹œ๋“œ๊ฐ€ ์—†๊ฑฐ๋‚˜ ๋ฏธํ™•์ •์ธ ์ €์žฅ์†Œ์—์„œ `/dev:batch` ๋Š” **์ ˆ๋Œ€ ํ•˜๋“œํŽ˜์ผํ•˜์ง€ ์•Š๋Š”๋‹ค**(submodule ๋™๊ธฐํ™” no-op ์™€ ๋™์ผํ•œ graceful degradation ํ˜•ํƒœ).

0.5-2. ์ •๋ ฌ ์ ๊ฒ€ (LLM-SEMANTIC, /spec:status ์žฌ์‚ฌ์šฉ):
   - ๋Œ€์กฐ ๋Œ€์ƒ:
     - pre-batch  โ†’ ์ด๋ฒˆ Epic ์•„๋ž˜ **๊ณ„ํš๋œ** StoryยทSub-task ์ด์Šˆ ์ง‘ํ•ฉ(์ œ๋ชฉ/๋ณธ๋ฌธ/AC)
     - post-batch โ†’ Phase 3 ๋ณ‘ํ•ฉ ์งํ›„ **์™„๋ฃŒ(Closed)๋œ** ์ด์Šˆ ์ง‘ํ•ฉ + Epic ๋ธŒ๋žœ์น˜ ๋ˆ„์  ๋ณ€๊ฒฝ(diff/PR)
   - `/spec:status --against {๊ณ„ํš/์™„๋ฃŒ ์ด์Šˆ ์ง‘ํ•ฉ ๋˜๋Š” Epic PR}` ๋ฅผ ์‹คํ–‰ํ•ด LLM-SEMANTIC ์ •๋ ฌ ๋ฆฌํฌํŠธ๋ฅผ ๋ฐ›๋Š”๋‹ค:
     - **AC-ID ์ƒํƒœ echo** โ€” Seed S4(Acceptance Boundaries)์˜ ๊ฐ ํ•ฉ๊ฒฉ ๊ธฐ์ค€์„ `AC-01`, `AC-02` โ€ฆ ๋กœ ์‹๋ณ„ํ•˜๊ณ  PENDING / IN-PROGRESS / MET / FAILED / WAIVED ๋กœ ํ‘œ๊ธฐ.
     - **๋ชฉํ‘œ ์ •๋ ฌ ํŒ์ •** โ€” ์ž‘์—… ๋ฌถ์Œ์˜ ์˜๋„๊ฐ€ Seed S1(Core Problem)๊ณผ ๊ฐ™์€ ๋ฐฉํ–ฅ์ธ์ง€ ALIGNED / MINOR-DRIFT / MAJOR-DRIFT ๋กœ ํŒ์ •.
     - **์ œ์•ฝ ์œ„๋ฐ˜ ํ”Œ๋ž˜๊ทธ** โ€” ์ž‘์—…์ด ์œ„๋ฐ˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด๋Š” Seed S2(Immutable Constraints) ํ•ญ๋ชฉ์„ ๋‚˜์—ด.
   - โš ๏ธ **์˜๋ฏธ ๊ธฐ๋ฐ˜ ํŒ๋‹จ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค(์ ˆ๋Œ€ ์–ดํœ˜/ํ† ํฐ ์ผ์น˜ ์•„๋‹˜)**: Seed ์™€ ์ด์Šˆ/AC ํ…์ŠคํŠธ๋Š” **ํ•œ๊ตญ์–ด ์šฐ์„ **์ด๋ผ ๊ณต๋ฐฑยทํ† ํฐ ๊ฒน์นจ ๋งค์นญ์€ ์กฐ์‚ฌยท๋„์–ด์“ฐ๊ธฐ์—์„œ ๊นจ์ง„๋‹ค. drift/์ •๋ ฌ/AC ๋งค์นญ์€ ๋ชจ๋‘ **LLM ์˜๋ฏธ ํŒ๋‹จ**์œผ๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค(`/spec:status` ์™€ ๋™์ผ ์›์น™).

0.5-3. ํŒ์ •๋ณ„ ํ–‰๋™:
   - ALIGNED / MINOR-DRIFT โ†’ ๋ฆฌํฌํŠธ๋งŒ ์ถœ๋ ฅํ•˜๊ณ  ๊ทธ๋Œ€๋กœ ์ง„ํ–‰(์ฐจ๋‹จ ์•„๋‹˜).
   - **MAJOR-DRIFT โ†’ ๊ฒฝ๊ณ  ํ›„ ์ผ์‹œ์ •์ง€(ํ•„์ˆ˜)**: ์–ด๊ธ‹๋‚œ ์ง€์ ์„ ์š”์•ฝํ•ด ๋ณด์—ฌ์ฃผ๊ณ  `AskUserQuestion` ์œผ๋กœ  " ๊ธฐํš๊ณผ ํฌ๊ฒŒ ์–ด๊ธ‹๋‚จ โ€” ๊ทธ๋ž˜๋„ ๊ณ„์†ํ• ๊นŒ์š”? "   ํ™•์ธ์„ ๋ฐ›๋Š”๋‹ค.
     - pre-batch: ์‚ฌ์šฉ์ž๊ฐ€  " ์ค‘๋‹จ "   ์„ ํƒ ์‹œ ๋ฐฐ์น˜๋ฅผ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ณ  ์ข…๋ฃŒ(์ด์Šˆ/๋ช…์„ธ ์กฐ์ • ํ›„ ์žฌ์‹คํ–‰).  " ๊ณ„์† "   ์„ ํƒ ์‹œ ์‚ฌ์œ ๋ฅผ ๋กœ๊ทธ์— ๋‚จ๊ธฐ๊ณ  Phase 1 ๋กœ ์ง„ํ–‰.
     - post-batch:  " ์ค‘๋‹จ "   ์„ ํƒ ์‹œ Epic ์ข…๋ฃŒ๋ฅผ ๋ณด๋ฅ˜(Epic PR ์€ ์ด๋ฏธ ๋ณ‘ํ•ฉ๋์œผ๋ฏ€๋กœ ์ถ”๊ฐ€ ํ›„์† ์ด์Šˆ๋กœ ํ‘œ๋ฅ˜ ํ•ญ๋ชฉ์„ ์ถ”์ ).  " ๊ณ„์† "   ์„ ํƒ ์‹œ ๊ทธ๋Œ€๋กœ ๋งˆ๋ฌด๋ฆฌ.
   - ์ด ์ ๊ฒ€์€ **ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐฉํ–ฅ ์ ๊ฒ€**์ด๋‹ค โ€” ํ…Œ์ŠคํŠธ/lint/๋ฆฌ๋ทฐ Critical ์ฒ˜๋Ÿผ hard fail ํ•˜์ง€ ์•Š๊ณ , **MAJOR-DRIFT ์—์„œ๋งŒ ์‚ฌ์šฉ์ž ํ™•์ธ์œผ๋กœ ๋ฉˆ์ถ˜๋‹ค**.

0.5-4. ๋ฉฑ๋“ฑ/์žฌ๊ฐœ: ์ฝ๊ธฐ ์ „์šฉ์ด๋ผ ๋ถ€์ž‘์šฉ์ด ์—†๋‹ค. `/dev:batch {epic}` ์žฌ์‹คํ–‰ ์‹œ pre-batch ์ ๊ฒ€๋„ ๋‹ค์‹œ ๋„๋Š” ๊ฒŒ ์ •์ƒ์ด๋ฉฐ, ์ด๋ฏธ Closed ์ธ Story ๋Š” Phase 2 ์—์„œ ๊ฑด๋„ˆ๋›ด๋‹ค.

๋ฐฐ๊ฒฝ(D4): ๊ธธ๊ฒŒ ๋„๋Š” batch ๊ฐ€ ํ•œ Story ์”ฉ ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ ๋ˆ„์ ๋˜๋ฉด "๊ฐœ๋ณ„ PR ์€ ํ†ต๊ณผํ–ˆ์ง€๋งŒ Epic ์ „์ฒด๊ฐ€ ์›๋ž˜ ๊ธฐํš ๋ชฉํ‘œ์—์„œ ๋ฒ—์–ด๋‚œ" ์ƒํƒœ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด checkpoint ๋Š” ๊ทธ ํ‘œ๋ฅ˜๋ฅผ ์‹œ์ž‘ ์‹œ์ ๊ณผ ๋งˆ๋ฌด๋ฆฌ ์‹œ์ ์— ์˜๋ฏธ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋ฒˆ์”ฉ ๋น„์ถ”๋Š” ๊ฑฐ์šธ์ด๋‹ค. ๋‹จ, ๊ธฐํš(Seed)์ด ์—†๋Š” ์ €์žฅ์†Œ์—์„œ๋„ batch ๋Š” ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์‹œ๋“œ ๋ถ€์žฌ/๋ฏธํ™•์ • ์‹œ ์™„์ „ํ•œ no-op ์œผ๋กœ ๋‘”๋‹ค(opt-in). ์ ๊ฒ€ ๋กœ์ง์€ /spec:status(D3) ์— ์œ„์ž„ํ•˜๋ฉฐ ์—ฌ๊ธฐ์„œ ์–ด๋–ค ๋น„๊ต ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ์ƒˆ๋กœ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š”๋‹ค.

Phase 1: Epic Branch Creation#

0. (Phase 0.5) Pre-batch seed-alignment checkpoint โ€” LOCKED seed ์žˆ์œผ๋ฉด LLM-SEMANTIC ์ •๋ ฌ ์ ๊ฒ€(MAJOR-DRIFT ์‹œ ํ™•์ธ ํ›„ ์ง„ํ–‰), ์—†์œผ๋ฉด no-op skip
1. Query Epic issue info (ZenHub)
2. Update development branch to latest
3. Create Epic branch: epic/{epic_number}-{slug}
4. Move Epic to In Progress pipeline

Phase 2: Sequential Story Processing (Per-Story Cycle)#

Executes the /dev:run cycle for each Story. Base branch is automatically set to the Epic branch.

Per-Story Cycle:
1. Move Pipeline to  " In Progress "   (+ ํ™œ์„ฑ ์Šคํ”„๋ฆฐํŠธ ๋ฐฐ์ • โ€” /dev:run Step 2.5 ์ƒ์†, --no-sprint ๋กœ opt-out)
2. Create Story branch: story/{story_number}-{slug} (based on Epic branch)
3. If Sub-tasks exist โ†’ execute Per-Sub-task Cycle
4. If no Sub-tasks โ†’ implement directly
5. Write and run tests
6. Pre-push verification (lint + DCM)
6.5. โญ **Per-Story Stall Budget** (verify์™€ review ์‚ฌ์ด): ๊ฐ™์€ ์‹คํŒจ๊ฐ€ ๋ฐ˜๋ณต๋˜๋ฉด 3-rung ๋ž˜๋”๋ฅผ ์˜ค๋ฅธ๋‹ค โ€” (1) same-strategy retry(์†Œํญ ๋ฐ”์šด๋“œ), (2) ๋™์ผ ์‹คํŒจ๊ฐ€ **์˜๋ฏธ์ƒ** ๋ฐ˜๋ณต๋˜๋ฉด affinity ํŽ˜๋ฅด์†Œ๋‚˜๋กœ `/dev:unstuck solo` ํ˜ธ์ถœ(reframe, ์žฌ์‹œ๋„ ์•„๋‹˜), (3) ๊ทธ๋ž˜๋„ ์•ˆ ํ’€๋ฆฌ๋ฉด ์ด Story๋ฅผ `BLOCKED( ' unstuck_exhausted ' )`๋กœ ํ‘œ์‹œํ•˜๊ณ  **๋‹ค์Œ Story๋กœ ๊ณ„์†**(Epic ์ „์ฒด ์ค‘๋‹จ ๊ธˆ์ง€). ์ƒ์„ธ๋Š” `sequential-workflow.md`์˜  " Stall Budget "   ์ฐธ์กฐ.
7. Code Review Gate
8. Create PR โ†’ targeting Epic branch (base: epic/{epic_number}-{slug}); PR body์— `Closes #{story_number}` + `Parent Epic: #{epic_number}` ํฌํ•จ
9. Squash merge (๋จธ์ง€ = Close) โ€” base๊ฐ€ **Epic ๋ธŒ๋žœ์น˜(๋น„๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜)** ์ด๋ฏ€๋กœ GitHub `Closes #`๋Š” **์ž๋™์œผ๋กœ ๋‹ซ์ง€ ์•Š์Šต๋‹ˆ๋‹ค**.
9.5. โญ **๋ช…์‹œ์  Close (ํ•„์ˆ˜ โ€” ํด๋ฐฑ ์•„๋‹˜)**: `gh issue close {story} --reason completed` ๋กœ ์ง์ ‘ ๋‹ซ๊ธฐ โ†’ `gh issue view {story} --json state`๋กœ `CLOSED` ํ™•์ธ โ†’ ZenHub `searchClosedIssues  " #{story} " `์— ์—†์œผ๋ฉด `updateIssue state:CLOSED` (Done โ‰  closed)
10. โญ Post-merge: `git checkout epic/{epic_number}-{slug}  & &   git pull --ff-only origin epic/{epic_number}-{slug}  & &   git submodule sync --recursive  & &   git submodule update --init --recursive` (base ์ตœ์‹ ํ™” + ์„œ๋ธŒ๋ชจ๋“ˆ ๋™๊ธฐํ™”) โ€” submodule sync/update ์‹คํŒจ๋Š” **๊ฒฝ๊ณ  ํ›„ ๊ณ„์†**(Epic ์ค‘๋‹จ ์•„๋‹˜). ์„œ๋ธŒ๋ชจ๋“ˆ ์—†์œผ๋ฉด no-op.
11. Move to next Story

Per-Story Stall Budget (Step 6.5 detail)

A single Story that keeps failing must NOT halt the Epic. Between verification (Step 6) and the Code Review Gate (Step 7), apply the 3-rung stall ladder (shared with sequential-workflow.md โ†’ "Stall Budget"):

RungTriggerAction
1First failuresSame-strategy retry, small bounded count (lint/format/build auto-fix).
2Same failure repeats (judged semantically, not by string diff)/dev:unstuck solo <affinity-persona> โ€” reframe, not retry; next move must differ in kind.
3Reframe exhausted, Story still stuckMark Story BLOCKED('unstuck_exhausted') โ†’ CONTINUE to next Story. Epic NOT halted.

Rung 2 affinity persona (semantic match, default CONTRARIAN): same-error-Nร— โ†’ hacker; flip-flop โ†’ architect; missing-info โ†’ researcher; over-built โ†’ simplifier; unknown โ†’ contrarian. Persona definitions: plugins/cc-spec-clarity/references/LATERAL_PERSONAS.md.

LLM-SEMANTIC, never lexical. "๋™์ผ ์‹คํŒจ์ธ๊ฐ€?" ํŒ์ •์€ ์˜๋ฏธ ๊ธฐ๋ฐ˜ โ€” ์—๋Ÿฌ ํ…์ŠคํŠธ์˜ ํ† ํฐ/๊ณต๋ฐฑ ๊ฒน์นจ์œผ๋กœ ๋น„๊ตํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•œ๊ตญ์–ด๋Š” ๋„์–ด์“ฐ๊ธฐ ๊ฒฝ๊ณ„๊ฐ€ ์—†๊ณ  ์กฐ์‚ฌ๊ฐ€ ๋ถ™์–ด ๊ฐ™์€ ๋ธ”๋กœ์ปค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋กœ๊ทธ๊ฐ€ ํ† ํฐ์„ ๊ฑฐ์˜ ๊ณต์œ ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. /dev:unstuck ์€ ์„ ํƒ์ง€๋ฅผ ์ค„ ๋ฟ ๊ฒฐ๋ก ์„ ๋‚ด์ง€ ์•Š๋Š”๋‹ค. BLOCKED ๋œ Story ๋Š” Phase 0 ์˜ ๋ฉฑ๋“ฑ resume ๊ณ„์•ฝ์œผ๋กœ ๋‚˜์ค‘์— ๋‹ค์‹œ ์‹œ๋„๋œ๋‹ค.

Phase 2.5: Sequential Sub-task Processing (Optional)#

When a Story has Sub-tasks, process them with the same pattern.

Per-Sub-task Cycle:
1. Create Sub-task branch: task/{subtask_number}-{slug} (based on Story branch)
2. Implementation work
3. Write and run tests
4. Verification gate
5. Create PR โ†’ targeting Story branch (base: story/{story_number}-{slug}); PR body์— `Closes #{subtask_number}` + `Parent Story: #{story_number}` ํฌํ•จ
6. Squash merge (๋จธ์ง€ = Close) โ€” base๊ฐ€ **Story ๋ธŒ๋žœ์น˜(๋น„๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜)** ์ด๋ฏ€๋กœ GitHub `Closes #`๋Š” **์ž๋™์œผ๋กœ ๋‹ซ์ง€ ์•Š์Šต๋‹ˆ๋‹ค**.
6.5. โญ **๋ช…์‹œ์  Close (ํ•„์ˆ˜ โ€” ํด๋ฐฑ ์•„๋‹˜)**: `gh issue close {subtask} --reason completed` ๋กœ ์ง์ ‘ ๋‹ซ๊ธฐ โ†’ `CLOSED` ํ™•์ธ โ†’ ZenHub ๋ฏธ๋™๊ธฐํ™” ์‹œ `updateIssue state:CLOSED`
7. โญ Post-merge: `git checkout story/{story_number}-{slug}  & &   git pull --ff-only origin story/{story_number}-{slug}  & &   git submodule sync --recursive  & &   git submodule update --init --recursive` (base ์ตœ์‹ ํ™” + ์„œ๋ธŒ๋ชจ๋“ˆ ๋™๊ธฐํ™”)
8. Move to next Sub-task

Phase 3: Epic PR Creation#

After all Stories are complete:

1. โ›” ์™„๋ฃŒ์„ฑ Hard Gate (ํ•„์ˆ˜, ์‹คํ–‰ํ˜•) โ€” ๋ชจ๋“  ํ•˜์œ„ StoryยทSub-task ์ด์Šˆ๊ฐ€ ์ •๋ง Closed ์ธ์ง€ ํ™•์ธ. prose ํ™•์ธ ๊ธˆ์ง€:
     const children = await mcp__zenhub__searchLatestIssues({ query: `parent:${epicId}` }); // getChildrenOfParent ์—†์Œ
     const open = children.filter(c = >   (c.state ||  " " ).toUpperCase() !==  " CLOSED " );          // GitHub state = source of truth
     if (children.length === 0) โ†’  " ํŒ์ • ๋ถˆ๊ฐ€ " : ์ž์‹์ด ์—†๋Š” ๊ฒŒ ๋งž๋Š”์ง€ ์‚ฌ์šฉ์ž ํ™•์ธ ํ›„์—๋งŒ ์ง„ํ–‰
     if (open.length  >   0) โ†’ โ›” Epic PR/๋จธ์ง€/์ข…๋ฃŒ ์ค‘๋‹จ. BLOCKED( ' unstuck_exhausted ' ) ๋„ OPEN ์œผ๋กœ ๊ฐ„์ฃผ.
       throw `Epic #${epic} ๋ฏธ์™„๋ฃŒ: OPEN child ${open.length}๊ฐœ (${open.map(c= > " # " +c.number)}). ํ•ด๊ฒฐ/์žฌ์‹œ๋„ ํ›„ batch ์žฌ์‹คํ–‰`
2. Review changes against development
3. Create Epic PR โ†’ targeting development; PR body์— `Closes #{epic_number}` ํฌํ•จ
4. Conduct code review
5. Squash merge after user approval (๋จธ์ง€ = Close)
6. **Epic ์ด์Šˆ ์ข…๋ฃŒ** โ€” `development`๊ฐ€ ์ €์žฅ์†Œ **๊ธฐ๋ณธ(default) ๋ธŒ๋žœ์น˜**๋ฉด `Closes #{epic_number}`๋กœ ์ž๋™ ๋‹ซํž˜, ์•„๋‹ˆ๋ฉด ์ž๋™์œผ๋กœ ๋‹ซํžˆ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ช…์‹œ์  ์ข…๋ฃŒ ํ•„์š”.
6.5. โญ Close ๊ฒ€์ฆ + ํด๋ฐฑ: `gh issue view {epic} --json state` โ†’ ๋ฏธclose ์‹œ `gh issue close {epic} --reason completed`; ZenHub ๋ฏธ๋™๊ธฐํ™” ์‹œ `updateIssue state:CLOSED`
6.6. โญ **Project ์žฌ๊ท€ ํ™•์ธ** โ€” Epic์ด Project(๋˜๋Š” Initiative)์˜ ์ž์‹์ด๋ฉด, `checkAndCloseParent(epic_number)`(`commands/agents/dev/issue-state-agent.md`)๋ฅผ ํ˜ธ์ถœํ•ด ํ˜•์ œ Epic์ด ๋ชจ๋‘ Closed์ธ์ง€ ํ™•์ธ ํ›„ ์ƒ์œ„๋ฅผ ์ž๋™ ์ข…๋ฃŒ(์—ฐ์‡„์ ์œผ๋กœ Initiative๊นŒ์ง€). Epic์ด ์ตœ์ƒ์œ„(๋ถ€๋ชจ ์—†์Œ)๋ฉด no-op.
7. โญ Post-merge: `git checkout development  & &   git pull --ff-only origin development  & &   git submodule sync --recursive  & &   git submodule update --init --recursive` (base ์ตœ์‹ ํ™” + ์„œ๋ธŒ๋ชจ๋“ˆ ๋™๊ธฐํ™”)
8. (Phase 0.5) Post-batch seed-alignment checkpoint โ€” LOCKED seed ์žˆ์œผ๋ฉด ์™„๋ฃŒ๋œ ์ด์Šˆ ์ง‘ํ•ฉ + Epic PR ์„ LLM-SEMANTIC ์œผ๋กœ ์žฌ๋Œ€์กฐ(AC-ID ์ƒํƒœ echo + ๋ชฉํ‘œ ์ •๋ ฌ ํŒ์ •), MAJOR-DRIFT ์‹œ ๊ฒฝ๊ณ  ํ›„ Epic ์ข…๋ฃŒ ํ™•์ธ. ์—†์œผ๋ฉด no-op skip.

Flow Diagram#

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  /dev:batch {epic_number}                                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                              โ”‚
โ”‚  Phase 1: Epic Branch Creation                               โ”‚
โ”‚  โ”œโ”€โ”€ Query Epic issue (ZenHub)                               โ”‚
โ”‚  โ”œโ”€โ”€ git checkout development  & &   git pull                   โ”‚
โ”‚  โ”œโ”€โ”€ git checkout -b epic/{number}-{slug}                   โ”‚
โ”‚  โ””โ”€โ”€ git push -u origin epic/{number}-{slug}                โ”‚
โ”‚                                                              โ”‚
โ”‚  Phase 2: Sequential Story Processing                        โ”‚
โ”‚  โ”œโ”€โ”€ Query Story list (child issues)                         โ”‚
โ”‚  โ”œโ”€โ”€ for each Story:                                         โ”‚
โ”‚  โ”‚   โ”œโ”€โ”€ /dev:run --base epic/{number}-{slug} {story_num}   โ”‚
โ”‚  โ”‚   โ”‚   โ”œโ”€โ”€ Branch: story/{story}-{slug}                    โ”‚
โ”‚  โ”‚   โ”‚   โ”œโ”€โ”€ [If Sub-tasks exist]                            โ”‚
โ”‚  โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ Per-Sub-task Cycle                          โ”‚
โ”‚  โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ task/{subtask}-{slug} (Story-based)    โ”‚
โ”‚  โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ Implement โ†’ Test โ†’ Verify               โ”‚
โ”‚  โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ PR โ†’ Merge into Story branch            โ”‚
โ”‚  โ”‚   โ”‚   โ”œโ”€โ”€ Implement โ†’ Test โ†’ Verification Gate            โ”‚
โ”‚  โ”‚   โ”‚   โ””โ”€โ”€ PR โ†’ Merge into Epic branch                     โ”‚
โ”‚  โ”‚   โ””โ”€โ”€ Next Story                                          โ”‚
โ”‚  โ”‚                                                           โ”‚
โ”‚  Phase 3: Epic PR Creation                                    โ”‚
โ”‚  โ”œโ”€โ”€ Create Epic branch โ†’ development PR                     โ”‚
โ”‚  โ”œโ”€โ”€ Review full changes                                     โ”‚
โ”‚  โ”œโ”€โ”€ Wait for user approval                                  โ”‚
โ”‚  โ””โ”€โ”€ Squash merge โ†’ Epic Close                               โ”‚
โ”‚                                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

MCP Call Order#

// Phase 1: Initialization
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const epic = await mcp__zenhub__searchLatestIssues({ query: `#${epicNumber}` });
const stories = await mcp__zenhub__searchLatestIssues({
  query: `parent:${epic[0].id}`,
});

// Phase 2: Per-Story processing
for (const story of stories) {
  // Check Sub-tasks
  const subtasks = await mcp__zenhub__searchLatestIssues({
    query: `parent:${story.id}`,
  });

  if (subtasks.length  >   0) {
    // Story with Sub-tasks โ†’ create Story branch first
    // Process Sub-tasks sequentially, then integrate into Story branch
    for (const subtask of subtasks) {
      // /dev:run --base story/{story_number}-{slug} {subtask.number}
    }
    // PR Story branch to Epic branch
  } else {
    // Story without Sub-tasks โ†’ implement directly
    // /dev:run --base epic/{epic_number}-{slug} {story.number}
  }
}

// Phase 3: Epic PR
// gh pr create --base development --title  " [Epic] ... "

Pipeline Query#

Pipeline IDs differ per workspace. Dynamic query at session start:

const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const pipelines = workspace.pipelines;
// Find by name in pipelines:  " New Issues " ,  " In Progress " ,  " Review/QA " , etc.
// Done pipeline is NOT used (Done โ‰  closed). Merge = Close: `Closes #` โ†’ GitHub closed
// โ†’ ZenHub syncs to Closed. Verify with searchClosedIssues + fallback updateIssue.

PR Creation Templates#

Story PR (โ†’ Epic branch)#

gh pr create --base  " epic/{epic_number}-{slug} "   \
  --title  " {story.title} "   --body  " $(cat  < < ' EOF ' 
 ## Summary
- {Change summary}

## Related Issue
- Closes #{story.number}
- Parent Epic: #{epic_number}

## Test Plan
- [ ] UseCase unit tests passed
- [ ] BLoC unit tests passed

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

Sub-task PR (โ†’ Story branch)#

gh pr create --base  " story/{story_number}-{slug} "   \
  --title  " {subtask.title} "   --body  " $(cat  < < ' EOF ' 
 ## Summary
- {Change summary}

## Related Issue
- Closes #{subtask_number}
- Parent Story: #{story_number}

## Test Plan
- [ ] Unit tests passed

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

Epic PR (โ†’ development)#

gh pr create --base  " development "   \
  --title  " [Epic] {epic.title} "   --body  " $(cat  < < ' EOF ' 
 ## Summary
- {Epic full change summary}

## Included Stories
- โœ… #{story_1} - {title}
- โœ… #{story_2} - {title}
- โœ… #{story_3} - {title}

## Related Issue
- Closes #{epic_number}

## Test Plan
- [ ] Full integration tests passed
- [ ] Manual testing complete

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

Issue Closure & Post-Merge Sync โญ#

๋ชจ๋“  ๋จธ์ง€๋Š” ํ•ด๋‹น ์ด์Šˆ๋ฅผ Close(๊ฒ€์ฆ ํฌํ•จ)ํ•˜๊ณ , base ๋ธŒ๋žœ์น˜๋ฅผ ์ตœ์‹ ์œผ๋กœ ๋™๊ธฐํ™”ํ•œ๋‹ค. ์ •์ฑ… = "๋จธ์ง€ = Close" (B).

โš ๏ธ ZenHub 2-์ƒํƒœ ๋ชจ๋ธ: Pipeline(๋ณด๋“œ ์นผ๋Ÿผ)๊ณผ GitHub state(open/closed)๋Š” ๋ณ„๊ฐœ๋‹ค. Done ์นผ๋Ÿผ์œผ๋กœ ์˜ฎ๊ฒจ๋„ GitHub ์ด์Šˆ๋Š” open ๊ทธ๋Œ€๋กœ โ€” Done โ‰  closed. Closed ํŒŒ์ดํ”„๋ผ์ธ๋งŒ GitHub closed์™€ 1:1. ๋”ฐ๋ผ์„œ Done์€ ์“ฐ์ง€ ์•Š๊ณ , ๋จธ์ง€ ํ›„ GitHub state๋กœ ๋‹ซํž˜์„ ๊ฒ€์ฆํ•˜๊ณ  ํด๋ฐฑํ•œ๋‹ค.

๋‹จ๊ณ„๋จธ์ง€ ๋ฐฉํ–ฅ์ด์Šˆ Close (๊ฒ€์ฆ ํฌํ•จ)Post-merge ์ฒดํฌ์•„์›ƒ
Sub-taskโ†’ Story ๋ธŒ๋žœ์น˜Sub-task ์ด์Šˆ Close (Closes #{subtask}) + verify_closedgit checkout story/{story}-{slug} && git pull + git submodule update --init --recursive
Storyโ†’ Epic ๋ธŒ๋žœ์น˜Story ์ด์Šˆ Close (Closes #{story}) + verify_closedgit checkout epic/{epic}-{slug} && git pull + git submodule update --init --recursive
Epicโ†’ developmentEpic ์ด์Šˆ ์ข…๋ฃŒ (Closes #{epic}) + verify_closedgit checkout development && git pull + git submodule update --init --recursive
  • ๊ฐ PR body์˜ Closes #{number} ํ‚ค์›Œ๋“œ๋กœ squash ๋จธ์ง€ ์‹œ GitHub ์ด์Šˆ๊ฐ€ ์ž๋™ Close๋˜๊ณ , ์—ฐ๋™๋œ ZenHub ์ด์Šˆ ์ƒํƒœ๋„ Closed๋กœ ๋™๊ธฐํ™”๋œ๋‹ค.
  • Close ๊ฒ€์ฆ + ํด๋ฐฑ (๋งค ๋จธ์ง€ ํ›„ ํ•„์ˆ˜): gh issue view {N} --json state๋กœ GitHub closed ํ™•์ธ โ†’ ์•„๋‹ˆ๋ฉด gh issue close {N} --reason completed. ์ด์–ด searchClosedIssues "#{N}"๋กœ ZenHub ๋™๊ธฐํ™” ํ™•์ธ โ†’ ๋ˆ„๋ฝ ์‹œ updateIssue state:CLOSED. (Closes #N ๋ˆ„๋ฝยท๋™๊ธฐํ™” ์ง€์—ฐ ๋Œ€๋น„)
  • ํ•˜์œ„ StoryยทSub-task๊ฐ€ ๋ชจ๋‘ Close๋˜๊ณ  Epic ๋ธŒ๋žœ์น˜ PR์ด development์— ๋จธ์ง€๋˜๋ฉด Epic ์ด์Šˆ๊ฐ€ ์ž๋™ ์ข…๋ฃŒ๋˜๋ฉฐ, development๋ฅผ ์ตœ์‹ ์œผ๋กœ ์ฒดํฌ์•„์›ƒํ•œ๋‹ค.
  • ์„œ๋ธŒ๋ชจ๋“ˆ ๋™๊ธฐํ™” (๋งค ๋จธ์ง€ ํ›„ ํ•„์ˆ˜): git pull์€ superproject์˜ ์„œ๋ธŒ๋ชจ๋“ˆ ํฌ์ธํ„ฐ๋งŒ ๊ฐฑ์‹ ํ•˜๊ณ  ์„œ๋ธŒ๋ชจ๋“ˆ ์›Œํ‚นํŠธ๋ฆฌ๋Š” ์ฒดํฌ์•„์›ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. base ์ตœ์‹ ํ™” ์งํ›„ git submodule sync --recursive && git submodule update --init --recursive๋กœ ์„œ๋ธŒ๋ชจ๋“ˆ์„ base๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ปค๋ฐ‹์— ์ •๋ ฌํ•œ๋‹ค(Serverpod/Melos ๋ชจ๋…ธ๋ ˆํฌ ๋นŒ๋“œ/์ฝ”๋“œ์   drift ๋ฐฉ์ง€). ์„œ๋ธŒ๋ชจ๋“ˆ์ด ์—†์œผ๋ฉด no-op.
  • ๋จธ์ง€ ํ›„ base ์ตœ์‹ ํ™” + ์„œ๋ธŒ๋ชจ๋“ˆ ๋™๊ธฐํ™”๋Š” /dev:run Step 12.5(Closure Verification + Post-Merge Sync)์™€ ๋™์ผ ์›์น™(git pull --ff-only + git submodule update)์ด๋‹ค.

Verification Checklist#

  • (seed๊ฐ€ LOCKED์ผ ๋•Œ๋งŒ) pre-batch / post-batch seed-alignment ์ ๊ฒ€ ์‹คํ–‰, MAJOR-DRIFT ์‹œ ์‚ฌ์šฉ์ž ํ™•์ธ โ€” seed ๋ถ€์žฌ/DRAFT๋ฉด no-op skip (์ฒดํฌ ๋ถˆํ•„์š”)
  • Epic branch correctly branched from development
  • Each Story branch branched from Epic branch
  • Sub-task branches branched from Story branch
  • Story PR base is Epic branch
  • Epic PR base is development
  • Epic PR created after all Stories are merged
  • ๋ฐ˜๋ณต ์‹คํŒจ Story๋Š” stall budget(retry โ†’ /dev:unstuck solo โ†’ BLOCKED)์„ ์ ์šฉํ•˜๊ณ , BLOCKED์—ฌ๋„ Epic์€ ๊ณ„์† ์ง„ํ–‰
  • ๊ฐ Sub-task/Story PR์ด Closes #{number}๋กœ ์ด์Šˆ๋ฅผ Close
  • ๊ฐ ๋จธ์ง€ ํ›„ GitHub closed + ZenHub Closed ๊ฒ€์ฆ (verify_closed, Done์— ๋ฐฉ์น˜ ๊ธˆ์ง€)
  • Epic PR ๋จธ์ง€ ์‹œ Epic ์ด์Šˆ ์ž๋™ ์ข…๋ฃŒ + ๊ฒ€์ฆ
  • Epic์ด Project/Initiative์˜ ์ž์‹์ด๋ฉด checkAndCloseParent๋กœ ์ƒ์œ„๊นŒ์ง€ ์žฌ๊ท€ ํ™•์ธ
  • ๊ฐ ๋จธ์ง€ ํ›„ base ๋ธŒ๋žœ์น˜ ์ตœ์‹  ์ฒดํฌ์•„์›ƒ (git pull)
  • BDD scenarios vs actual implementation comparison
  • Code conventions followed
  • Lint 0 issues + DCM error 0 issues