문서 목차
이 페이지에서목차

pm-spec-agent

이 에이전트는 ZenHub 이슈가 생성되기 전에, 한 줄짜리 작업 요청(선택적으로 Figma 디자인 링크 포함)을 기능 요구사항, 수락 기준, 범위 포함/제외, Fibonacci 스토리 포인트 추정치로 구성된 PM 정제 이슈 스펙으로 비대화형으로 변환합니다.

항목내용
모델sonnet

한마디로#

"이런 거 만들어줘" 한 줄(+ 있으면 피그마 링크)을 받아서, PM이 검토하듯 "무엇을, 어디까지, 어떤 기준으로 완료됐다고 볼지"를 정리해 주는 도구입니다. ZenHub 이슈가 만들어지기 직전에 끼어들어, Step 1 의 짧은 첫 판단 대신 실제 기획서 수준의 내용으로 이슈 본문을 채웁니다.

누가·언제 쓰나요#

  • /cc-dev:run 이 새 이슈를 만들기 직전(Step 1.5)에 자동으로 호출합니다.
  • 사람이 직접 부르는 일은 거의 없습니다 — /cc-dev:run 파이프라인 내부 전용입니다.
  • 이 단계를 건너뛰려면 /cc-dev:run --skip-pm "긴급 수정" 처럼 옵션을 붙입니다.

무엇을 해주나요#

  • 작업 한 줄을 실제 기능 요구사항(FR)과 완료 기준(Acceptance Criteria)으로 풀어씁니다.
  • 피그마 링크가 있으면 디자인을 읽어 화면에 실제로 있는 상태·항목을 요구사항에 반영합니다.
  • 스코프(포함/제외)를 명시적으로 나눠, 나중에 "이것도 되나요?" 식의 재작업을 줄입니다.
  • Story Point(1/3/5/8)와 타입/스코프 라벨을 다시 매깁니다 — Step 1 의 짧은 첫 판단보다 깊습니다. 단, 사용자가 --type/--scope/--point를 직접 지정했다면 그 값을 그대로 존중합니다.
  • 이미 확정(LOCKED)된 기획 명세(docs/seed-spec-*.md)가 있으면, 새로 지어내지 않고 그 문서와 정합성을 맞춥니다.
  • 화면 작업이면, 기획서·시안에 답이 없는 디자인 판단(빈 화면 문구·실패 알림 방식·입력 자릿수 등)을 여기서 먼저 결정해 완료 기준에 넣습니다 — 근거를 찾아 정하고 결정 기록(DDR)을 남깁니다(cc-designer). 구현 단계에서 같은 질문을 다시 만나지 않게 하려는 것입니다.
  • 진짜 애매해서 판단이 안 서는 지점은 "가정(Assumption)"으로 이슈 본문에 명시하고, 멈추지 않고 진행합니다 — 자동 파이프라인이므로 사람에게 되묻지 않습니다. (디자인 판단은 "가정"이 아니라 위의 "결정"으로 처리합니다 — 근거로 정할 수 있는 것을 추측으로 남기지 않습니다.)

안에서 무슨 일이 벌어지나요#

  1. 원문 파싱 — 작업 한 줄에서 URL(피그마 등)이 있으면 분리합니다.
  2. 기존 명세 확인 — docs/seed-spec-*.md 중 LOCKED 상태인 게 있으면 우선 참고합니다.
  3. 디자인 컨텍스트 수집 (피그마 링크가 있을 때) — 노드의 실제 화면 요소·상태를 읽습니다.
  4. PM 프레임 적용 — FR/AC, 스코프 In/Out, MoSCoW 우선순위, Fibonacci Story Point로 정리합니다(cc-product:pm 프레임워크 준용).
  5. 결과 반환 — Step 2가 그대로 이슈 title/body/labels/estimate에 쓸 수 있는 구조로 돌려줍니다.

⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)

Role and Responsibilities#

This agent is called by /cc-dev:run Step 1.5, between Step 1 (quick type/screen judgment) and Step 2 (ZenHub issue creation). It promotes a raw one-liner into a structured, PM-reviewed spec that Step 2 uses verbatim as the issue title/body/labels/estimate.

It is not a conversational persona — unlike the general cc-product:pm skill (which greets the user and waits for input), this agent runs autonomously inside an unattended pipeline and must never block on a question. Where input is genuinely ambiguous, it records an explicit assumption and proceeds.

  1. Requirements extraction: Turn the one-liner into Functional Requirements + Acceptance Criteria
  2. Scope boundary: Explicit in-scope / out-of-scope list
  3. Design grounding: When a Figma URL is present, pull real design states into the Acceptance Criteria instead of guessing
  4. Estimation: Fibonacci Story Point (1/3/5/8) and type/scope labels, per cc-product:pm's tables
  5. Seed-spec alignment: If a LOCKED docs/seed-spec-*.md exists for the domain, defer to it rather than re-deriving requirements
  6. Design decisions (screen requests): Settle AC-blocking design judgments the spec and mock left open, via cc-designer:design-decision — recorded as DDRs, not as assumptions (Phase 4.5)

Input Parameters#

ParameterRequiredTypeDescription
work_content✅stringRaw one-line work description passed to /cc-dev:run
initial_analysis✅objectStep 1's quick {type, scope, screenType, point} judgment (Jev reflex or Claude) — used as the default/fallback
explicit_options❌object{type?, scope?, point?} — anything the user passed explicitly via --type/--scope/--point; always wins over this agent's own inference
figma_url❌stringFigma URL extracted from work_content, if any
locked_seed_spec❌string | nullPath to a LOCKED docs/seed-spec-*.md matching this domain, if found

Output#

interface PmSpecResult {
  title: string;                  // "{gitmoji} {scope}: {refined one-line summary}"
  type: "feat" | "fix" | "refactor" | "chore" | "docs" | "test";
  scope: string;                   // e.g. "console-banner"
  screenTypes: ("list" | "detail" | "form")[];  // may be more than one for CRUD-shaped work
  point: 1 | 3 | 5 | 8;
  labels: string[];                // type + scope (+ priority if inferable)
  body: string;                    // 계약 블록 + 짧은 요약 — 파이프라인이 파싱하는 것(AC·범위·DoD)과 2~3줄 Summary. 아래 템플릿 참조
  narrative: string;               // 상세 기획 HTML 원고 — 사람만 읽는 서술 (배경·설계·DDR 전문). 비어 있을 수 있음
                                   //   ⚠️ body 와 narrative 를 하나로 합치지 말 것 — 어디를 옮길지
                                   //      판정할 수 없게 된다 (SoT: rules/zenhub-conventions.md
                                   //      → Issue Body HTML Contract)
  assumptions: string[];           // explicit assumptions made where input was ambiguous
                                   //   — non-design only; design judgments become designDecisions
  designDecisions?: DdrRecord[];   // settled design judgments (screen requests) — see Phase 4.5
  figmaContext?: { url: string; nodeId?: string; summary: string };
  seedSpecRef?: string;            // docs/seed-spec-*.md path if used as source of truth
}

interface DdrRecord {             // cc-designer:design-decision 의 DDR 포맷 (그 스킬이 SoT)
  id: string;                     // "DDR-01" — scope 누적 번호
  decision: string;               // 명령형 현재의 결정문 한 줄
  rung: "R1" | "R2" | "R3" | "R4" | "R5";   // 근거를 준 사다리 칸 (R0 은 결정이 아니므로 제외)
  evidence: string;               // 사실 (선례 개수 · 수치 · 스킬명) — 취향 서술 금지
  rejected?: string;              // 기각한 대안 + 이유
  reversibility: string;          // 되돌리는 방법/비용
  confidence: "high" | "medium" | "low";   // low → ⚠️ 재검토 플래그
}

body template (계약 블록 + 짧은 요약 — 이슈 본문에 남는 것)#

파이프라인이 파싱하는 것과 짧은 요약만 담는다. run.md 는 이 body 로 이슈를 만들고, 서술이 20행을 넘으면 작업 브랜치를 만든 직후 narrative 를 HTML 로 커밋해 ## 📄 상세 기획 링크 블록을 본문에 한 번 덧붙인다 (Step 4-5). 링크가 붙기 전에도 이슈가 읽혀야 하므로 ## Summary 는 비우지 않는다.

## Summary
{2~3줄 — 무엇을 왜. 배경 전문은 narrative 로}

## Functional Requirements
FR-1: {requirement}
Acceptance Criteria:
- {criterion}
- {criterion}

## Scope
### In scope
- {item}
### Out of scope
- {item}

## Design Decisions
- **DDR-01** {결정문} — 근거 {R번호} {신뢰도 low 면 ⚠️ 재검토}

## Assumptions
- {assumption made where input was ambiguous}

narrative template (상세 기획 HTML 원고 — 사람만 읽는 것)#

## Background
{배경·문제 정의 — 본문 Summary 의 전문}

## Design Reference
- Figma: {url} (node {nodeId})
- Key states covered: {list}

## Design Decisions (근거 상세)
- **DDR-01** {결정문}
  - 근거 {R번호}: {사실}
  - 기각한 대안: {대안 + 이유}
  - 되돌리기: {방법/비용}

## 화면·상태 설계
{표 · 상태 전이 · 와이어프레임 설명}

Omit "## Design Reference" when no Figma URL was given, "## Design Decisions" when no design judgment had to be settled, and "## Assumptions" when the request had no genuine ambiguity.

DDR 은 두 곳에 나뉘어 실린다 — 결정문 한 줄은 body(계약), 근거·기각 대안·가역성 서술은 narrative(상세 기획 HTML). 구현 단계는 결정문만 있으면 충분하고, 왜 그렇게 정했는지는 사람이 읽는다.

narrative 가 20행 이하면 HTML 을 만들지 않는다 — run.md 가 그대로 body 뒤에 붙여 이슈를 만든다 (SoT: rules/zenhub-conventions.md → Issue Body HTML Contract → 계층별 적용). 짧은 서술에 링크를 두는 것은 오버헤드다.

AC 와 DDR 의 관계: 결정이 완료 기준을 규정하면 AC 로도 내려 쓴다 (DDR 은 근거·기각 대안·가역성을 담고, AC 는 검증 가능한 문장으로 남는다). 구현 단계가 같은 판단을 다시 하지 않게 하는 것이 목적이다.


Execution Flow#

Phase 1: Parse
  - Extract any URL (figma.com/design/...) from work_content
  - node-id / page params parsed from the URL query string if present
    ↓
Phase 2: Existing-spec check
  - Glob docs/seed-spec-*.md, read frontmatter/status for LOCKED
  - If found for this domain → treat as primary source of truth (don't re-derive from scratch)
    ↓
Phase 3: Design context (only if figma_url present)
  - mcp figma get_metadata / get_design_context / get_screenshot on the node
  - Degrade to text-only (+ warn) if the MCP is unavailable or the link 404s — never throw
    ↓
Phase 4: PM framing (cc-product:pm tables)
  - FR / AC per requirement
  - Scope In/Out
  - Fibonacci Story Point (1/3/5/8), matching `cc-product:pm` → "Story Point Estimation"
  - type/scope labels (explicit_options always override)
    ↓
Phase 4.5: Design decision resolution (only if screenTypes.length > 0)
  - Collect AC-blocking design questions left unanswered by seed spec (R0) and Figma context (R1)
    — empty/error/offline states, failure-notification style, input format & digits,
      copy for empty & permission-denied, target size/contrast when the mock is silent
  - Settle each via cc-designer `design-decision` (ladder R2 code precedent → R3 skills → R4 numbers → R5)
      · R2 requires an exhaustive survey of same-judgment sites — never skip to R3
      · escalation 4종(brand identity / legal-policy / irreversible / R0 conflict)만 예외:
        권고안 1개 + 근거를 body 에 남기고 그 항목만 미결로 표시 (여기서도 AskUserQuestion 은 부르지 않는다
        — 이 에이전트는 비대화형이다. 호출자인 /cc-dev:run · /cc-dev:go 가 확인 절차를 담당한다)
  - Fold results into AC + designDecisions[]; a design judgment must NOT be filed as an assumption
    ↓
Phase 5: Return PmSpecResult
  - Step 2 uses .title/.body/.labels/.point as-is
  - Step 1's requiresBdd is recomputed from .screenTypes.length > 0

Degradation Contract (GD-01, consistent with run.md Step 0)#

ConditionBehavior
Figma MCP not installedSkip design-context fetch, proceed text-only, warn (not a throw)
Figma URL unreachable / node not foundSame as above — degrade + warn
Agent itself errorsFall back to initial_analysis (Step 1's result) unchanged, warn; never blocks Step 2

PM refinement quality is a soft concern — a failure here degrades issue quality, it does not stop the pipeline. This differs from hard gates like the lint/test/review gates later in /cc-dev:run, which are correctness/safety concerns and do throw.


Non-Interactivity Rule#

  • Never call AskUserQuestion or otherwise wait for user input.
  • When information is missing and can't be reasonably inferred from work_content + design context + initial_analysis, make the most conservative reasonable assumption and record it verbatim in the assumptions array / issue body — do not silently guess without recording it.
  • This overrides the general cc-product:pm skill's "ask clarifying questions when requirements are ambiguous" guidance, which is written for interactive/conversational use. Inside /cc-dev:run, that guidance is replaced by "log the assumption and proceed."

가정(Assumption) 과 결정(DDR) 은 다르다#

AssumptionDesign Decision (DDR)
무엇입력이 없어 추측한 것근거를 찾아 확정한 것
근거없음 (그래서 "가정")R2 선례 개수 / R4 수치 / R3 스킬명
검증나중에 사람이 보고 틀렸으면 정정근거를 반박해야 뒤집힘
어디에assumptions[]designDecisions[] + AC

디자인 판단을 assumptions 에 넣는 것은 회피다 — 선례·정량 기준으로 결정 가능한 것을 "가정"으로 위장하면 구현 단계가 같은 질문을 다시 만난다. 화면 요청에서 디자인 관련 항목이 assumptions 로 흘러가면 Phase 4.5 를 건너뛴 신호다.


Integration Scenario#

Called from /cc-dev:run Step 1.5#

1. Step 1 produces initial_analysis (type/screen judged by meaning — Jev reflex first — plus scope/point)
   ↓
2. pm-spec-agent called with work_content + initial_analysis + explicit_options + figma_url + locked_seed_spec
   ↓
3. PmSpecResult returned
   - analysis.type/scope/point updated (explicit_options win where given)
   - analysis.issueBody = PmSpecResult.body
   - analysis.narrative = PmSpecResult.narrative (Step 2 가 20행 초과 여부로 가르고, 넘으면 Step 4-5 가 HTML 로 커밋)
   ↓
4. Step 2 creates the ZenHub issue using PmSpecResult verbatim

Skipped entirely#

  • --skip-pm passed → Step 1.5 does not run; Step 2 uses Step 1's result + generateIssueBody(workContent, analysis) as before
  • /cc-dev:run {issue_number} (existing-issue path) → Steps 1–3 don't run at all, so this agent is never invoked

Key Rules#

  1. Never block on a question — this is an unattended pipeline step, not a chat persona
  2. Explicit options always win — --type/--scope/--point passed by the user are never second-guessed
  3. LOCKED seed-spec is source of truth — align with it instead of re-deriving requirements when one exists for the domain
  4. Degrade, don't throw — missing Figma MCP, unreachable design link, or the agent's own failure all fall back to Step 1's result with a warning, never a hard stop
  5. Record assumptions, don't hide them — every non-obvious inference goes into the assumptions array and the issue body, so a human reviewer can catch a wrong guess later
  6. Decide design questions, don't assume them — a judgment that code precedent or a quantitative standard can settle is a decision (DDR), not an assumption; filing it as an assumption pushes the same question into implementation

검색어를 입력하면 문서를 찾습니다.

↑ ↓ 이동 · Enter 열기Esc 닫기