user-scope-skills/jira-dispatch/SKILL.md
Use when "/jira:dispatch", "서브태스크 생성", "지라 태스크 생성", "jira dispatch", "jira subtask", "create subtasks", "태스크 디스패치", "이 태스크들 지라에 올려줘", "서브태스크 만들어줘". Also use as the final step after /jira:assess completes.
npx skillsauth add onejaejae/skills jira-dispatchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scope 리포트(specs/{KEY}-scope.md)의 Section 6 (Task Definition Candidates)을 파싱하여
사용자 확인 후 Jira REST API로 직접 서브태스크를 일괄 생성한다.
Phase 0: Parse & Validate (소스 파싱 + 인증 + 중복 체크)
Phase 1: Task Preview + Confirm (사용자 확인)
Phase 2: Sequential Creation (REST API로 서브태스크 생성)
Phase 3: Report (결과 보고)
티켓 키 추출: 입력에서 부모 Jira 키를 파싱한다.
https://khc.atlassian.net/browse/DPHRS-8 → DPHRS-8DPHRS-8 → DPHRS-8([A-Z][A-Z0-9]+-\d+)태스크 소스 로드: 두 가지 소스를 순서대로 시도한다.
~/.claude/specs/{KEY}-scope.md 파일의 Section 6/jira:assess {KEY}를 실행해주세요."마크다운 테이블 파싱: Section 6의 테이블에서 태스크를 추출한다.
기대 형식:
| # | Task | Priority | Assignee | Dependencies | Effort | DoD |
|---|------|----------|----------|-------------|--------|-----|
| 1 | {title} | HIGH | - | - | 5h | {dod} |
각 행에서:
#: 태스크 번호Task: 서브태스크 제목Priority: HIGH → High, MED → Medium, LOW → Low, 기타 → MediumAssignee: - 이면 기본 담당자(현재 사용자) 사용Dependencies: 의존 태스크 번호 (Jira description에 포함)Effort: 공수 추정 (Jira description에 포함)DoD: 완료 기준 (Jira description에 포함). 비어있으면 "{title}이 정상 동작함" 기본값.Jira 인증 확인 (REST API): jira CLI의 config에서 인증 정보를 추출한다:
# jira CLI config에서 서버/로그인 정보 확인
cat ~/.config/.jira/.config.yml
필요 정보:
server: Jira 서버 URL (예: https://khc.atlassian.net)login: 이메일 (예: [email protected])JIRA_API_TOKEN (config 파일에는 없음)Auth 토큰 구성 (반드시 이 순서로):
login을 읽고, JIRA_API_TOKEN 환경변수에서 토큰을 가져온다server="${server%/}" (이중 슬래시 방지)echo -n "{login}:${JIRA_API_TOKEN}" | base64{auth_token}으로 사용인증 테스트:
curl -s "https://{server}/rest/api/2/myself" \
-H "Authorization: Basic {auth_token}" \
-H "Content-Type: application/json"
accountId와 displayName 캡처jira init을 실행해주세요."현재 사용자 account ID 확인:
REST API /rest/api/2/myself 응답에서:
accountId: 서브태스크 assignee에 사용 (예: 712020:bbef064a-b726-40d1-9e80-71ea963b7d90)displayName: Preview에 표시프로젝트 키 + 서브태스크 이슈 타입 ID 확인: 부모 티켓을 조회하여 프로젝트 키와 서브태스크 이슈 타입 ID를 확인한다:
curl -s "https://{server}/rest/api/2/issue/{KEY}" \
-H "Authorization: Basic {auth_token}"
응답에서:
fields.project.key: 프로젝트 키 (예: DPHRS)서브태스크 이슈 타입 ID 확인 (순서대로 시도):
fields.subtasks[0].fields.issuetype.id 추출subtask: true)인 타입 조회:curl -s "https://{server}/rest/api/2/issue/createmeta?projectKeys={PROJECT}" \
-H "Authorization: Basic {auth_token}"
응답의 projects[0].issuetypes 중 "subtask": true인 항목의 id를 사용.
주의: issuetypeNames에 "하위 작업"을 하드코딩하지 않는다 — Jira 인스턴스 언어에 따라 "Sub-task" 등 다를 수 있다.
기존 서브태스크 중복 체크:
jira issue list -q "parent = {KEY}" -p {PROJECT} --plain --no-truncate
또는 REST API:
curl -s "https://{server}/rest/api/2/search?jql=parent={KEY}" \
-H "Authorization: Basic {auth_token}"
중복 매칭 알고리즘:
Step 1: 정규화
Step 2: 정확 일치 검사
Step 3: 토큰 기반 유사도 검사 (정확 일치 아닌 경우)
[, ], (, ), -, _, /)로 분리의, 및, 등, 를, 을, 이, 가, 에, for, the, a, an, and, orJ(A, B) = |A ∩ B| / |A ∪ B|SKIP? 표시, 사용자 확인)예시:
기존: "사용자 권한 관리 API" 새: "사용자 권한 관리 API" → 정확 일치, SKIP
기존: "사용자 권한 관리 API" 새: "사용자 권한 관리" → J=0.75, SKIP?
기존: "사용자 추가" 새: "권한 추가" → J=0.33, NEW
기존: "[BE] DB 마이그레이션" 새: "DB 마이그레이션 작성" → J=0.67, NEW
파싱한 태스크를 사용자에게 보여주고 확인을 받는다.
## Subtask Preview for {KEY}
**Parent**: {KEY} — {parent_title}
**Assignee**: {displayName} ({accountId 앞 8자...})
**Source**: specs/{KEY}-scope.md Section 6
| # | Title | Priority | Assignee | Status |
|---|-------|----------|----------|--------|
| 1 | {task_title} | High | {displayName} | NEW |
| 2 | {task_title} | Medium | {displayName} | NEW |
| 3 | {task_title} | - | - | SKIP (exists: {existing_key}) |
**NEW**: {count} tasks to create
**SKIP**: {count} tasks (already exist)
### Task Details
{For each NEW task:}
**#{n}: {title}**
- Priority: {priority}
- Effort: {effort}
- Dependencies: {deps}
- DoD: {dod}
AskUserQuestion으로 확인:
Edit 동작 상세:
3회 Edit 소진 시: AskUserQuestion으로 Create All / Cancel 2지선다 강제.
확인된 NEW 태스크를 Jira REST API로 직접 순서대로 생성한다.
scripts/create-subtask.sh 헬퍼 스크립트를 사용한다 (JSON 이스케이프, 에러 파싱 내장):
~/.claude/skills/jira-dispatch/scripts/create-subtask.sh \
--server "{server}" \
--auth "{auth_token}" \
--project "{PROJECT_KEY}" \
--parent "{PARENT_KEY}" \
--type-id "{subtask_type_id}" \
--summary "{task_title}" \
--priority "{priority}" \
--account-id "{account_id}" \
--labels "{labels}" \
--body-file "/tmp/{KEY}-task-{n}.md"
description은 /tmp/{KEY}-task-{n}.md에 임시 파일로 작성 후 --body-file로 전달한다.
Labels는 부모 티켓의 labels를 상속한다:
fields.labels 캡처[]accountId 사용curl -s "https://{server}/rest/api/2/user/search?query={name}" \
-H "Authorization: Basic {auth_token}"
중요: Jira REST API v2의 description 필드는 Jira Wiki Markup을 사용한다. Markdown(##, -)을 사용하면 렌더링이 깨진다.
h2. Description
{task_title}
h2. Dependencies
{dependencies — #N을 실제 Jira 키로 치환한 값. 예: "DPHRS-63, DPHRS-64" or "None"}
h2. Effort Estimation
{effort}
h2. Definition of Done
* {dod_item_1}
* {dod_item_2}
* {dod_item_3}
----
_Created by /jira:dispatch from specs/{KEY}-scope.md_
Wiki Markup 변환 규칙:
| Markdown | Jira Wiki Markup |
|----------|-----------------|
| ## Header | h2. Header |
| ### Header | h3. Header |
| - item | * item |
| **bold** | *bold* |
| *italic* | _italic_ |
| --- | ---- |
| `code` | {{code}} |
description을 /tmp/{KEY}-task-{n}.md 임시 파일에 작성할 때 반드시 Wiki Markup으로 작성한다.
특수문자 이스케이프:
[text]: Jira가 유효한 링크가 아니면 무시. [DPHRS-123] 같은 이슈 키는 자동 링크화 (의도된 동작).| (파이프): Wiki Markup 테이블 구분자. description 본문에 |가 포함되면 \|로 이스케이프. 단, h2./h3. 헤더와 * 불릿 내부에서는 테이블 컨텍스트가 아니므로 이스케이프 불필요.{ } (중괄호): Wiki Markup 매크로 구분자. {code}, {color} 등으로 해석될 수 있음. description에 중괄호가 포함되면 (예: Python dict {"key": "value"}) → \{ \}로 이스케이프하거나, {code}...{code} 블록 안에 넣어 보호.DoD 줄바꿈 처리: scope.md Section 6의 DoD 셀에 줄바꿈이나 여러 항목이 있으면, 각 항목을 * 접두사로 분리하여 Wiki Markup 불릿 리스트로 변환. 구분자: , 또는 \n 또는 실제 줄바꿈.
코드블록 변환: DoD에 마크다운 코드블록(```)이 포함된 경우 → Jira {code}...{code} 블록으로 변환.
{태스크번호 → Jira키} 맵에 기록. 예: {1: "DPHRS-63", 2: "DPHRS-64", ...}#N 참조를 맵에서 조회하여 실제 Jira 키로 치환
#1, #2, #3 → DPHRS-63, DPHRS-64, DPHRS-65#N (미생성) 그대로 유지[1/5] Created DPHRS-63: SystemRole Enum + Role ORM 모델 정의
[2/5] Created DPHRS-64: DB 마이그레이션
[3/5] FAILED: 관리자 역할 관리 API — 400 Bad Request: {error}
| 에러 | 동작 | |------|------| | 400 Bad Request | 에러 메시지 파싱, 기록 후 다음 태스크 | | 401 Unauthorized | 전체 중단 (인증 만료) | | 403 Forbidden | 에러 기록, 다음 태스크 | | 네트워크 타임아웃 | 1회 재시도, 실패 시 기록 후 진행 | | JSON 파싱 에러 | 에러 기록, 다음 태스크 |
## jira:dispatch Complete — {KEY}
| # | Key | Title | Priority | Assignee | Result |
|---|-----|-------|----------|----------|--------|
| 1 | DPHRS-63 | {title} | High | {name} | Created |
| 2 | DPHRS-64 | {title} | Medium | {name} | Created |
| 3 | - | {title} | - | - | Skipped (exists: DPHRS-42) |
| 4 | - | {title} | High | {name} | Failed: {reason} |
### Summary
- **Created**: {count}
- **Skipped**: {count}
- **Failed**: {count}
### Created Issues
- https://{server}/browse/DPHRS-63
- https://{server}/browse/DPHRS-64
issue create 대신 curl + REST API 사용 (안정성)issue create 안정성 문제 (2026-04-07 발견)jira issue create -t "Sub-task" 실행 시 issue type config 에러, assignee 매칭 실패, 명령 hangissue view, issue list, me)에만 사용.os.environ["PROJECT"] → KeyErrorexport 필요하나 누락export PROJECT PARENT SUMMARY TYPE_ID PRIORITY DESCRIPTION ACCOUNT_ID LABELS SERVER 추가-a "[email protected]" → "Unable to find associated user"/rest/api/2/myself에서 accountId 확인 후 사용. 타인 assignee는 /rest/api/2/user/search 사용.| Scenario | Action |
|----------|--------|
| scope.md 미존재 | STOP with "먼저 /jira:assess를 실행해주세요" |
| Section 6 파싱 실패 | STOP with "Section 6 테이블 형식이 올바르지 않습니다" |
| Jira 인증 실패 (REST API) | STOP with "Jira 인증이 만료되었습니다. jira init을 실행해주세요" |
| 부모 티켓 미존재 | STOP with "부모 티켓이 존재하지 않습니다" |
| 서브태스크 이슈 타입 ID 조회 실패 | STOP with "서브태스크 이슈 타입을 찾을 수 없습니다" |
| 모든 태스크 SKIP | STOP with "모든 태스크가 이미 존재합니다" |
| 개별 생성 실패 | 기록 후 다음 태스크로 진행, Phase 3에서 보고 |
| 401 응답 (인증 만료) | 전체 중단, 인증 재설정 안내 |
| 사용자 Cancel | STOP with "서브태스크 생성이 취소되었습니다" |
testing
CLAUDE.md 기반 환경 안전 체크. 작업 시작 전에 프로젝트의 안전 규칙, 컨벤션, 환경 설정을 자동 검증하여 CLEAR/WARNING/BLOCKED 상태를 보고한다. /check가 "변경 후 검증"이라면, /pre-flight는 "작업 전 환경 검증"이다. Use PROACTIVELY before starting work, especially after switching branches, pulling changes, or resuming a session. Also use when explicitly asked: "/pre-flight", "프리플라이트", "환경 체크", "작업 전 점검", "안전 체크", "environment check", "pre-flight check", "시작해도 돼?", "환경 괜찮아?", "safety check", "DB 확인", "설정 확인", "config check".
tools
PR 리뷰 워크플로우와 체크리스트를 제공하는 스킬. "PR 리뷰해줘", "코드 리뷰 해줘", "이 PR 봐줘", "review this PR" 등 PR 리뷰 요청 시 사용. GitHub/GitLab PR URL 또는 로컬 브랜치 diff를 기반으로 체계적이고 일관된 리뷰를 수행. 코드 품질, 안정성/보안, 성능, 테스트, 문서화 관점에서 건설적인 피드백 제공.
documentation
PR review comments를 체계적으로 처리하는 skill. Use when: (1) PR에 동료의 리뷰가 달렸을 때, (2) 여러 리뷰를 한 번에 처리하고 싶을 때, (3) 수정 후 commit 링크가 포함된 reply를 자동으로 추가하고 싶을 때
tools
PR diff를 받아 코드 리뷰 자동 요약을 생성하는 스킬. 핵심 변경점을 3줄로 요약하고, 변경 파일별로 what changed / why it matters / risk level을 정리. Use when: "PR 요약", "diff 요약", "PR 변경점 정리", "코드 변경 요약", "summarize PR", "PR summary", "diff summary", "what changed in this PR", "변경점 요약해줘", "PR 핵심 정리", "리뷰 요약"