---
name: prepare-epic-work-items
description: 현재 또는 지정 Milestone의 정확히 한 Epic을 작은 직접 작업과 큰 PLAN/CODE_REVIEW pair로 변환하고, fresh one-shot 자가검토, refine-plans 세분화, 최종 재검토와 push까지 수행할 때 사용한다. "현 마일스톤의 X Epic에서 작은 작업은 바로 처리하고 큰 작업은 plan으로 작성해", "X 마일스톤 Y Epic 작업 준비해" 요청에서 사용한다.
---

# Prepare Epic Work Items

## 목적

정확히 한 Epic을 한 사이클로 준비한다. 작은 작업은 구현·검증하고 큰 작업은 실행 가능한 PLAN/CODE_REVIEW pair로 만든 뒤 두 번의 fresh 검토와 한 번의 세분화를 거쳐 remote branch에 보존한다.

## 입력

- `workspace`: 준비된 feature worktree 절대 경로 (필수)
- `target-milestone`: 활성 Milestone slug 또는 경로 (필수)
- `target-epic`: 정확한 Epic id 또는 이름 (필수)
- `execution-catalog`: 런타임이 주입한 agent-model 실행 카탈로그 경로. `AGENT_TASK_EXECUTION_CATALOG`로 대신 주입할 수 있다. (필수)
- `planner-target`: 카탈로그에 선언된 materialize/refine 실행 target id. `AGENT_TASK_PLANNER_TARGET`로 대신 주입할 수 있다. (필수)
- `review-target`: 카탈로그에 선언된 initial/final review target id. `AGENT_TASK_REVIEW_TARGET`로 주입하거나 생략하면 `planner-target`과 같다. (선택)
- `retry`: terminal failure의 원인을 사용자가 해소한 뒤 같은 Epic 상태를 재개할 때만 사용한다. (선택)
- `batch-task-ids`: 상위 `prepare-milestone-workspace`가 고정한 선택 Epic Task id 합집합. 직접 호출에서는 사용하지 않는다. (내부 선택)

## 범위 계약

- 한 실행은 Epic 하나만 다룬다. Epic 범위 요청은 `prepare-milestone-workspace` coordinator가 문서 순서대로 하나씩 실행한다.
- 실행 identity는 `<milestone-slug>:<epic-id>`다.
- standalone 사이클의 다음 Epic은 현재 Epic의 모든 Task가 workstate sync에서 완료된 `EPIC_COMPLETED` 뒤에 시작한다.
- 상위 coordinator가 고정한 batch에서는 현재 Epic의 `EPIC_WORK_ITEMS_READY`도 다음 선택 Epic 준비를 허용한다. 이때 현재 Epic pair는 유지하고, 다음 Epic cycle은 batch Task id 합집합 안의 앞선 pair를 구조 검증하되 소유하거나 변경하지 않는다.
- 실행 중 Epic cycle의 batch Task id 합집합은 바꾸지 않는다. 준비 terminal 뒤에는 같은 Epic을 이후 단독/복수 batch의 일부로 다시 검증할 수 있다.
- `EPIC_WORK_ITEMS_READY`는 큰 작업 plan이 준비됐다는 뜻이며 구현 완료가 아니다.
- 개별 `EPIC_WORK_ITEMS_READY`는 dispatcher 시작 신호가 아니다. 복수 선택의 dispatcher gate는 상위 coordinator의 `MILESTONE_WORK_ITEMS_READY` 하나다.
- 같은 identity를 다시 실행하면 active pair, USER_REVIEW, runtime state를 먼저 대조하고 중복 plan을 만들지 않는다.

작은 작업은 아래를 모두 만족해야 한다.

- 하나의 응집된 변경이고 한 번의 bounded 실행과 명시 검증으로 완료할 수 있다.
- 새 API, wire, schema, migration, 외부 side effect 또는 책임 경계 변경이 없다.
- 사용자·SDD 결정이 필요하지 않고 큰 작업의 write set과 충돌하지 않는다.

하나라도 거짓이거나 불명확하면 큰 작업으로 분류한다. 고정 LOC나 파일 수만으로 분류하지 않는다.

## 실행 절차

1. **Epic을 고정한다**
   - target Milestone이 `[계획]` 또는 `[진행중]`, 구현 잠금 해제인지 확인한다.
   - `### Epic: [<epic-id>] <title>`을 정확히 하나 찾고 그 아래 Task id를 고정한다.
   - standalone에서 다른 Epic의 active pair가 있거나 target이 모호하면 `FAILED`로 멈춘다. 상위 batch에서는 선택 Task id 합집합 밖 pair 또는 Epic 경계를 가로지르는 pair만 거부한다.

2. **foreground 사이클을 실행한다**
   - 아래 스크립트를 한 번 실행하고 execution-layer event wait를 유지한다.

```bash
python3 agent-ops/skills/common/prepare-epic-work-items/scripts/run_epic_cycle.py \
  --workspace "$WORKSPACE" \
  --milestone "$MILESTONE" \
  --epic "$EPIC" \
  --execution-catalog "$EXECUTION_CATALOG" \
  --planner-target "$PLANNER_TARGET" \
  --review-target "$REVIEW_TARGET"
```

   - agent, model, 실행 명령과 provider별 옵션은 스킬이나 스크립트에 고정하지 않고 카탈로그 target의 opaque metadata와 argv template에서 가져온다.
   - target id와 카탈로그 revision은 실행 evidence에 보존한다. `--retry`는 동일 카탈로그 계약과 target을 사용한다.
   - 상위 batch에서 호출할 때만 고정된 Task id 합집합을 `--batch-task-ids`로 전달한다.
   - 스크립트는 카탈로그가 지시한 각 target을 새 one-shot session으로 실행한다.
   - model stdout/stderr는 git common dir의 locator log에만 저장한다. caller stdout에는 lifecycle/attention event만 출력한다.

3. **상태 전이를 따른다**
   - `MATERIALIZE`: 작은 작업을 먼저 구현·검증하고, 변경된 source를 기준으로 큰 작업에 `plan`을 적용한다.
   - `INITIAL_REVIEW`: fresh reviewer가 전체 변경과 PLAN/CODE_REVIEW stub을 재검토하고 누락을 수정한다. 구현 전 stub에 공식 `code-review`를 실행하지 않는다.
   - 첫 검토가 유효하면 변경을 commit/push한다.
   - `REFINE`: target Epic Task id를 가진 모든 미착수 pair에 `refine-plans`를 한 번 적용한다. 분리 가치가 없으면 `no-change`를 허용한다.
   - `FINAL_REVIEW`: fresh reviewer가 child scope 합집합, 중복, dependency, `milestone-task`, routing, 검증을 다시 확인하고 수정한다.
   - 최종 validator가 통과하면 남은 변경을 commit/push하고 `EPIC_WORK_ITEMS_READY`를 낸다.

4. **중단 상태를 처리한다**
   - 사용자만 결정할 범위·설계 문제는 roadmap SDD `USER_REVIEW.md`로 남기고 유효한 stop artifact를 commit/push한 뒤 `USER_REVIEW`로 끝낸다.
   - agent-task 구현 review gate가 아니므로 preparation agent가 `agent-task/**/USER_REVIEW.md`를 만들지 않는다.
   - agent exit, invalid pair, plan validator, git commit/push 실패는 자동 삭제 없이 `FAILED`로 끝낸다.
   - foreground wait가 끊겼지만 동일 PID/start-token의 one-shot이 살아 있으면 state를 `tracking`으로 유지하고 `AGENT_TRACKING`만 낸다. 재호출은 새 agent를 만들지 않는다.
   - tracking handle이 종료되면 `AGENT_RECOVERY_REQUIRED`에서 멈춘다. locator 확인 뒤 `--retry`하면 현재 artifact를 먼저 채택·검증한다. 검증 실패 뒤의 명시적 `--retry`만 새 one-shot을 허용한다.
   - `EPIC_WORK_ITEMS_READY` 뒤 dispatcher와 workstate sync가 Task와 active pair를 모두 닫으면 같은 identity 재호출이 clean HEAD를 재검증해 `EPIC_COMPLETED`로 승격한다.

## 상태 이벤트

- `EPIC_SCOPE_RESOLVED`
- `MATERIALIZE_STARTED`, `MATERIALIZE_FINISHED`
- `INITIAL_REVIEW_STARTED`, `INITIAL_REVIEW_FINISHED`
- `INITIAL_CHECKPOINT_PUSHED`
- `REFINE_STARTED`, `REFINE_FINISHED`
- `FINAL_REVIEW_STARTED`, `FINAL_REVIEW_FINISHED`
- `FINAL_ARTIFACTS_PUSHED`
- `AGENT_TRACKING`, `AGENT_RECOVERY_REQUIRED`, `AGENT_RESULT_RECOVERED`
- `EPIC_BATCH_VALIDATED` (상위 batch의 deterministic barrier 검증)
- `EPIC_WORK_ITEMS_READY`, `EPIC_COMPLETED`, `USER_REVIEW`, `FAILED`

routine event는 caller 판단을 요구하지 않는다. caller는 `USER_REVIEW`, `AGENT_RECOVERY_REQUIRED`, 복구 불가능한 `FAILED`, terminal completion에서만 깨어난다.

## 실행 결과 검증

- [ ] active PLAN/CODE_REVIEW가 항상 pair이고 첫 줄 metadata가 일치하는가
- [ ] 모든 `milestone-task`가 target Epic Task id의 비어 있지 않은 부분집합인가
- [ ] 상위 batch 호출이면 다른 pair도 선택 batch 합집합 안에 있고 target Epic 경계를 가로지르지 않는가
- [ ] 모든 PLAN이 dispatcher `--validate-plan`을 통과하는가
- [ ] refine 전후 Task id 합집합과 scope가 보존됐는가
- [ ] repository에 unresolved template token이나 preparation runtime state가 추적되지 않는가
- [ ] 완료 checkpoint가 현재 feature branch remote에 push됐는가
- 검증 실패 시: partial artifact를 commit하지 않고 locator와 복구 조건을 남겨 `FAILED`로 끝낸다.

## 출력 형식

```text
Epic work preparation
- identity: <milestone-slug>:<epic-id>
- direct work: <completed task ids 또는 없음>
- plans: <active pair paths 또는 없음>
- refinement: <split | no-change>
- event: <EPIC_WORK_ITEMS_READY | EPIC_COMPLETED | USER_REVIEW | FAILED>
- remote: <branch와 pushed commit>
```

## 금지 사항

- 여러 Epic을 한 agent context에서 처리하지 않는다.
- 같은 session을 self-review에 resume하지 않는다.
- plan/refine agent가 nested agent나 task dispatcher를 실행하지 않는다.
- 구현 전 CODE_REVIEW stub에 공식 code-review verdict를 쓰지 않는다.
- timer polling, LLM keepalive, routine model stream 중계를 하지 않는다.
- validation 실패 상태를 commit/push하거나 force push하지 않는다.
