LogoSkills

zenhub:epic

ZenHub Project/Epic/Story creation (based on feature requirements), with priority review and pipeline sorting

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

/zenhub:epic โ€” ์š”๊ตฌ์‚ฌํ•ญ์„ ZenHub ์ผ๊ฐ์œผ๋กœ ์ž๋™ ์ •๋ฆฌ#

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

๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ(๋˜๋Š” ํ™”๋ฉด ์บก์ฒ˜ ์ด๋ฏธ์ง€)์„ ๋„ฃ์œผ๋ฉด, ZenHub์— "ํฐ ์ผ๊ฐ โ†’ ์ž‘์€ ์ผ๊ฐ"์„ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ํฐ ๊ณต์‚ฌ ๊ณ„ํš์„œ๋ฅผ ๋ฐ›์•„์„œ "ํ”„๋กœ์ ํŠธ โ†’ ๋‹จ๊ณ„ โ†’ ์„ธ๋ถ€ ์ž‘์—…"์œผ๋กœ ์ชผ๊ฐœ๊ณ , ์–ด๋–ค ์ผ์„ ๋จผ์ € ํ• ์ง€ ์šฐ์„ ์ˆœ์œ„๊นŒ์ง€ ๋งค๊ฒจ ์ผ์ •ํ‘œ(๋ณด๋“œ)์— ๊ฝ‚์•„ ์ฃผ๋Š” ๋น„์„œ๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

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

  • ๊ธฐํš/์š”๊ตฌ์‚ฌํ•ญ์ด ์ •๋ฆฌ๋œ ์ƒํƒœ์—์„œ ZenHub์— ์‹ค์ œ ์ผ๊ฐ(์ด์Šˆ)์„ ๋งŒ๋“ค์–ด์•ผ ํ•  ๋•Œ
  • ํ™”๋ฉด ์บก์ฒ˜ ์ด๋ฏธ์ง€๋งŒ ์žˆ๊ณ , ๊ทธ๊ฑธ ๋ฐ”ํƒ•์œผ๋กœ ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์ผ๊ฐ์„ ํ•œ ๋ฒˆ์— ๋ฝ‘๊ณ  ์‹ถ์„ ๋•Œ
  • /figma:analyze(ํ”ผ๊ทธ๋งˆ ๋ถ„์„)์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์—์„œ ์ž๋™์œผ๋กœ ์ด์–ด์„œ ํ˜ธ์ถœ๋  ๋•Œ
  • ์—ฌ๋Ÿฌ Epic์„ ๋ฌถ๋Š” ์ƒ์œ„ Project ๋‹จ์œ„ ์ผ๊ฐ์„ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ (--project)

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

  • ZenHub ์ด์Šˆ ๊ณ„์ธต์„ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค: (์„ ํƒ) Project โ†’ Epic(ํฐ ์ผ๊ฐ) โ†’ Story(ํ™”๋ฉด๋ณ„ ์ผ๊ฐ) โ†’ Sub-task(์„ธ๋ถ€ ์ž‘์—…)
  • ๊ฐ ์ผ๊ฐ์— ์šฐ์„ ์ˆœ์œ„(P0/P1/P2) ๋ฅผ ๋งค๊ธฐ๊ณ , ๊ทธ ๊ทผ๊ฑฐ ํ‘œ๋ฅผ Epic ๋ณธ๋ฌธ์— ๋„ฃ์–ด ์ค๋‹ˆ๋‹ค
  • Epic์— ์ผ์ •(์‹œ์ž‘์ผ~์ข…๋ฃŒ์ผ)๊ณผ Story Point(์˜ˆ์ƒ ์ž‘์—…๋Ÿ‰) ๋ฅผ ๋„ฃ์–ด ๋กœ๋“œ๋งต์— ๋ง‰๋Œ€๋กœ ํ‘œ์‹œ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค
  • ๋งŒ๋“  ์ด์Šˆ๋“ค์„ ์šฐ์„ ์ˆœ์œ„์— ๋งž๋Š” ํŒŒ์ดํ”„๋ผ์ธ(Product Backlog / Sprint Backlog / Icebox) ์œผ๋กœ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค
  • ์ด๋ฏธ์ง€ ๋ถ„์„์„ ์“ฐ๋ฉด ์š”๊ตฌ์‚ฌํ•ญยทBDD ์‹œ๋‚˜๋ฆฌ์˜ค ๋ฌธ์„œ๊นŒ์ง€ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด .claude/docs/{๊ธฐ๋Šฅ๋ช…}/ ์•„๋ž˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค (requirements.md, bdd/, zenhub/epic.md, priority.md ๋“ฑ)

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

# ๊ฐ€์žฅ ๊ธฐ๋ณธ โ€” community ๊ธฐ๋Šฅ, Post ์—”ํ‹ฐํ‹ฐ๋กœ Epic+Story ์ƒ์„ฑ
/zenhub:epic community Post

# ์—ฌ๋Ÿฌ Epic์„ ๋ฌถ๋Š” ์ƒ์œ„ Project๊นŒ์ง€ ํ•œ ๋ฒˆ์— ๋งŒ๋“ค๊ธฐ
/zenhub:epic --project  " ์–ด๋“œ๋ฏผ ์ฝ˜์†” v2 "   --epics  " auth,community,payment " 

 # ์ด๋ฏธ ์žˆ๋Š” Project ์ด์Šˆ(์˜ˆ: 1024๋ฒˆ) ๋ฐ‘์— Epic ์—ฐ๊ฒฐ
/zenhub:epic community Post --parent-project 1024

# ํ™”๋ฉด ์บก์ฒ˜ ์ด๋ฏธ์ง€๋กœ๋ถ€ํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ+์ผ๊ฐ ์ž๋™ ์ƒ์„ฑ
/zenhub:epic community Post --images  " list.png,detail.png,form.png " 

 # ์Šคํ”„๋ฆฐํŠธยท๋ผ๋ฒจ ์ง€์ •
/zenhub:epic community Post --labels  " sprint-1,mvp "   --sprint current

# ์ผ์ • ์ง์ ‘ ์ง€์ • (๋˜๋Š” --no-dates ๋กœ ์ผ์ • ๋น„์šฐ๊ธฐ)
/zenhub:epic community Post --start-date 2026-06-16 --end-date 2026-07-14

์ž์ฃผ ์“ฐ๋Š” ์˜ต์…˜ ๋ช‡ ๊ฐ€์ง€:

  • --images / --images-dir: ํ™”๋ฉด ์บก์ฒ˜๋กœ ์š”๊ตฌ์‚ฌํ•ญยทBDD๊นŒ์ง€ ์ž๋™ ์ƒ์„ฑ
  • --points "3,3,5": ํ™”๋ฉด๋ณ„ ์˜ˆ์ƒ ์ž‘์—…๋Ÿ‰(Story Point)์„ ์ง์ ‘ ์ง€์ •
  • --no-sort: ํŒŒ์ดํ”„๋ผ์ธ ์ž๋™ ์ •๋ ฌ์„ ๊ฑด๋„ˆ๋œ€
  • --no-dates: Epic ์ผ์ • ์„ค์ •์„ ๊ฑด๋„ˆ๋œ€

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

๋Œ€๋žต ์ด๋Ÿฐ ์ˆœ์„œ๋กœ ์ง„ํ–‰๋˜๊ณ , ์ค‘์š”ํ•œ ๋ถ„๊ธฐ๋งˆ๋‹ค "์ด๋Œ€๋กœ ์ง„ํ–‰ํ• ๊นŒ์š”?"๋ผ๊ณ  ์‚ฌ๋žŒ์—๊ฒŒ ํ™•์ธ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

  1. (์ด๋ฏธ์ง€๊ฐ€ ์žˆ์œผ๋ฉด) ํ™”๋ฉด ๋ถ„์„ โ€” ์บก์ฒ˜๊ฐ€ ๋ชฉ๋ก/์ƒ์„ธ/ํผ ์ค‘ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋‚ด๊ณ , ๊ฑฐ๊ธฐ์„œ Entity ํ•„๋“œ์™€ BDD ์‹œ๋‚˜๋ฆฌ์˜ค, ์š”๊ตฌ์‚ฌํ•ญ ๋ฌธ์„œ๋ฅผ ์ž๋™์œผ๋กœ ๋ฝ‘์Šต๋‹ˆ๋‹ค.
  2. ์š”๊ตฌ์‚ฌํ•ญ ์ฝ๊ธฐ โ€” ๋ฐฉ๊ธˆ ๋งŒ๋“ (๋˜๋Š” ๊ธฐ์กด) ์š”๊ตฌ์‚ฌํ•ญยทBDD ๋ฌธ์„œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
  3. ์šฐ์„ ์ˆœ์œ„ ๊ฒ€ํ†  โ€” ๋งŒ๋“ค ์ผ๊ฐ๋งˆ๋‹ค ์˜์กด์„ฑยท์ค‘์š”๋„ยท์œ„ํ—˜ยท์ž‘์—…๋Ÿ‰์„ ๋”ฐ์ ธ P0/P1/P2 ๋“ฑ๊ธ‰์„ ๋งค๊ธฐ๊ณ , ํ‘œ๋กœ ๋ณด์—ฌ ์ค€ ๋’ค ํ™•์ธ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. (๋ผ๋ฒจ์€ ์ƒ์„ฑ ํ›„ ๋ชป ๋ฐ”๊พธ๋ฏ€๋กœ ๋ฏธ๋ฆฌ ์ •ํ•ฉ๋‹ˆ๋‹ค.)
  4. ์ด์Šˆ ์ƒ์„ฑ โ€” (์„ ํƒ) Project โ†’ Epic โ†’ Story โ†’ Sub-task ์ˆœ์„œ๋กœ ZenHub ์ด์Šˆ๋ฅผ ๋งŒ๋“ค๊ณ  ์„œ๋กœ ๋ถ€๋ชจ-์ž์‹์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
  5. ์ผ์ •ยท์ž‘์—…๋Ÿ‰ ์„ค์ • โ€” Epic์— ์‹œ์ž‘/์ข…๋ฃŒ์ผ๊ณผ Story Point๋ฅผ ๋„ฃ์–ด ๋กœ๋“œ๋งต์— ํ‘œ์‹œ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. Story๋“ค๋„ Epic ๊ธฐ๊ฐ„ ์•ˆ์—์„œ ์ˆœ์„œ๋Œ€๋กœ ๋‚˜๋ˆ  ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
  6. ํŒŒ์ดํ”„๋ผ์ธ ์ •๋ ฌ โ€” ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ๊ฐ ์ด์Šˆ๋ฅผ ์•Œ๋งž์€ ๋ณด๋“œ(ํŒŒ์ดํ”„๋ผ์ธ)๋กœ ์˜ฎ๊ธฐ๊ณ , P0 Story๋Š” (์š”์ฒญ ์‹œ) ์Šคํ”„๋ฆฐํŠธ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
  7. ๊ฒฐ๊ณผ ๊ธฐ๋ก โ€” ๋งŒ๋“  ๋‚ด์šฉ๊ณผ ์šฐ์„ ์ˆœ์œ„ยท๋ฐฐ์น˜ ๊ฒฐ๊ณผ๋ฅผ .claude/docs/{๊ธฐ๋Šฅ๋ช…}/ ์•„๋ž˜ ๋ฌธ์„œ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.

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

Triggers#

  • When creating issues from feature requirements
  • When called from /figma:analyze Phase 4
  • When manually creating ZenHub issues
  • When creating a Project-level issue that wraps multiple Epics (--project)

Context Trigger Pattern#

/zenhub:epic {feature_name} {entity_name} [--options]

Parameters#

Required Parameters#

ParameterDescriptionExample
feature_nameFeature name (snake_case)community
entity_nameEntity name (PascalCase)Post

Image Analysis Options (Optional)#

ParameterDescriptionExample
--imagesImage files to analyze (comma-separated)"list.png,detail.png,form.png"
--images-dirImage directory path./screenshots/
--attach-imagesAttach to Issue after committing to repo (default: false)true/false
--min-confidenceMinimum confidence for screen type identification (default: 70%)80
--skip-analysisSkip image analysistrue/false
--no-cacheIgnore cache and re-analyzetrue/false

Hierarchy Options (Optional)#

ParameterDescriptionExample
--initiativeCreate an Initiative-level issue (wraps the Project/Epic(s) as children)--initiative "2026 H2 ์ „๋žต ๋ชฉํ‘œ"
--parent-initiativeLink the created Project (or top-level Epic) to an existing Initiative issue (issue number)--parent-initiative 900
--projectCreate a Project-level issue and link the Epic(s) as children--project "์–ด๋“œ๋ฏผ ์ฝ˜์†” v2"
--parent-projectLink the Epic to an existing Project issue (issue number)--parent-project 1024
--epicsMultiple Epic names under one Project (comma-separated; default: single Epic)"auth,community,payment"

--project and --parent-project are mutually exclusive; so are --initiative and --parent-initiative. If none are given, the Epic is top-level (existing behavior). --initiative/--parent-initiative may be combined with --project/--parent-project (Initiative wraps Project) or used alone (Initiative wraps Epic directly, when no Project level is requested).

Other Options (Optional)#

ParameterDescriptionExample
--requirementsRequirements document path.claude/docs/community/requirements.md
--bdd-dirBDD scenario directory.claude/docs/community/bdd/
--labelsAdditional labels"sprint-1,mvp"
--screensScreens to generate"list,detail,form"
--pointsStory Point setting"3,3,5"
--sprintSprint assignment (current=ํ™œ์„ฑ/next=๋‹ค์Œ/์ˆซ์žยท์ด๋ฆ„)"current"
--start-dateEpic timeline start date (ISO YYYY-MM-DD). Default: ํ™œ์„ฑ ์Šคํ”„๋ฆฐํŠธ ์‹œ์ž‘ (or today)2026-06-16
--end-dateEpic timeline end date (ISO YYYY-MM-DD). Default: start + computed duration2026-07-14
--durationTimeline length in weeks (used when --end-date omitted). Default: auto from total points4
--no-sortSkip the priority review/pipeline sorting step (Step 5)true/false
--no-datesSkip timeline date setting (Epic created without a period)true/false

Workspace Info Query (required โ€” before Step 0)#

Issue Type ID, Repository ID, and Pipeline ID differ per workspace. Dynamically query based on the workspace configured in .mcp.json at the project root:

// 1. Repository ID + Pipeline ID
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const repoId = workspace.githubRepositories.find(r = >   /* GitHub ๋ ˆํฌ ์„ ํƒ */).id;

// 2. Issue Type ID (includes hierarchy level: lower = higher level)
const issueTypes = await mcp__zenhub__getIssueTypes({ repositoryId: repoId });
const initiativeType = issueTypes.find(t = >   t.name ===  " Initiative " );  // may be absent
const projectType = issueTypes.find(t = >   t.name ===  " Project " );  // may be absent
const epicTypeId = issueTypes.find(t = >   t.name ===  " Epic " ).id;
const featureTypeId = issueTypes.find(t = >   t.name ===  " Feature " ).id;
const subtaskTypeId = issueTypes.find(t = >   t.name ===  " Sub-task " ).id;

// Initiative type fallback: if --initiative given but type absent,
// warn the user and create the Project (or Epic, if no --project) as top level instead
if (useInitiativeLevel  & &   !initiativeType) {
  // โš ๏ธ  " ์ด ์›Œํฌ์ŠคํŽ˜์ด์Šค์—๋Š” Initiative Issue Type์ด ์—†์Šต๋‹ˆ๋‹ค. Project(๋˜๋Š” Epic)๋ฅผ ์ตœ์ƒ์œ„๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. " 
 }

// Project type fallback: if --project given but type absent,
// warn the user and create Epic(s) as top level instead
if (useProjectLevel  & &   !projectType) {
  // โš ๏ธ  " ์ด ์›Œํฌ์ŠคํŽ˜์ด์Šค์—๋Š” Project Issue Type์ด ์—†์Šต๋‹ˆ๋‹ค. Epic์„ ์ตœ์ƒ์œ„๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. " 
 }

Behavioral Flow#

Step 0: Image Analysis (when --images provided)#

Executed when --images or --images-dir parameter is provided.

0.1 Image Load

Supported formats: PNG, JPG, JPEG, WEBP Recommended size: Max 5MB/file, 1920x1080 or smaller recommended

# Specify individual files
--images  " list.png,detail.png,form.png " 

 # Specify directory (auto-filter supported formats)
--images-dir ./screenshots/

0.2 Screen Type Identification

Identify each image via Claude multimodal analysis:

ImageScreen TypeConfidenceKey Components
list.pngList95%AppBar, ListView, FAB
detail.pngDetail90%SliverAppBar, ContentSection
form.pngForm92%Form, TextField, Button

Screen Type Identification Criteria:

  • List: Multiple repeating cards/items, scrollable layout, FAB
  • Detail: Full info of single item, large image/gallery, action buttons
  • Form: Input fields (TextField, Dropdown, etc.), save/cancel buttons

Confidence threshold (--min-confidence, default: 70%):

  • Screens below threshold request manual user confirmation
  • e.g.: With --min-confidence 80, confidence below 80% needs confirmation

0.3 Entity Field Extraction

Infer Entity fields from UI elements in images:

entity:
  name: {EntityName}
  fields:
    - name: title
      type: String
      required: true
      ui_component: TextField
      validation:
        max_length: 100
      source_screen: form.png

    - name: content
      type: String
      required: true
      ui_component: TextArea
      validation:
        max_length: 5000
      source_screen: form.png

    - name: category
      type:  " {EntityName}Category " 
       required: true
      ui_component: Dropdown
      options: [general, notice, event]
      source_screen: form.png

    - name: imageUrls
      type:  " List < String > ? " 
       required: false
      ui_component: ImagePicker
      validation:
        max_count: 5
      source_screen: form.png

0.4 BDD Scenario Generation

Apply default BDD scenario templates based on screen type.

Language: BDD scenarios are generated in Korean (project convention).

List screen:

  • List loading success
  • Pull to refresh
  • Infinite scroll
  • Card tap โ†’ navigate to detail
  • Apply filter
  • Empty list

Detail screen:

  • Display detail info
  • Like toggle
  • Edit/delete
  • Go back

Form screen:

  • Valid form submission
  • Required field missing
  • Image attachment
  • Cancel creation

0.5 Requirements Document Generation

Save analysis results as markdown:

Path: .claude/docs/{feature_name}/requirements.md

# {Feature} Requirements Specification

 >   Auto-generated from image analysis

## Entity Definition

### {Entity}
| Field | Type | Required | Description |
|------|------|------|------|
| title | String | โœ… | Title |
| content | String | โœ… | Content |
...

## Screen Definition

### 1. List Screen (list.png)
- Components: AppBar, ListView, FAB
- Actions: Card tap โ†’ navigate to detail, FAB tap โ†’ create
...

0.6 Image Save and URL Generation (with --attach-images true)

Default: --attach-images is disabled (false) by default. You must explicitly specify --attach-images true to commit images to the repo.

Save images to repo and generate GitHub raw URLs:

โš ๏ธ Caution: Pushes directly to the current branch. May fail for protected branches (main/development).

User confirmation prompt:

๐Ÿ–ผ๏ธ ์ด๋ฏธ์ง€๋ฅผ repo์— commitํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

- ๋Œ€์ƒ ํŒŒ์ผ: list.png, detail.png, form.png
- ์ €์žฅ ๊ฒฝ๋กœ: .claude/docs/{feature}/screenshots/
- ํ˜„์žฌ ๋ธŒ๋žœ์น˜: {current_branch}

**๊ณ„์†ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? (y/N)**
# 1. Copy images to .claude/docs
cp {input_images} .claude/docs/{feature}/screenshots/

# 2. Add to Git (current branch)
git add .claude/docs/{feature}/screenshots/
git commit -m  " docs: ๐Ÿ“ธ {feature} ์Šคํฌ๋ฆฐ์ƒท ์ถ”๊ฐ€ " 
 git push origin HEAD

# 3. Generate GitHub raw URLs
# https://raw.githubusercontent.com/{owner}/{repo}/{branch}/.claude/docs/{feature}/screenshots/{image}

Protected Branch Handling:

  • Recommend running from feature branch
  • If push fails, proceed without image URLs (use local paths)

0.7 User Confirmation

## ๐Ÿ“ธ ์ด๋ฏธ์ง€ ๋ถ„์„ ๊ฒฐ๊ณผ

### ์‹๋ณ„๋œ ํ™”๋ฉด
| # | ์ด๋ฏธ์ง€ | ํ™”๋ฉด ํƒ€์ž… | ์ปดํฌ๋„ŒํŠธ ์ˆ˜ |
|---|--------|----------|-----------|
| 1 | list.png | List | 5 |
| 2 | detail.png | Detail | 4 |
| 3 | form.png | Form | 6 |

### ์ถ”์ถœ๋œ Entity ํ•„๋“œ
| ํ•„๋“œ | ํƒ€์ž… | ํ•„์ˆ˜ | ์ถœ์ฒ˜ |
|------|------|------|------|
| title | String | โœ… | form.png |
| content | String | โœ… | form.png |
| category | Enum | โœ… | form.png |

### ์ƒ์„ฑํ•  BDD ์‹œ๋‚˜๋ฆฌ์˜ค
- ๋ชฉ๋ก: 8๊ฐœ
- ์ƒ์„ธ: 6๊ฐœ
- ํผ: 7๊ฐœ

**๋ถ„์„ ๊ฒฐ๊ณผ๊ฐ€ ์ •ํ™•ํ•ฉ๋‹ˆ๊นŒ? (Y/n)**

0.8 Error Handling

SituationHandling
Image file not foundOutput โŒ File not found: {path} and exit
Unsupported formatOnly PNG, JPG, JPEG, WEBP supported. Other formats ignored with warning
Git push failureProceed without image URLs, use local paths (show warning)
Analysis confidence < thresholdRequest manual user confirmation: โš ๏ธ Confidence {n}% - please verify screen type
No images in directoryOutput โš ๏ธ No supported images in directory: {path} and exit
Entity field extraction failureProceed with empty fields, request manual input from user

Step 1: Load Requirements#

Priority:

  1. Requirements generated in Step 0 (when using --images)
  2. File specified via --requirements
  3. Default path: .claude/docs/{feature}/requirements.md
## ์š”๊ตฌ์‚ฌํ•ญ ๋กœ๋“œ

1. .claude/docs/{feature}/requirements.md ์ฝ๊ธฐ
2. BDD ์‹œ๋‚˜๋ฆฌ์˜ค ํŒŒ์ผ๋“ค ์ฝ๊ธฐ (์žˆ๋Š” ๊ฒฝ์šฐ)
3. Entity ํ•„๋“œ ์ •์˜ ์ถ”์ถœ
4. ํ™”๋ฉด ์ •์˜ ์ถ”์ถœ

Step 1.5: Priority Review (before creation)#

โš ๏ธ updateIssue cannot change labels โ€” priority labels must be decided before issue creation.

Score every issue to be created (Epic/Story/Sub-task) and assign a tier per rules/zenhub-conventions.md โ†’ Priority Review and Pipeline Sorting:

AxisQuestion
DependencyDo other Stories depend on this? (Entity/API foundation = P0)
Business valueCore user path of the Epic?
RiskTechnically uncertain โ†’ earlier
EffortAmong equals, smaller points first

Matrix(impactร—effort) ์‹ ํ˜ธ ์˜์†ํ™” (C6): effort ๋Š” setIssueEstimate(Story Point)๋กœ, impact ๋Š” ๋ณ„๋„ ๋ผ๋ฒจ impact-high|impact-med|impact-low ๋กœ ์ €์žฅํ•œ๋‹ค(๋ผ๋ฒจ ๋ถˆ๋ณ€ โ†’ ์ƒ์„ฑ ์‹œ ํ™•์ •). impact = Business value + Dependency + Risk (effort ์ œ์™ธ โ€” effort ๋ฅผ impact ์— ์„ž์œผ๋ฉด ZenHub Matrix ์—์„œ ์ด์ค‘ ๊ณ„์‚ฐ๋œ๋‹ค). P-tier ์™€ ๋…๋ฆฝ๋œ ์ถ•์ด๋ฉฐ, ์ด๊ฑธ ์ฑ„์›Œ์•ผ Matrix Y์ถ•์ด ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š”๋‹ค.

## ๐Ÿ”ข ์šฐ์„ ์ˆœ์œ„ ๊ฒ€ํ†  ๊ฒฐ๊ณผ

| ์ˆœ์œ„ | ์ด์Šˆ | ํ‹ฐ์–ด | impact | ๊ทผ๊ฑฐ |
|------|------|------|--------|------|
| 1 | {feature} ๋ชฉ๋ก ํ™”๋ฉด | P0 | high | ์ƒ์„ธ/ํผ ํ™”๋ฉด์ด ๋ชฉ๋ก Entity์— ์˜์กด(value+dependency ๋†’์Œ) |
| 2 | {feature} ์ƒ์„ธ ํ™”๋ฉด | P1 | med | ํ•ต์‹ฌ ๊ฒฝ๋กœ, ์˜์กด ์ด์Šˆ ์—†์Œ |
| 3 | {feature} ํผ ํ™”๋ฉด | P1 | low | ํ•ต์‹ฌ ๊ฒฝ๋กœ |

**์ด ์šฐ์„ ์ˆœ์œ„๋กœ ์ง„ํ–‰ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? (Y/n)**

Confirmed tiers become p0/p1/p2 and impact-high|med|low labels passed to createGitHubIssue (both immutable post-creation), and the table is embedded in the Epic (or Project) body.

Step 1.6: Initiative Creation (with --initiative)#

Create the Initiative-level issue first, one level above Project; the Project (or, if no --project, the Epic directly) is linked as its child.

const initiative = await mcp__zenhub__createGitHubIssue({
  title:  " {initiative_title} " ,
  body:  " {initiative_body_template} " ,   // strategic goal, wrapped Project/Epic list
  repositoryId: repoId,
  issueTypeId: initiativeType.id,
  labels: [ " initiative " ,  " p{priority} " ]
});

With --parent-initiative {issue_number}, query the existing issue via searchLatestIssues and use its GraphQL ID instead of creating a new one.

Step 1.7: Project Creation (with --project)#

Create the Project-level issue first; Epics are linked as children.

const project = await mcp__zenhub__createGitHubIssue({
  title:  " {project_title} " ,
  body:  " {project_body_template} " ,   // goals, Epic list, priority table
  repositoryId: repoId,
  issueTypeId: projectType.id,
  parentIssueId: initiative?.id, // when --initiative/--parent-initiative is used
  labels: [ " project " ,  " p{priority} " ]
});

With --parent-project {issue_number}, query the existing issue via searchLatestIssues and use its GraphQL ID as the parent instead of creating a new one.

When --initiative/--parent-initiative is used without --project, link the Epic directly to the Initiative instead (parentIssueId: initiative.id on the Epic in Step 2).

Step 2: Epic Creation#

MCP call example:

mcp__zenhub__createGitHubIssue({
  title:  " {feature} ๊ธฐ๋Šฅ ๊ตฌํ˜„ " ,
  body:  " {epic_body_template} " ,
  repositoryId: repoId,      // getWorkspacePipelinesAndRepositories()์—์„œ ์กฐํšŒ
  issueTypeId: epicTypeId,   // getIssueTypes()์—์„œ ์กฐํšŒ
  parentIssueId: project?.id ?? initiative?.id, // --project/--parent-project ์šฐ์„ , ์—†์œผ๋ฉด --initiative/--parent-initiative ์ง์ ‘ ์—ฐ๊ฒฐ
  labels: [ " epic " ,  " feature " ,  " {feature_name} " ,  " p{priority} " ]
})

Per rules/zenhub-conventions.md, always use createGitHubIssue โ€” createZenhubIssue is prohibited (ZenHub-native issues cannot move pipelines or set timelines).

Step 2.5: Epic Timeline + Estimate (required โ€” skipped only with --no-dates)

โš ๏ธ Without this step the Epic never appears on the Goals & Planning timeline. setIssueEstimate controls SP; setDatesForIssue controls the timeline period. Setting SP alone (the previous behavior) leaves startDate/endDate null, so the Epic shows points but no bar on the roadmap. Always set both.

// 1) Organization ID (required by setDatesForIssue)
const orgId = workspace.zenhubOrganization.id;

// 2) Compute the timeline window
//    ์‹œ์ž‘: ๋ช…์‹œ ํ”Œ๋ž˜๊ทธ  >   --sprint ์…€๋ ‰ํ„ฐ ์Šคํ”„๋ฆฐํŠธ ์‹œ์ž‘  >   ์˜ค๋Š˜
//    โš ๏ธ getUpcomingSprint ๋Š”  ' ๋‹ค์Œ '   ์Šคํ”„๋ฆฐํŠธ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์“ฐ๋ฉด Epic ๋ฐ”๊ฐ€ ํ•œ ์Šคํ”„๋ฆฐํŠธ ๋ฐ€๋ฆฐ๋‹ค.
//       ๊ธฐ๋ณธ(current)์€ getSprint()(id ์—†์Œ=ํ™œ์„ฑ)๋ฅผ ์“ด๋‹ค.
const kickoffSprint = options.sprint ===  " next " 
   ? await mcp__zenhub__getUpcomingSprint()
  : await mcp__zenhub__getSprint();                        // ๊ธฐ๋ณธ current = ํ™œ์„ฑ ์Šคํ”„๋ฆฐํŠธ
const startDate =
  options.startDate ??
  kickoffSprint?.startAt?.slice(0, 10) ??
  todayISO();                                              //  " YYYY-MM-DD " 

 // Default duration auto-derived from total Story Points when --duration/--end-date omitted.
// Heuristic: ~5 points โ‰ˆ one 2-week sprint (min 2 weeks, rounded up to whole weeks).
const totalPoints = stories.reduce((s, x) = >   s + x.point, 0);
const weeks = options.duration ?? Math.max(2, Math.ceil(totalPoints / 5) * 2);
const endDate = options.endDate ?? addWeeksISO(startDate, weeks);

// 3) Set the Epic timeline (THIS is what was missing) โ€” unless --no-dates
if (!options.noDates) {
  await mcp__zenhub__setDatesForIssue({
    issueId: epic.id,
    startDate,                 //  " YYYY-MM-DD " 
     endDate,                   //  " YYYY-MM-DD " 
     zenhubOrganizationId: orgId,
  });
}

// 4) Set the Epic estimate (roll-up of child Story Points)
await mcp__zenhub__setIssueEstimate({
  issueId: epic.id,
  estimate: totalPoints,
});

Verification: after the call, re-query the issue and confirm startDate/endDate are non-null. If setDatesForIssue fails (e.g. missing zenhubOrganizationId), surface the error โ€” do not silently continue, or the Epic stays off the timeline.

## Epic ์ƒ์„ฑ ํ™•์ธ

**์ œ๋ชฉ**: {feature} ๊ธฐ๋Šฅ ๊ตฌํ˜„

**๋‚ด์šฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ**:
---
# Epic: {Feature} ๊ธฐ๋Šฅ ๊ตฌํ˜„

## ๐Ÿ“‹ ๊ฐœ์š”
{feature_description}

## ๐Ÿ’ผ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜
**์‚ฌ์šฉ์ž๋กœ์„œ**, {capability}์„(๋ฅผ) ์›ํ•ฉ๋‹ˆ๋‹ค.
**๊ทธ๋ž˜์„œ** {value}์„(๋ฅผ) ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## ๐Ÿ“Š ๋ฒ”์œ„
- โœ… ๋ชฉ๋ก ํ™”๋ฉด
- โœ… ์ƒ์„ธ ํ™”๋ฉด
- โœ… ํผ ํ™”๋ฉด

## ๐Ÿ› ๏ธ ๊ธฐ์ˆ  ๋…ธํŠธ
| ํ•ญ๋ชฉ | ๊ฐ’ |
|------|-----|
| Entity | `{EntityName}` |
| Backend | Serverpod endpoint |
| Caching | SWR |
---

**๋ผ๋ฒจ**: epic, feature, {feature_name}, kobic

**๐Ÿ“… ํƒ€์ž„๋ผ์ธ**: {start_date} ~ {end_date} ({weeks}์ฃผ)  โ† Goals  &   Planning ๋กœ๋“œ๋งต์— ํ‘œ์‹œ๋จ
**๐Ÿ“ Story Point (๋กค์—…)**: {total_points}

**์ƒ์„ฑํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? (Y/n)**

ํƒ€์ž„๋ผ์ธ์„ ๋น„์›Œ๋‘๋ ค๋ฉด --no-dates, ๊ธฐ๊ฐ„์„ ์ง์ ‘ ์ง€์ •ํ•˜๋ ค๋ฉด --start-date/--end-date ๋˜๋Š” --duration ์‚ฌ์šฉ.

Step 3: Story Creation#

Create per-screen Stories after confirmation:

MCP call example (repeated per screen):

mcp__zenhub__createGitHubIssue({
  title:  " {feature} {screen} ํ™”๋ฉด " ,
  body:  " {story_body_template} " ,
  repositoryId: repoId,         // getWorkspacePipelinesAndRepositories()์—์„œ ์กฐํšŒ
  issueTypeId: featureTypeId,   // getIssueTypes()์—์„œ ์กฐํšŒ
  parentIssueId:  " {epic_id} " ,                                    // Epic๊ณผ ์—ฐ๊ฒฐ
  labels: [ " story " ,  " {feature_name} " ,  " {screen_type}-view " ,  " p{priority} " ,  " impact-{impact} " ]  // impact: high|med|low (Matrix Y์ถ•, C6)
})

// effort ์ถ•: Story Point ์„ค์ • (Matrix X์ถ•)
await mcp__zenhub__setIssueEstimate({ issueId: story.id, estimate: story.point });

// โš ๏ธ Story ํƒ€์ž„๋ผ์ธ: setDatesForIssue ๋Š” ์ƒ์œ„ ํƒ€์ž…(Epic/Project) ์ „์šฉ์ด๋ฏ€๋กœ Story ์—๋Š” ์“ฐ์ง€ ์•Š๋Š”๋‹ค(off-spec).
//   Roadmap Visibility Contract(rules/zenhub-conventions.md)๋Œ€๋กœ Story ๋Š” **์Šคํ”„๋ฆฐํŠธ ๋ฉค๋ฒ„์‹ญ**์œผ๋กœ ๋…ธ์ถœํ•œ๋‹ค โ€”
//   --sprint ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด Step 5 ์—์„œ addIssuesToSprints ๋กœ ํ•ด๋‹น ์Šคํ”„๋ฆฐํŠธ ๋ ˆ์ธ์— ์˜ฌ๋ฆฐ๋‹ค.
//   ์ฆ‰ Story ์˜ ๋กœ๋“œ๋งต ๊ฐ€์‹œ์„ฑ = ๋ถ€๋ชจ Epic ์˜ ๊ธฐ๊ฐ„ ๋ฐ” + ์ž์‹ ์˜ ์Šคํ”„๋ฆฐํŠธ ๋ ˆ์ธ.

Story ๋Š” ๊ฐœ๋ณ„ ๋‚ ์งœ ๋Œ€์‹  ์Šคํ”„๋ฆฐํŠธ ๋ ˆ์ธ์œผ๋กœ ํƒ€์ž„๋ผ์ธ์— ๋…ธ์ถœ๋œ๋‹ค. Epic ๋งŒ ๋ช…์‹œ์  ๊ธฐ๊ฐ„(start/end)์„ ๊ฐ–๋Š”๋‹ค. ์ •๋ฐ€ ์ผ์ •์€ ZenHub ๋ณด๋“œ์—์„œ ๋“œ๋ž˜๊ทธ๋กœ ๋ฏธ์„ธ ์กฐ์ •ํ•˜์„ธ์š”.

## Story ์ƒ์„ฑ

| # | Screen | Title | Point | Timeline | Acceptance Criteria Count |
|---|------|------|-------|----------|-------|
| 1 | List | {feature} ๋ชฉ๋ก ํ™”๋ฉด | 3 | {s1_start}~{s1_end} | 8 |
| 2 | Detail | {feature} ์ƒ์„ธ ํ™”๋ฉด | 3 | {s2_start}~{s2_end} | 9 |
| 3 | Form | {feature} ํผ ํ™”๋ฉด | 5 | {s3_start}~{s3_end} | 10 |

**Total Stories**: 3
**Total Points**: 11
**Epic Timeline**: {epic_start} ~ {epic_end}

Step 3.5: Sub-task Creation (Optional)#

Create detailed tasks as Sub-tasks under Stories.

MCP call example:

mcp__zenhub__createGitHubIssue({
  title:  " [{PREFIX}-00X-0Y] {task_description} " ,
  body:  " {subtask_body} " ,
  repositoryId: repoId,         // getWorkspacePipelinesAndRepositories()์—์„œ ์กฐํšŒ
  issueTypeId: subtaskTypeId,   // getIssueTypes()์—์„œ ์กฐํšŒ
  parentIssueId:  " {story_id} " ,                                   // Story์™€ ์—ฐ๊ฒฐ
  labels: [ " subtask " ,  " {feature_name} " ,  " p{priority} " ]
})

Auto-generated Sub-tasks by screen type:

Screen TypeSub-task List
ListTable column definition, search, filter, sort, pagination
DetailData display, action buttons, edit/delete confirmation
FormField validation, form submission, cancel handling, image upload

Sub-task title format:

  • [{PREFIX}-001-01] : First Sub-task of Story 001
  • [{PREFIX}-001-02] : Second Sub-task of Story 001
  • PREFIX is based on feature_name (e.g., AUTH, INST, BOOK)

Step 4: Hierarchy Linking (Project-Epic-Story)#

## ์—ฐ๊ฒฐ ์™„๋ฃŒ

โœ… Project #{project_number} ์ƒ์„ฑ ์™„๋ฃŒ (--project ์‚ฌ์šฉ ์‹œ)
โœ… Epic #{epic_number} ์ƒ์„ฑ ์™„๋ฃŒ (Project์— ์—ฐ๊ฒฐ๋จ)
โœ… Story #{story_1} ์—ฐ๊ฒฐ๋จ
โœ… Story #{story_2} ์—ฐ๊ฒฐ๋จ
โœ… Story #{story_3} ์—ฐ๊ฒฐ๋จ

### ์ƒ์„ฑ๋œ ์ด์Šˆ ๋งํฌ
- Project: https://github.com/cocode/kobic/issues/{project_number}
- Epic: https://github.com/cocode/kobic/issues/{epic_number}
- ๋ชฉ๋ก: https://github.com/cocode/kobic/issues/{story_1}
- ์ƒ์„ธ: https://github.com/cocode/kobic/issues/{story_2}
- ํผ: https://github.com/cocode/kobic/issues/{story_3}

Step 5: Pipeline Sorting (skipped with --no-sort)#

Place every created issue into its pipeline based on the Step 1.5 priority tiers. Placement matrix follows rules/zenhub-conventions.md:

TargetPipeline
Project / EpicProduct Backlog
Story P0 (with --sprint)Sprint Backlog + addIssuesToSprints
Story P0/P1 (no sprint)Product Backlog
Story P2Icebox
Sub-taskFollows parent Story (no separate move)
// fail-closed ํ•ด์„: ์ด๋ฆ„์ด ๋ผ์ด๋ธŒ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ๋‹ค๋ฅด๋ฉด throw (๋ถ€๋ถ„ ๋ฐฐ์น˜ ํ›„ ๋ฌด์Œ ์ค‘๋‹จ ๋ฐฉ์ง€)
const pipelineByName = (name) = >   {
  const p = workspace.pipelines.find(p = >   p.name === name);
  if (!p) throw new Error(`ํŒŒ์ดํ”„๋ผ์ธ  ' ${name} '   ์—†์Œ. ๋ผ์ด๋ธŒ: ${workspace.pipelines.map(p = >   p.name).join( " ,  " )}`);
  return p;
};
const backlog = pipelineByName( " Product Backlog " );
const sprintBacklog = pipelineByName( " Sprint Backlog " );
const icebox = pipelineByName( " Icebox " );

// โš ๏ธ moveIssueToPipeline has no position param โ€”
// move in DESCENDING priority order (P0 first) to approximate top-to-bottom ordering
for (const issue of issuesSortedByPriority) {
  await mcp__zenhub__moveIssueToPipeline({
    issueId: issue.id,
    pipelineId: pipelineFor(issue),  // matrix above
  });
}

// --sprint ์‚ฌ์šฉ ์‹œ P0 Story๋ฅผ ํ•ด๋‹น ์Šคํ”„๋ฆฐํŠธ์— ์ถ”๊ฐ€
if (options.sprint) {
  // ์…€๋ ‰ํ„ฐ (rules/zenhub-conventions.md โ†’  " Sprint Selector Resolution "   ์™€ ๋™์ผ ๊ทœ์น™):
  //   current โ†’ ํ™œ์„ฑ(getSprint, id ์—†์Œ) ยท next โ†’ ๋‹ค์Œ(getUpcomingSprint) ยท ์ˆซ์ž/์ด๋ฆ„ โ†’ listRecentSprints ๋งค์นญ
  const targetSprint =
    options.sprint ===  " next "      ? await mcp__zenhub__getUpcomingSprint() :
    options.sprint ===  " current "   ? await mcp__zenhub__getSprint()         :
    (await mcp__zenhub__listRecentSprints()).openSprints
      .find(s = >   s.name.includes(String(options.sprint)));
  if (!targetSprint?.id) throw new Error(`์Šคํ”„๋ฆฐํŠธ  ' ${options.sprint} '   ํ•ด์„ ์‹คํŒจ โ€” current/next/๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•˜๋ผ`);
  await mcp__zenhub__addIssuesToSprints({
    issueIds: p0StoryIds,
    sprintIds: [targetSprint.id],
  });
}
## ํŒŒ์ดํ”„๋ผ์ธ ์ •๋ ฌ ์™„๋ฃŒ

| ์ด์Šˆ | ํ‹ฐ์–ด | ํŒŒ์ดํ”„๋ผ์ธ |
|------|------|-----------|
| Epic #{epic_number} | โ€” | Product Backlog |
| #{story_1} ๋ชฉ๋ก ํ™”๋ฉด | P0 | Sprint Backlog (Sprint 12) |
| #{story_2} ์ƒ์„ธ ํ™”๋ฉด | P1 | Product Backlog |
| #{story_3} ํผ ํ™”๋ฉด | P1 | Product Backlog |

 >   ํŒŒ์ดํ”„๋ผ์ธ ๋‚ด ์„ธ๋ถ€ ์ˆœ์„œ๋Š” MCP๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
 >   ์šฐ์„ ์ˆœ์œ„ ์ˆœ์„œ๋Œ€๋กœ ์ด๋™ํ–ˆ์œผ๋ฉฐ, ๋ฏธ์„ธ ์กฐ์ •์€ ZenHub ๋ณด๋“œ์—์„œ ๋“œ๋ž˜๊ทธ๋กœ ์กฐ์ •ํ•˜์„ธ์š”.

Output Files#

.claude/docs/{feature_name}/
โ”œโ”€โ”€ screenshots/              # ์ด๋ฏธ์ง€ ๋ถ„์„ ์‹œ ์ €์žฅ (--images ์‚ฌ์šฉ ์‹œ)
โ”‚   โ”œโ”€โ”€ list.png
โ”‚   โ”œโ”€โ”€ detail.png
โ”‚   โ””โ”€โ”€ form.png
โ”œโ”€โ”€ image_analysis.md         # ์ด๋ฏธ์ง€ ๋ถ„์„ ๊ฒฐ๊ณผ (--images ์‚ฌ์šฉ ์‹œ)
โ”œโ”€โ”€ requirements.md           # ์š”๊ตฌ์‚ฌํ•ญ (์ž๋™ ์ƒ์„ฑ ๋˜๋Š” ๊ธฐ์กด ํŒŒ์ผ)
โ”œโ”€โ”€ bdd/                      # BDD ์‹œ๋‚˜๋ฆฌ์˜ค (์ž๋™ ์ƒ์„ฑ)
โ”‚   โ”œโ”€โ”€ {feature}_list.feature
โ”‚   โ”œโ”€โ”€ {feature}_detail.feature
โ”‚   โ””โ”€โ”€ {feature}_form.feature
โ””โ”€โ”€ zenhub/
    โ”œโ”€โ”€ project.md            # Project ์ƒ์„ธ ์ •๋ณด (--project ์‚ฌ์šฉ ์‹œ)
    โ”œโ”€โ”€ epic.md               # Epic ์ƒ์„ธ ์ •๋ณด
    โ”œโ”€โ”€ priority.md           # ์šฐ์„ ์ˆœ์œ„ ๊ฒ€ํ†  ๊ฒฐ๊ณผ + ํŒŒ์ดํ”„๋ผ์ธ ๋ฐฐ์น˜ ๊ธฐ๋ก
    โ””โ”€โ”€ stories/
        โ”œโ”€โ”€ list_story.md     # ๋ชฉ๋ก Story ์ •๋ณด
        โ”œโ”€โ”€ detail_story.md   # ์ƒ์„ธ Story ์ •๋ณด
        โ””โ”€โ”€ form_story.md     # ํผ Story ์ •๋ณด

Epic Template#

# Epic: {Feature} ๊ธฐ๋Šฅ ๊ตฌํ˜„

## ๐Ÿ“‹ ๊ฐœ์š”
{Feature์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•œ ์„ค๋ช…}

## ๐Ÿ’ผ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜
**์‚ฌ์šฉ์ž๋กœ์„œ**, {feature_capability}์„(๋ฅผ) ์›ํ•ฉ๋‹ˆ๋‹ค.
**๊ทธ๋ž˜์„œ** {business_value}์„(๋ฅผ) ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## ๐Ÿ“Š ๋ฒ”์œ„

### ํฌํ•จ
- โœ… {screen_1} ํ™”๋ฉด
- โœ… {screen_2} ํ™”๋ฉด
- โœ… {screen_3} ํ™”๋ฉด

### ์ œ์™ธ
- โŒ (ํ•„์š”์‹œ ๋ช…์‹œ)

## ๐Ÿ› ๏ธ ๊ธฐ์ˆ  ๋…ธํŠธ
| ํ•ญ๋ชฉ | ๊ฐ’ |
|------|-----|
| Entity | `{EntityName}` |
| Backend | Serverpod endpoint |
| Caching | {SWR / Cache-First} |
| Location | `feature/{location}/{feature_name}` |

## ๐ŸŽจ ๋””์ž์ธ ์Šคํฌ๋ฆฐ์ƒท

 >   `--images` ์‚ฌ์šฉ ์‹œ ์ž๋™ ์ƒ์„ฑ๋จ

### ๋ชฉ๋ก ํ™”๋ฉด
![๋ชฉ๋ก ํ™”๋ฉด](https://raw.githubusercontent.com/{owner}/{repo}/{branch}/.claude/docs/{feature}/screenshots/list.png)

### ์ƒ์„ธ ํ™”๋ฉด
![์ƒ์„ธ ํ™”๋ฉด](https://raw.githubusercontent.com/{owner}/{repo}/{branch}/.claude/docs/{feature}/screenshots/detail.png)

### ํผ ํ™”๋ฉด
![ํผ ํ™”๋ฉด](https://raw.githubusercontent.com/{owner}/{repo}/{branch}/.claude/docs/{feature}/screenshots/form.png)

 >   ๋˜๋Š” Figma ๋งํฌ: {figma_urls}

## ๐Ÿ“Ž ๊ด€๋ จ Story
- [ ] #{story_1_number} - ๋ชฉ๋ก ํ™”๋ฉด
- [ ] #{story_2_number} - ์ƒ์„ธ ํ™”๋ฉด
- [ ] #{story_3_number} - ํผ ํ™”๋ฉด

---
 >   ๐Ÿค– Generated by `/zenhub:epic`

Story Template#

# Story: {Screen Name}

## ๐Ÿ“‹ ์‚ฌ์šฉ์ž ์Šคํ† ๋ฆฌ
**{user_type}๋กœ์„œ**, {screen_capability}์„(๋ฅผ) ์›ํ•ฉ๋‹ˆ๋‹ค.
**๊ทธ๋ž˜์„œ** {value}์„(๋ฅผ) ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## โœ… ์ธ์ˆ˜ ๊ธฐ์ค€ (Acceptance Criteria)

### AC1: {scenario_1_name}
gherkin

Given {precondition_1} When {action_1} Then {expected_result_1}

- **Priority**: {High/Medium/Low}
- **Tag**: @{tag}

### AC2: {scenario_2_name}
gherkin

Given {precondition_2} When {action_2} Then {expected_result_2}

- **Priority**: {High/Medium/Low}
- **Tag**: @{tag}

## ๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์ž‘์—…

### Backend
- [ ] Serverpod endpoint ๊ตฌํ˜„
- [ ] DTO ์ •์˜

### Domain
- [ ] Entity ์ •์˜
- [ ] Repository Interface ์ •์˜
- [ ] UseCase ๊ตฌํ˜„
- [ ] UseCase ํ…Œ์ŠคํŠธ ์ž‘์„ฑ

### Data
- [ ] Repository ๊ตฌํ˜„
- [ ] Serverpod Mixin ๊ตฌํ˜„
- [ ] ์บ์‹ฑ ์ „๋žต ์ ์šฉ

### Presentation
- [ ] BLoC ๊ตฌํ˜„ (Event/State)
- [ ] Page ์œ„์ ฏ ๊ตฌํ˜„
- [ ] Widget ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„
- [ ] Route ๋“ฑ๋ก
- [ ] BDD ํ…Œ์ŠคํŠธ ์ž‘์„ฑ

### Widgetbook
- [ ] Component story ์ถ”๊ฐ€

## ๐ŸŽจ ๋””์ž์ธ ์ฐธ์กฐ

 >   `--images` ์‚ฌ์šฉ ์‹œ ์ž๋™ ์ƒ์„ฑ๋จ

![{screen_name}](https://raw.githubusercontent.com/{owner}/{repo}/{branch}/.claude/docs/{feature}/screenshots/{screen}.png)

 >   ๋˜๋Š” Figma ๋งํฌ: {figma_link}

## ๐Ÿ“ ์˜ˆ์ƒ Story Point
{point_value}

---
 >   ๐Ÿค– Generated by `/zenhub:epic`
 >   ๐Ÿ“Ž Epic: #{epic_number}

MCP Integration#

TaskMCP ServerPurpose
Issue creationZenHubEpic/Story creation
Template structuringSequentialSystematic issue organization

Examples#

Basic Usage#

/zenhub:epic community Post

Project Level Creation (new)#

# Create new Project + Epics under it
/zenhub:epic community Post --project  " ์–ด๋“œ๋ฏผ ์ฝ˜์†” v2 " 

 # Multiple Epics under one Project
/zenhub:epic --project  " ์–ด๋“œ๋ฏผ ์ฝ˜์†” v2 "   --epics  " auth,community,payment " 

 # Link Epic to an existing Project issue
/zenhub:epic community Post --parent-project 1024

Specify Requirements File#

/zenhub:epic community Post \
  --requirements .claude/docs/community/requirements.md \
  --bdd-dir .claude/docs/community/bdd/

Specify Sprint and Labels#

/zenhub:epic community Post \
  --labels  " sprint-1,mvp "   \
  --sprint current

Custom Story Points#

/zenhub:epic community Post \
  --screens  " list,detail,form "   \
  --points  " 5,3,8 "

Create Epic from Image Files (new)#

/zenhub:epic community Post \
  --images  " list.png,detail.png,form.png "

Create Epic from Image Directory#

/zenhub:epic community Post \
  --images-dir ./screenshots/community/

Images + Additional Options#

/zenhub:epic community Post \
  --images  " list.png,detail.png,form.png "   \
  --labels  " sprint-1,mvp "   \
  --sprint current

Analysis Only Without Image Attachment#

/zenhub:epic community Post \
  --images  " list.png,detail.png,form.png "   \
  --attach-images false

Reference Agent#

Detailed implementation rules: ${CLAUDE_PLUGIN_ROOT}/commands/agents/zenhub-integration-agent.md

Key Rules#

  1. Top-Down Creation: Create in hierarchy order โ€” Initiative (optional) โ†’ Project (optional) โ†’ Epic โ†’ Story โ†’ Sub-task
  2. Link Required: All Stories must be linked to Epic; Epics link to Project when --project/--parent-project is used (or directly to Initiative when --initiative/--parent-initiative is used without a Project); Projects link to Initiative when both are used
  3. GitHub Issues Only: Always use createGitHubIssue (createZenhubIssue prohibited โ€” see rules/zenhub-conventions.md)
  4. Priority Before Creation: Run the Step 1.5 priority review first โ€” labels (p0/p1/p2) cannot be changed after creation
  5. Timeline Required (Step 2.5): Always set both setIssueEstimate (SP) and setDatesForIssue (start/end) on the Epic โ€” SP alone leaves the Epic off the Goals & Planning roadmap. Skip only with --no-dates. setDatesForIssue requires zenhubOrganizationId
  6. Pipeline Sorting Required: After creation, always place issues per the priority โ†’ pipeline matrix (Step 5), moving in descending priority order
  7. Include Acceptance Criteria: Include BDD-based Acceptance Criteria in each Story
  8. Label Consistency: Follow the defined label system
  9. Create After Confirmation: Create actual issues only after user confirmation
  10. Documentation: Save creation results to .claude/docs (including priority.md)
  11. Image Analysis: Detailed analysis via Claude multimodal when using --images
  12. Image Attachment: On --attach-images true, commit to repo after user confirmation to attach URLs to Issues
  13. BDD Language: Auto-generated BDD scenarios are written in Korean