---
name: update-roadmap
version: 1.22.0
description: 로드맵 업데이트, 로드맵에 추가, 마일스톤 추가/갱신, phase/페이즈 변경 요청에 사용한다. Roadmap-Phase-Milestone scaffold에서 target 없는 신규 작업의 규모를 판정하고 기존 Phase/Milestone/Epic/Task를 검색해 upsert한 뒤, 없을 때만 새 항목을 만들고 로컬 current.md 동기화, runtime m-task 완료 이벤트 반영, 완료 후보 검토중 전환, agent-ui 코드 동기화 Milestone의 종료 검토 시 구현됨 상태 반영, 완료 근거 충족 archive 이동, workspace 외부 의존 잠금 양방향 동기화를 처리한다.
---

# 로드맵 업데이트

## 목적

기존 `agent-roadmap/` 구조를 현재 프로젝트 방향과 진행 상태에 맞게 갱신한다.
표준 구조는 `ROADMAP.md -> phase/<phase-slug>/PHASE.md -> phase/<phase-slug>/milestones/<milestone-slug>.md`다.
archive도 같은 Phase scaffold를 유지하며 `archive/phase/<phase-slug>/...` 아래에 둔다.
로드맵 전체를 매 작업마다 읽지 않도록 유지하면서, 브랜치별 로컬 `current.md`의 활성 Phase와 활성 Milestone 창이 실제 작업 후보 목록으로 동작하게 한다.

Milestone은 구현 계획이 아니라 방향성, 범위, 위험, 확인 필요 사항을 기록하는 협업 문서로 유지한다.
Epic과 Task는 별도 파일로 분리하지 않고 Milestone 문서의 `기능` 안에서 관리한다. 별도 `완료 기준` 섹션은 만들지 않고, 검증이 필요한 기능에만 같은 Task 안의 `검증:` 문구로 통합한다.

## 언제 호출할지

- 사용자가 "로드맵 업데이트", "마일스톤 갱신", "phase 변경", "현재 활성 마일스톤 바꿔줘"라고 요청할 때
- 사용자가 "로드맵에 추가", "로드맵 작업 추가", "로드맵 기능 추가", "로드맵 Epic/Task 추가", "로드맵 에픽/태스크 추가", "마일스톤에 추가", "마일스톤 추가"처럼 로드맵에 새 내용을 넣어 달라고 요청할 때
- Milestone 완료, 보류, 폐기, 신규 추가가 필요할 때
- Phase 완료, 보류, 폐기, 신규 추가가 필요할 때
- 완료 또는 폐기된 Phase/Milestone을 archive로 이동해야 할 때
- 런타임이 `m-<milestone-slug>` task group의 PASS 완료 이벤트를 Milestone에 반영해야 할 때
- 특정 기능이나 작업을 새 Milestone, 기존 Milestone의 Epic, 기존 Epic의 Task 중 적절한 위치에 추가해야 할 때
- 활성 Phase/Milestone 창에 포함할 목록이 달라졌을 때
- 기존 로드맵을 `phase/<phase-slug>/PHASE.md` scaffold로 마이그레이션하거나 표준화해야 할 때
- 사용자가 "이 Milestone은 X가 끝나야 가능하다", "A 전까지 B를 잠근다", "잠금 해제 조건은 X다", "현재 마일스톤은 X 프로젝트 작업 뒤에 진행되어야 한다", "의존성 설정해"처럼 외부 의존 잠금을 말할 때

## 입력

- `mode`: `status` / `milestone` / `phase` / `replan` / `sync` / `concretize` / `archive` 중 하나 (선택, 요청에서 추론 가능)
- `target-phase`: 갱신할 Phase 이름, slug, 파일 경로 (선택)
- `target-milestone`: 갱신할 Milestone 이름, slug, 파일 경로 (선택)
- `active-phases`: 활성 Phase 창에 둘 Phase 이름, slug, 파일 경로 목록 (선택)
- `active-milestones`: 활성 Milestone 창에 둘 Milestone 이름, slug, 파일 경로 목록 (선택)
- `new-feature`: 추가할 기능, 작업, 또는 새 Milestone 설명 (선택)
- `placement`: 새 작업 배치 위치. 예: `<phase-name> 안`, `<milestone-name> 안`, `<epic-id> 아래`, `<item-id> 앞`, `<item-id> 뒤`, `auto` (선택)
- `placement-unit`: 삽입 단위. `phase` / `milestone` / `epic` / `task` / `subtask` / `auto` 중 하나 (선택)
- `target-status`: 전환할 Phase/Milestone 상태. `[스케치]` / `[계획]` / `[진행중]` / `[검토중]` / `[완료]` / `[보류]` / `[폐기]` 중 하나 (선택)
- `lock-state`: Milestone 구현 잠금 상태. `잠금` / `해제` 중 하나 (선택)
- `decision-needed`: `구현 잠금`에 남길 에이전트가 확정할 수 없는 제품/범위/우선순위/책임 경계 결정 목록 (선택)
- `sdd-state`: Milestone SDD gate. `필요` / `불필요` / `확인 필요` 중 하나 (선택)
- `sdd-path`: SDD 문서 경로. 기본값은 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md` (선택)
- `sdd-review`: SDD 사용자 리뷰 상태. `없음` / `요청됨` / `해결됨` 중 하나 (선택)
- `evidence`: 완료 판단에 사용할 파일, PR, 테스트, 커밋, 사용자 설명 (선택)
- `complete-log`: 런타임 완료 이벤트가 전달한 `complete.log` 경로. `Roadmap Completion` 섹션이 있을 때만 Milestone 기능 Task 체크에 사용한다 (선택)
- `review-state`: 완료 리뷰 상태. `검토중` / `통과` / `보완 필요` / `보류` / `폐기` 중 하나 (선택)
- `review-comment`: 완료 리뷰에 남길 보완, 보류, 폐기 방향성 또는 근거 메모 (선택)
- `origin-task`: 런타임 완료 이벤트가 전달한 `agent-task/m-<milestone-slug>` 또는 `agent-task/m-<milestone-slug>/<subtask_dir>` 형식의 원래 active task 경로. 이벤트가 최종 archive 경로만 갖고 있으면 런타임이 이 형식으로 정규화해 전달한다 (선택)
- `archive-date`: Phase/Milestone 아카이브 날짜. 없으면 현재 날짜를 사용한다 (선택)
- `workspace-lock`: 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`에 기록하거나 동기화할 외부 의존 잠금 설명 (선택)

## 표준 구조

```text
agent-roadmap/
  ROADMAP.md
  current.md  # local, git ignored
  phase/
    <phase-slug>/
      PHASE.md
      milestones/
        <milestone-slug>.md
  sdd/
    <phase-slug>/
      <milestone-slug>/
        SDD.md
        USER_REVIEW.md
  archive/
    phase/
      <phase-slug>/
        PHASE.md
        milestones/
          <milestone-slug>.md
    sdd/
      <phase-slug>/
        <milestone-slug>/
          SDD.md
```

- `ROADMAP.md`는 전체 목표와 Phase 흐름만 담는다.
- `PHASE.md`는 해당 Phase의 목표, 상태, Milestone 흐름, Phase 경계를 담는다.
- Milestone 문서는 해당 Phase 하위 `milestones/`에 둔다.
- 완료된 Phase는 `archive/phase/<phase-slug>/PHASE.md`로 이동하고, 하위 Milestone도 같은 archive Phase scaffold 아래에 둔다.
- 진행중 Phase 안에서 완료된 Milestone은 `archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동하고, 활성 `PHASE.md`에는 짧은 archive 링크를 남긴다.
- archive `PHASE.md`는 Phase 자체가 완료/폐기될 때만 만든다. 진행중 Phase의 완료 Milestone만 archive된 경우에는 archive Phase 디렉터리에 `milestones/`만 있을 수 있다.
- 큰 Milestone의 SDD는 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`에 둔다.
- SDD 사용자 리뷰는 같은 디렉터리의 `USER_REVIEW.md`로 두고, 해결 후 `user_review_N.log`로 남긴다.
- 완료 또는 폐기된 Milestone의 SDD는 `agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/`로 이동한다.
- `<phase-slug>`와 `<milestone-slug>`는 소문자 영문, 숫자, 하이픈만 사용한다.
- `current.md`는 브랜치별 로컬 포인터이며 활성 Phase와 활성 Milestone을 모두 가리킨다.
- `current.md`는 git 추적 대상이 아니며, 공유 진행 상태는 `ROADMAP.md`, `PHASE.md`, Milestone 문서, `.agent-roadmap-sync/locks.yaml`에 기록한다.
- `current.md`에는 archive 경로를 넣지 않는다.
- `current.md`에는 `[완료]` 또는 `[폐기]` Phase/Milestone을 남기지 않는다. 완료 후보는 완료 근거와 archive 전환이 정리될 때까지 `[검토중]`으로 둔다.

## 상태와 id

- 상태 표기는 `[스케치]`, `[계획]`, `[진행중]`, `[검토중]`, `[완료]`, `[보류]`, `[폐기]` 중 하나만 사용한다.
- 기존 비표준 상태 표기는 갱신 범위에 포함될 때 표준 상태 표기로 정리한다.
- `[스케치]`는 방향성, 문제의식, 후보 범위, 미정 질문을 기록하는 컨셉 상태다. 구현 가능한 계획이 아니므로 `agent-task` 구현 계획 생성과 코드 구현 대상으로 삼지 않는다.
- `[스케치]` 항목은 `[계획]`으로 승격하기 위한 `승격 조건`, 에이전트가 확정할 수 없는 결정, 범위 경계, 후속 Milestone 후보를 정리한다.
- `[계획]` 이상 Milestone에서 `승격 조건` 섹션은 선택 사항이다. 섹션이 없거나 `- 없음`이면 템플릿 오류로 보지 않는다.
- `[스케치]`를 `[계획]`으로 전환할 때는 `승격 조건`의 미정 항목이 해소되고, 목표, 범위, 기능 Task, 직접 필요한 결정 항목, 후속 구현 단위가 구현 계획을 만들 수 있을 만큼 정리되었는지 확인한다.
- `[계획]`은 목표, 범위, 기능 Task, 구현 잠금, 결정 필요 항목이 문서화되어 잠금 해제 후 구현 계획을 만들 수 있는 상태다.
- `[검토중]`은 모든 기능 Task와 Task 안에 명시된 검증이 충족되고 `구현 잠금`이 해제되었으나, 완료 근거 정리와 archive 전환이 남은 완료 후보 상태다.
- 검토 결과 보완이 필요하면 별도 reopen 상태를 만들지 않고 `[진행중]`으로 되돌린 뒤 `완료 리뷰` 또는 `작업 컨텍스트`에 보완 방향을 남긴다.
- 검토 결과 보류 또는 폐기 결정이 나면 `[보류]` 또는 `[폐기]`로 전환한다.
- `ROADMAP.md`의 Phase 흐름과 `PHASE.md`의 Milestone 흐름은 완료, 검토중, 진행중, 계획, 스케치 순서를 기본으로 하며 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
- Epic heading은 `### Epic: [epic-id] <이름>` 형식으로 작성한다.
- Task는 `- [ ] [item-id] 설명` 또는 `- [x] [item-id] 설명` 형식으로 작성한다.
- epic-id와 item-id는 공백 없는 짧은 ASCII 토큰이며, 해당 Milestone 안에서만 유일하면 된다.
- 사용자가 epic-id 또는 item-id를 언급하면 해당 항목을 우선 anchor로 삼고, 기존 id는 명시적 요청 없이 바꾸지 않는다.

## 로딩 원칙

- 일반 갱신은 로컬 `current.md`, 관련 활성 Phase, 관련 활성 Milestone을 우선 읽는다.
- `current.md`가 없고 활성 창 갱신이 필요하면 `agent-ops/skills/common/_templates/roadmap-current-template.md` 형식으로 로컬 파일을 만든다.
- `ROADMAP.md`는 Phase 흐름, 전체 구조, 활성 범위 밖 작업, 전체 재계획, archive 링크 갱신이 필요할 때 읽는다.
- `agent-roadmap/archive/**`는 일반 작업이나 sync에서 읽지 않는다.
- archive 모드에서 이동 대상이 아직 활성 경로에 있으면 그 대상 문서는 읽을 수 있다.
- 과거 완료 내용, 완료 근거, 복원, 비교가 필요한 요청이면 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 archive 문서만 읽는다.

## 템플릿

- `ROADMAP.md`: `agent-ops/skills/common/_templates/roadmap-template.md`
- `current.md`: `agent-ops/skills/common/_templates/roadmap-current-template.md`
- `PHASE.md`: `agent-ops/skills/common/_templates/roadmap-phase-template.md`
- Milestone: `agent-ops/skills/common/_templates/roadmap-milestone-template.md`
- SDD: `agent-ops/skills/common/_templates/roadmap-sdd-template.md`
- SDD 사용자 리뷰: `agent-ops/skills/common/_templates/roadmap-sdd-user-review-template.md`

## 링크 표기

- 사용자에게 보여주는 결과 보고와 새로 생성/갱신하는 로드맵 문서에서 `ROADMAP.md`, `current.md`, `PHASE.md`, Milestone 문서, SDD, `USER_REVIEW.md`, archive 문서, `complete.log` 같은 문서/산출물 포인터는 raw path만 쓰지 말고 `[표시 제목](상대경로)` Markdown 링크로 쓴다.
- 로드맵 문서 안의 링크 target은 링크를 작성하는 Markdown 파일 위치 기준 상대경로로 쓴다. 예: `ROADMAP.md`와 `current.md`에서는 `[PHASE.md](phase/<phase-slug>/PHASE.md)`, Phase 문서에서는 `[Milestone](milestones/<milestone-slug>.md)`, Milestone 문서에서는 `[ROADMAP.md](../../../ROADMAP.md)`와 `[PHASE.md](../PHASE.md)`를 쓴다.
- 채팅 결과 보고처럼 저장 위치가 없는 출력은 repo root 기준 상대경로를 쓸 수 있다. 예: `[PHASE.md](agent-roadmap/phase/<phase-slug>/PHASE.md)`.
- `경로:`, `Phase:`, `Milestone:`, `SDD 문서:`, `수정 파일:` 같은 필드명을 유지해야 해도 값은 Markdown 링크로 작성한다.
- 실제 갱신한 활성 로드맵 문서에는 `<phase-slug>`, `<milestone-slug>`, `<relative-...>` 같은 placeholder가 들어간 링크 target을 남기지 않는다. 템플릿 placeholder는 실제 파일 위치 기준 상대경로 또는 `없음`으로 치환한다.
- 기존 문서에 남아 있는 raw path나 backtick path는 읽기/마이그레이션 입력으로 허용한다. 갱신 범위에 포함된 활성 문서 포인터만 Markdown 링크로 보정하고, archive 스냅샷은 링크 표기만을 이유로 재포맷하지 않는다.
- `.agent-roadmap-sync/locks.yaml`의 `locked`, `rely-on.target`, Milestone identity(`<project>:agent-roadmap/...`), 명령 입력값처럼 machine-readable 계약 값은 raw 값을 유지할 수 있다. 다만 사용자-facing 설명에는 가능한 경우 별도 Markdown 문서 링크를 함께 붙인다.

## 구현 잠금

- `구현 잠금`은 승인 절차가 아니라 에이전트가 확정할 수 없는 결정이 필요한지 표시하는 얇은 상태다.
- 제품 방향, 범위, 우선순위, 책임 경계처럼 에이전트가 확정할 수 없는 항목이 남아 있으면 `잠금`으로 두고 `결정 필요` 목록에 남긴다.
- 기존 구조, 도메인 rule, 플랫폼 관례, 업계 표준으로 합리적으로 정할 수 있는 항목은 `결정 필요`가 아니라 `작업 컨텍스트`의 표준선으로 기록한다.
- Milestone 전체에서 에이전트가 확정할 수 없는 결정 항목이 더 이상 없고 에이전트가 표준선에 따라 실행하면 되는 상태라면 `해제`로 둔다.
- `구현 잠금` 섹션이 없거나, 상태가 `잠금`이거나, 미완료 `결정 필요` 항목이 하나라도 있으면 실구현 계획, 코드 구현, Milestone 완료 후보 전환을 차단한다.
- 잠금 상태에서 허용되는 갱신은 잠금 해소, SDD gate 처리, 범위 제외/후속 Milestone 이동, 작업 컨텍스트 정리 같은 roadmap-only 변경뿐이다.
- 남은 `결정 필요` 항목이 현재 Milestone 실구현 범위가 아니면 먼저 그 항목을 `범위 제외`, 후속 Milestone, 또는 `작업 컨텍스트`로 옮긴 뒤 `구현 잠금`을 `해제`한다. 잠금 해제 전에는 기능 Task 완료 근거가 있어도 `[검토중]`으로 올리지 않는다.
- SDD gate가 필요한 Milestone은 `구현 잠금`에 `SDD: 필요`, 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크, 잠금 해제 조건을 남기고 SDD 잠금이 해제될 때까지 `잠금`으로 둔다.
- 새 Milestone을 만들거나 `[스케치]`를 `[계획]`으로 승격하면서 `SDD: 필요`로 판정한 경우, 같은 `update-roadmap` 흐름 안에서 `roadmap-sdd create`까지 수행해 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md`를 만든다. `SDD: 필요`와 SDD 문서 링크만 남기고 파일이 없는 상태로 종료하지 않는다.
- SDD 작성에 필요한 목표, 범위, 기능 Task, Acceptance Scenario 후보를 이미 판단했고 사용자만 결정할 항목이 없으면 SDD 상태를 `[승인됨]`, SDD 잠금을 `해제`로 두고 Milestone `구현 잠금`도 `해제`한다.
- 사용자만 결정할 항목이 있으면 SDD 초안을 만들고 `roadmap-sdd review-ready` 방식으로 `USER_REVIEW.md`를 남긴다. 이 경우 Milestone `구현 잠금`은 `잠금`으로 둔다.
- SDD 파일을 만들 수 없는 예외는 사용자가 명시적으로 SDD 생성을 뒤로 미룬 경우뿐이다. 이때 결과 보고에 `SDD gate: 필요-작성 전`과 구체적인 지연 사유를 남긴다.
- SDD gate가 불필요한 Milestone은 `SDD: 불필요`과 짧은 사유를 남긴다.
- SDD가 필요한 기준: cross-repo 계약, 외부 provider 쓰기, 상태 머신/lifecycle, idempotency/retry/identity map, API/proto/config/env/schema 변경, field smoke, 사용자 승인 gate 영향.
- SDD 사용자 리뷰가 필요한 결정은 chat으로 즉시 묻지 않고 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md`에 남긴다.
- 잠금 상태 변경은 Milestone 완료 판정이 아니므로 `기능` Task를 자동 완료 처리하지 않는다.
- `[스케치]` Milestone은 `구현 잠금`이 `해제`로 보이더라도 구현 계획과 코드 구현 대상이 아니다. 먼저 승격 조건을 충족해 `[계획]`으로 전환한다.

## 프로젝트 간 잠금

- 프로젝트 상위 `.agent-roadmap-sync/locks.yaml`은 프로젝트 간 Milestone 잠금 인덱스다. 외부 의존 잠금을 생성하거나 동기화해야 하면 파일이 없어도 디렉터리와 파일을 만든다.
- entry는 `id`, `locked`, `rely-on[].target`, `rely-on[].status`, `rely-on[].note`만 사용한다.
- `locks.yaml`은 root sequence block style을 기본으로 작성한다. 예: `- id: ...` 아래에 `locked`, `rely-on`을 둔다.
- `id`는 기본적으로 `<잠긴-project>:<잠긴-milestone-slug>`로 만든다.
- `locked`와 `rely-on[].target`은 `<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md` 형식으로 기록한다.
- Milestone 경로가 `agent-roadmap/...` 상대 경로이면 현재 프로젝트명을 prefix로 붙인다. workspace 하위 절대/상대 경로이면 workspace 바로 아래 디렉터리명을 project로 삼고, 그 뒤 `agent-roadmap/...` 경로를 붙인다.
- `locked`는 잠긴 Milestone, `rely-on.target`은 선행 조건 Milestone이다. 둘 다 같은 workspace의 어느 활성 Phase 하위 Milestone이어도 된다. 의존 대상이 `current.md`에 있어야 한다고 가정하지 않는다.
- 의존 Milestone 확정 순서:
  1. 사용자가 명시한 `<project>:agent-roadmap/phase/.../milestones/<slug>.md` 또는 파일 경로
  2. 사용자가 명시한 프로젝트와 Milestone slug
  3. 사용자가 명시한 프로젝트와 Milestone 제목의 정규화 일치
  4. 잠긴 Milestone 문서의 `선행 <project> Milestone: ...`, `관련 <project> Milestone: ...`, `외부 의존 잠금: ...`에 적힌 slug/제목 힌트
  5. 프로젝트명만 있고 Milestone 힌트가 없을 때만 해당 프로젝트 로컬 `current.md`의 활성 Milestone 단일 후보
- 정규화 비교는 소문자 변환, backtick/따옴표 제거, 영문/숫자가 아닌 연속 문자를 `-` 하나로 치환, 앞뒤 `-` 제거 후 비교한다. 정규화한 힌트는 Milestone 파일 slug와 정규화한 제목 둘 다에 대조한다.
- 2-4번 탐색은 대상 프로젝트의 `agent-roadmap/phase/*/milestones/*.md` 활성 문서만 대상으로 한다. archive 문서는 사용자가 archive 경로를 명시한 경우 외에는 읽거나 후보로 삼지 않는다.
- 후보가 없거나 둘 이상이면 `locks.yaml`을 만들거나 고치지 말고 모호성을 보고한다. 잠금 대상 확정이 제품/범위 결정이면 대상 Milestone의 `구현 잠금 > 결정 필요`로 분리한다.
- 외부 의존 잠금 요청이 있거나, 갱신 대상 Milestone이 `구현 잠금: 잠금`이며 문서에 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `.agent-roadmap-sync/locks.yaml`을 upsert한다. resolvable한 외부 의존 문구를 Milestone에 남기고 lock entry를 누락하지 않는다.
- 외부 의존 잠금을 만들 때 대상 Milestone의 `구현 잠금`은 `잠금`으로 둔다.
- 새 `rely-on.status`는 선행 Milestone 상태에서 파생한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태거나 상태를 확인할 수 없으면 `disable`이다.
- 같은 `id` entry를 upsert할 때 기존 `rely-on` 항목을 삭제하지 않는다. 같은 `rely-on.target`만 status/note를 갱신하고, 없는 target은 추가하며, `locked` 경로가 바뀐 경우에만 `locked`를 갱신한다.
- `locks.yaml`이 있고 Milestone을 갱신하거나 archive할 때는 대상 Milestone identity로 `agent-ops/bin/roadmap-dependency-checker.sh --find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다.
- find 결과가 `none`이면 결과 보고의 `Workspace 잠금`에 `관련 lock 없음`을 남긴다. 외부 의존 잠금 생성/동기화 요청이 아니라면 `locks.yaml`을 새로 만들거나 수정하지 않는다.
- 이 스킬이 갱신한 Milestone identity가 어느 entry의 `rely-on.target`과 일치하면 해당 `rely-on.status`를 Milestone 상태 기준으로 동기화한다. `[검토중]` 또는 `[완료]`이면 `enable`, 그 외 상태면 `disable`이다.
- 이 스킬이 갱신하거나 선택한 Milestone identity가 어느 entry의 `locked`와 일치하면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고의 `Workspace 잠금`에 `런타임 해제 대기` 또는 `미충족`으로 남긴다.
- archive 모드에서는 파일 이동 전에 대상 Milestone의 활성 경로 identity를 보존하고, 그 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다. 보존한 identity가 어느 entry의 `rely-on.target`과 일치하고 Milestone 상태가 `[완료]`이면 archive 이동 전에 해당 `rely-on.status`를 `enable`로 바꾼다.
- archive 모드에서 보존한 identity가 어느 entry의 `locked`와 일치하면 archive 이동 전에 모든 `rely-on.status`가 `enable`인지 확인해 결과 보고에 남긴다. 미충족이면 archive 자체를 막지 않지만 `Workspace 잠금: 미충족`으로 보고한다.
- 모든 `rely-on.status`가 `enable`이어도 여기서 다른 프로젝트 Milestone을 직접 해제하지 않는다. 잠금 해제 실행은 런타임이 별도 `update-roadmap` 호출로 처리한다.

## 완료 리뷰와 검토중 상태

- Task 완료 또는 Milestone 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`인지 확인하고, `구현 잠금`이 `해제`이며 미완료 `결정 필요` 항목이 없는지 함께 확인한다.
- 기능 Task가 모두 충족되어도 `구현 잠금`이 남아 있으면 Milestone을 `[검토중]`으로 바꾸지 않는다. `완료 리뷰` 또는 `작업 컨텍스트`에 잠금 차단 항목을 남기고, 잠금 해소 roadmap 갱신을 먼저 요구한다.
- 기능 Task와 구현 잠금이 모두 충족된 것으로 보이면 Milestone을 `[완료]`로 바로 바꾸거나 archive로 이동하지 말고 `[검토중]`으로 바꾼다.
- `[검토중]`으로 바꿀 때는 Milestone 문서의 `완료 리뷰` 섹션을 만들거나 갱신한다.
- `완료 리뷰`에는 `상태: 검토중`, `요청일`, 완료 근거 1~3줄, 남은 차단 항목, 리뷰 코멘트를 남긴다. 에이전트가 확정할 수 없는 결정 항목은 완료 리뷰가 아니라 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.
- `구현 잠금`이 해제되어 있지 않으면 `[완료]`로 전환하거나 archive하지 않는다. 잠금 해소 roadmap 갱신을 먼저 요구한다.
- 기능 Task, 검증, 구현 잠금이 모두 충족되어 있으면 `완료 리뷰`를 `상태: 통과`로 바꾸고 Milestone 상태를 `[완료]`로 전환한 뒤 archive 모드를 수행할 수 있다.
- 보완 근거가 있으면 `완료 리뷰`를 `상태: 보완 필요`로 바꾸고 Milestone 상태를 `[진행중]`으로 되돌린다. 이때 보완 방향을 `완료 리뷰` 또는 `작업 컨텍스트`에 남기며 별도 reopen 상태는 만들지 않는다.
- 보류 또는 폐기 근거가 있으면 `완료 리뷰`와 Milestone 상태를 각각 `보류`/`[보류]`, `폐기`/`[폐기]`로 맞춘다. `[폐기]`는 archive 대상이 될 수 있다.
- Phase는 하위 Milestone이 모두 `[완료]` 또는 `[폐기]`로 정리되고 Phase 목표도 충족된 것으로 보일 때 `[완료]` 또는 `[폐기]`로 archive한다.

### agent-ui 코드 동기화 Milestone 완료 리뷰

- 이 절은 `sync-agent-ui`가 코드 작업을 `milestone-required`로 라우팅했거나 사용자가 명시해 Milestone `완료 리뷰`에 `agent-ui 상태 반영: 대기`가 있는 경우에만 적용한다.
- agent-ui 문서만 갱신한 Milestone, 작은 `direct-sync` 작업, 일반 `plan-required` 작업, `agent-ui 상태 반영: 해당 없음`인 Milestone에는 적용하지 않는다.
- 기존 Milestone에 `agent-ui 상태 반영` 항목이 없으면 `해당 없음`으로 취급한다. 문서 구조 보정 또는 해당 Milestone 갱신 범위에 포함될 때만 `agent-ui 상태 반영: 해당 없음`을 보강한다.
- 사용자가 "이 Milestone을 종료해도 될지 검토", "마일스톤 완료 검토", "종료 검토"처럼 완료 리뷰를 요청했거나 `review-state=통과`로 갱신할 때 적용한다.
- agent-ui 코드 동기화 Milestone이 완료 리뷰 `통과` 조건을 충족하면 `[완료]` 전환 또는 archive 전에 관련 agent-ui view/component/frame 문서의 `status`를 `구현됨`으로 반영할 수 있다.
- 상태 반영은 완료 evidence가 직접 가리키는 agent-ui 활성 문서에만 적용한다. Milestone 전체 완료만을 근거로 `agent-ui/definition/**` 전체를 일괄 `구현됨`으로 바꾸지 않는다.
- 각 대상 문서는 실제 존재하는 code evidence path와 최종 검증 근거가 있어야 `구현됨`으로 바꾼다. 근거가 없으면 `계획` 또는 기존 상태를 유지하고 완료 리뷰를 `보완 필요`로 둔다.
- agent-ui 상태 반영은 `update-agent-ui`의 문서 갱신 규칙을 따르고, 반영 후 `validate-agent-ui`로 정합성을 확인한다. 이 단계는 이미 완료된 코드 반영의 문서 상태 갱신이므로 `sync-agent-ui`를 새로 실행하지 않는다.
- status/code evidence 반영과 `validate-agent-ui`가 모두 통과하면 Milestone `완료 리뷰`의 `agent-ui 상태 반영`을 `완료`로 바꾼다.
- 근거 부족, 미해결 USER_REVIEW, 또는 `validate-agent-ui` 실패로 반영하지 못하면 Milestone `완료 리뷰`의 `agent-ui 상태 반영`을 `차단: <사유>`로 바꾸고 `상태: 보완 필요`를 남긴다.
- `validate-agent-ui`가 FAIL이거나 현재 범위에 미해결 `agent-ui/USER_REVIEW.md`가 있으면 Milestone을 `[완료]`로 전환하지 않고 완료 리뷰를 `보완 필요`로 둔다.
- `agent-ui 상태 반영: 대기`가 아닌 Milestone에서는 완료 리뷰 중 agent-ui status를 변경하지 않는다.

## Milestone task group 연동

- 런타임 완료 이벤트의 `origin-task`에서 `agent-task/` 다음 첫 path segment가 `m-<milestone-slug>`이면 Milestone 기반 plan/review 완료에서 온 요청으로 본다. `origin-task`는 archive 이동 전 active task 경로 또는 런타임이 그 형태로 정규화한 경로를 사용한다.
- `<milestone-slug>`는 활성 `agent-roadmap/phase/*/milestones/<milestone-slug>.md`에서 정확히 하나만 찾아야 한다. archive Milestone은 target 후보가 아니다.
- target이 없거나 둘 이상이면 Milestone 내용을 추정해 수정하지 말고 target 불명확으로 보고한다.
- target이 확정되어도 `complete-log` 입력이 없거나 해당 파일에 `Roadmap Completion` 섹션이 없으면 Milestone 기능 Task를 체크하지 않고 no-op으로 보고한다. 일반 `m-*` 완료 이벤트만으로 Task를 추정해 체크하지 않는다.
- `Roadmap Completion` 섹션이 있으면 Milestone 경로가 target과 일치하는지, Completed task ids의 각 id가 해당 Milestone의 기존 기능 Task id 하나와 정확히 일치하는지 확인한다. 하나라도 일치하지 않으면 수정하지 말고 target 불일치로 보고한다.
- target Milestone이 `SDD: 필요`이면 런타임 완료 이벤트의 `complete-log`에 있는 `Roadmap Completion`과 최종 검증 evidence가 SDD `Evidence Map`을 충족해야 한다. 사용자가 `update-roadmap` 요청에 별도 evidence를 명시해 수동 반영을 요구한 경우에만 Evidence Map 충족 근거를 보조 근거로 사용할 수 있다. 근거가 없으면 `Roadmap Completion`이 있어도 Task를 체크하지 않고 SDD evidence 부족으로 보고한다.
- 일치하면 PASS evidence, `complete.log`, final archive path, archived plan/review log 경로, code-review 결과 요약을 근거로 `Roadmap Completion`에 적힌 기능 Task만 `[x]`로 갱신한다. target routing 자체는 완료 이벤트의 `m-<milestone-slug>` task group과 `complete.log`의 `Roadmap Completion` 섹션으로 결정한다.
- 갱신 후 모든 기능 Task와 Task 안에 명시된 검증이 충족되어도 `구현 잠금`이 해제되어 있지 않으면 `[검토중]` 전환을 하지 않고 잠금 차단으로 보고한다. 기능 Task와 구현 잠금이 모두 충족될 때만 `[검토중]` 전환과 `완료 리뷰` 요청 규칙을 적용한다.
- target Milestone이 `[스케치]`이면 완료 이벤트를 반영하지 말고 상태 불일치로 보고한다. `[스케치]`는 Milestone 기반 `agent-task` 완료 이벤트의 target이 될 수 없다.

## 삽입 단위 정책

| 삽입 단위 | 사용 기준 |
|-----------|-----------|
| 새 Phase | 독립적인 제품 진화 단계와 여러 Milestone 묶음이 필요하다 |
| 새 Milestone | 독립적인 목표와 기능 Task 묶음이 필요하고 Phase 흐름에 의미 있는 경계를 만든다 |
| 새 Epic | 기존 Milestone 안에서 여러 Task를 묶는 상위 capability 또는 산출물이다 |
| 새 Task | 기존 Epic 아래에 들어가는 완료 가능한 capability 또는 산출물이다. 검증이 필요한 경우에만 같은 Task 안에 붙인다 |
| 하위 작업 | 기존 Task를 완성하기 위한 구현 세부다. Milestone `기능`에는 하위 체크박스로 만들지 않고, plan 내부 체크리스트나 기존 Task의 `검증:`/설명 보강으로 다룬다 |
| 작업 컨텍스트/TODO | 에이전트가 확정할 수 없는 결정 또는 조사/확인이 먼저 필요해 기능 Task로 확정하기 어렵다 |

- 먼저 요청 내용의 규모를 판정한다. 배치 위치를 찾기 전에 `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 단위를 고른다.
- 요청이 방향성, 문제의식, 컨셉, 운영 원칙 수준이고 기능 Task나 실행 범위가 아직 부족하면 새 항목의 상태는 `[스케치]`로 둔다.
- `[스케치]` Phase/Milestone을 만들 때는 `승격 조건`에 `[계획]`으로 전환하기 위해 필요한 정의, 결정, 경계, 후속 구현 Milestone 후보를 체크리스트로 남긴다.
- 가장 작은 충분한 단위 원칙을 따른다. 애매하면 새 Phase나 새 Milestone으로 키우지 말고, 기존 Milestone의 Epic/Task에 넣을 수 있는지 먼저 확인한다.
- 위치 지정이 있으면 anchor의 레벨을 먼저 확인한다.
- `<epic-id> 아래`는 해당 Epic 아래 Task로 넣는다.
- `<item-id> 앞/뒤`는 같은 Epic 안의 형제 Task로 넣는다.
- `<item-id> 아래`는 해당 Task의 설명 또는 `검증:`을 보강한다. 구현 세부나 테스트만 따로 떼어낸 하위 체크박스는 Milestone `기능` 아래에 만들지 않는다.
- `<phase-name> 안`은 새 Milestone 또는 기존 Milestone/Epic/Task 중 작업 성격에 맞는 단위로 배치한다.
- 위치 지정이 없으면 `auto`로 본다. 로컬 `current.md`의 활성 창만으로 결정하지 않고, 필요한 경우 `ROADMAP.md`의 Phase 흐름까지 확인해 완료/검토중/진행중/계획/스케치 Phase를 비교한다.
- target 없는 신규 추가 요청은 요청 문장, 관련 파일/도메인 힌트, Phase 목표, Milestone 목표, 기존 Epic/Task, 선후 의존성, 상태, 활성 창을 비교해 가장 자연스러운 위치를 자동 판단한다.
- 자동 배치 후보가 여러 개이면 1순위와 2순위 후보를 비교하고, 선택한 Phase/Milestone/Epic/Task와 밀린 후보의 이유를 짧게 남긴다.
- 관련성이 비슷하면 `[진행중]` Milestone을 `[계획]` Milestone보다 우선하되, `[검토중]` Milestone은 리뷰 보완 요청이 아닌 신규 작업의 기본 배치 대상으로 삼지 않는다.
- 자동 배치한 경우 결과 보고에 선택한 삽입 단위, 위치, 판단 근거, 비교한 후보를 짧게 남긴다.
- 사용자 지정 위치가 Phase 목표, Milestone 범위 제외, 선후 의존성과 충돌하면 충돌을 보고하고 수정하지 않는다. 제품/범위 결정으로 해소해야 하면 대상 Milestone의 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.

## 레벨별 탐색과 upsert 정책

target 없는 신규 추가 요청은 append가 아니라 upsert로 처리한다.

1. **요청 정규화**
   - 요청 문장에서 기능명, 목표, 산출물, 관련 경로/도메인, 완료 기대, 제약, 명시 anchor를 뽑는다.
   - 사용자가 Phase/Milestone/Epic/Task/id/path를 명시했으면 그 anchor를 우선 후보로 둔다.

2. **규모 판정**
   - 여러 Milestone을 묶는 제품/운영 단계면 Phase 규모다.
   - 독립 목표, 기능 Task 묶음, 여러 Epic이 필요한 결과면 Milestone 규모다.
   - 컨셉은 충분히 크지만 구현 가능한 목표/범위/기능 Task가 아직 없으면 `[스케치]` Phase 또는 Milestone 후보로 둔다.
   - 한 Milestone 안의 capability 묶음이면 Epic 규모다.
   - Epic 아래에서 완료 가능한 단일 capability 또는 산출물이면 Task 규모다. 검증이 필요한 경우에만 같은 Task 안에 포함한다.
   - Task를 완성하기 위한 구현 세부면 subtask 규모다. roadmap에는 하위 체크박스로 기록하지 않고, 구현 계획 내부 또는 기존 Task 보강으로 처리한다.
   - 조사, 결정, 보류 질문이면 작업 컨텍스트/TODO 규모다.

3. **레벨별 탐색**
   - Phase 후보를 먼저 찾는다. 로컬 `current.md`의 활성 Phase를 우선 보되, target이 없거나 활성 범위 밖 가능성이 있으면 `ROADMAP.md`의 Phase 흐름도 본다.
   - 선택한 Phase 안에서 Milestone 후보를 찾는다. 활성 Milestone을 우선 보되, 요청이 계획 Milestone 목표와 더 직접 맞으면 계획 Milestone도 후보로 둔다.
   - 선택한 Milestone 안에서 Epic 후보를 찾는다. `기능`의 Epic heading, 목표 설명, Task 묶음을 비교한다. 기존 문서가 `필수 기능`을 쓰면 갱신 시 `기능`으로 정규화한다.
   - 선택한 Epic 안에서 Task 후보를 찾는다. item-id, 문장 의미, Task 안의 검증 문구, 관련 경로를 비교한다.
   - archive 문서는 기본 탐색 대상이 아니다. 사용자가 과거 기록 비교를 명시했거나 완료 내용 확인이 필요한 경우에만 `ROADMAP.md` 또는 `PHASE.md`의 archive 링크를 따라 필요한 문서만 읽는다.

4. **중복/업데이트 판정**
   - 같은 id, 같은 제목, 같은 목표, 같은 관련 경로, 같은 Task 안의 검증 문구, 또는 같은 산출물을 다루면 동일/유사 후보로 본다.
   - 동일 항목이면 새로 만들지 않고 기존 Phase/Milestone/Epic/Task를 업데이트한다.
   - 기존 항목의 범위를 보강하는 내용이면 해당 항목의 설명, Task 안의 검증 문구, 작업 컨텍스트 중 알맞은 곳에 병합한다.
   - 기존 항목과 충돌하거나 범위 제외를 건드리면 충돌을 보고하고 수정하지 않는다. 제품/범위 결정으로 해소해야 하면 대상 Milestone의 `구현 잠금 > 결정 필요` 또는 SDD `USER_REVIEW.md`로 분리한다.
   - 같은 레벨에 적절한 후보가 없을 때만 새 항목을 만든다. 새 항목도 판정한 규모보다 크게 만들지 않는다.
   - 부모 레벨 후보는 있고 판정 규모의 항목만 없으면, 부모 아래에 판정 규모의 새 항목을 만든다. 부모 레벨도 없을 때만 필요한 부모 항목을 함께 만든다.

## archive 정책

### Milestone archive

- 대상 Milestone이 `[완료]` 또는 `[폐기]`인지 확인한다.
- `[검토중]` Milestone은 archive하지 않는다. 완료 근거가 있어도 `구현 잠금`이 해제되어 있지 않으면 `[완료]`로 바꾸지 않는다. 명시적인 폐기 근거가 있으면 `[폐기]`로 바꾼 뒤 archive할 수 있다.
- `[완료]` archive 대상은 `구현 잠금`이 해제되어 있고 미완료 `결정 필요` 항목이 없어야 한다. `[폐기]` archive는 이 완료 잠금 조건을 요구하지 않는다.
- archive 이동 전에 대상 Milestone의 활성 경로 identity(`<project>:agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`)를 보존한다.
- `locks.yaml`이 있으면 보존한 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 실행해 이 Milestone이 `locked`인지, `rely-on.target`인지, 관련 lock이 없는지 먼저 확인한다.
- 보존한 identity가 `.agent-roadmap-sync/locks.yaml`의 `rely-on.target`에 있으면 archive 이동 전에 상태를 동기화한다. `[완료]`이면 `enable`, `[폐기]`이면 `disable`이다.
- 보존한 identity가 `.agent-roadmap-sync/locks.yaml`의 `locked`에 있으면 archive 이동 전에 의존 조건 충족 여부를 결과 보고에 남긴다.
- find 결과가 `none`이면 `Workspace 잠금: 관련 lock 없음`으로 보고한다.
- 대상 파일을 `agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md`에서 `agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md`로 이동한다.
- 활성 SDD 디렉터리 `agent-roadmap/sdd/<phase-slug>/<milestone-slug>/`가 있으면 `agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/`로 이동한다. `USER_REVIEW.md`가 남아 있으면 archive하지 말고 해결 필요로 보고한다.
- 활성 `PHASE.md`의 Milestone 흐름에는 `[완료]` 또는 `[폐기]` 항목을 남기고, 경로는 archive 경로로 바꾼다.
- 로컬 `current.md`의 활성 Milestone에서는 제거한다.
- `ROADMAP.md`는 Phase 상태나 경로가 바뀌지 않으면 수정하지 않는다.
- 이동한 archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.

### Phase archive

- Phase 전체가 `[완료]` 또는 `[폐기]`인지 확인한다.
- `[검토중]` Phase는 archive하지 않는다. 완료 또는 폐기 근거가 충족되면 먼저 `[완료]` 또는 `[폐기]`로 바꾼 뒤 archive한다.
- `agent-roadmap/phase/<phase-slug>/PHASE.md`를 `agent-roadmap/archive/phase/<phase-slug>/PHASE.md`로 이동한다.
- 해당 Phase의 하위 Milestone도 `archive/phase/<phase-slug>/milestones/` 아래로 이동한다.
- `ROADMAP.md`의 Phase 흐름에는 해당 Phase 항목을 남기고, 상태와 경로를 archive `PHASE.md`로 바꾼다.
- 로컬 `current.md`의 활성 Phase와 활성 Milestone에서는 해당 Phase와 하위 Milestone을 제거한다.
- archive 문서는 스냅샷으로 보존하고 최신 템플릿에 맞춰 재포맷하지 않는다.

## 실행 절차

1. **갱신 범위 결정**
   - 요청에서 mode, 대상 Phase/Milestone, placement, placement-unit을 추론한다.
   - 런타임 완료 이벤트의 `origin-task` task group이 `m-<milestone-slug>`이면 `target-milestone`을 활성 Milestone 경로 매칭으로 확정한다.
   - 런타임 완료 이벤트가 `complete-log`를 전달하면 파일을 읽고 `Roadmap Completion` 섹션 유무와 Completed task ids를 확인한다. 섹션이 없으면 Milestone 기능 Task 체크는 no-op이다. SDD 대상 Milestone이면 SDD `Evidence Map` 충족 여부도 확인한다.
   - 구조 전환, 템플릿 보정, current 동기화는 `sync`로 본다.
   - 완료/폐기 근거가 충족된 이동은 `archive`로 본다.
   - 완료 리뷰 요청에서 대상 Milestone의 `완료 리뷰`가 `agent-ui 상태 반영: 대기`인지 확인한다. 항목이 없거나 `대기`가 아니면 agent-ui 상태 반영 단계를 적용하지 않는다.
   - 새 기능 배치, Epic/Task 추가는 `milestone` 또는 `phase`로 본다.
   - "로드맵에 추가"처럼 target이 없는 신규 작업 요청은 `placement=auto`, `placement-unit=auto`, `new-feature=<요청 내용>`으로 본다.
   - 외부 의존 잠금 요청이면 `workspace-lock` 갱신으로 본다.
   - 외부 의존 잠금 요청이 아니어도, 갱신 대상 Milestone이 `구현 잠금: 잠금`이고 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 `workspace-lock` 동기화 후보로 본다.
   - 외부 의존 잠금 요청에서 "현재 마일스톤" 또는 target 생략 표현이 있으면 로컬 `current.md`의 활성 Milestone 단일 후보를 잠긴 대상으로 확정한다.
   - 의존 대상은 명시 경로, 명시 slug, 명시 제목, 잠긴 Milestone 문서의 선행 Milestone 힌트, 대상 프로젝트 로컬 `current.md` 단일 후보 순서로 확정한다.
   - 잠긴 대상 또는 의존 대상 후보가 없거나 둘 이상이면 `locks.yaml`을 수정하지 말고 모호성을 보고한다. 잠금 대상 확정이 제품/범위 결정이면 대상 Milestone의 `구현 잠금 > 결정 필요`로 분리한다.

2. **요청 정규화와 규모 판정**
   - 요청에서 기능명, 목표, 관련 경로, 명시 anchor, 완료 기대, 제약을 추출한다.
   - `phase`, `milestone`, `epic`, `task`, `subtask`, `context` 중 가장 작은 충분한 규모를 판정한다.
   - 동일/유사 항목이 이미 있으면 신규 추가가 아니라 업데이트 후보로 기록한다.

3. **레벨별 후보 탐색**
   - 로컬 `current.md`의 활성 Phase와 활성 Milestone 후보를 확인한다.
   - target이 명시된 경우 대상 Phase의 `PHASE.md`를 읽고 Milestone 흐름과 Phase 경계를 확인한다.
   - target이 없거나 활성 창 밖 배치 가능성이 있으면 `ROADMAP.md`의 Phase 흐름을 확인하고, 관련성이 높은 Phase 문서를 읽는다.
   - 대상 또는 후보 Milestone 문서의 목표, 상태, 승격 조건, 범위, 기능 Task, 완료 리뷰, 범위 제외, 구현 잠금을 확인한다. SDD가 필요한 Milestone이면 SDD 문서 링크와 사용자 리뷰 상태도 확인한다. 기존 문서에 `필수 기능`/`완료 기준`이 분리되어 있으면 갱신 범위에서 `기능` Task로 흡수할 후보를 기록한다.
   - Phase -> Milestone -> Epic -> Task 순서로 내려가며 같은 레벨의 동일/유사 후보를 먼저 찾는다.
   - 로컬 `current.md`에 archive 경로가 있으면 읽지 말고 제거 대상으로 기록한다.
   - 필요한 경우에만 `ROADMAP.md`를 읽어 전체 Phase 흐름을 확인한다.

4. **스케치 승격 판단**
   - `target-status=[계획]`, `mode=concretize`, 또는 사용자가 "구체화", "계획으로 올려"처럼 요청하면 `[스케치] -> [계획]` 승격 검토로 본다.
   - 대상이 `[스케치]`가 아니면 일반 상태 갱신이나 Milestone 갱신으로 처리한다.
   - 대상이 `[스케치]`이면 `승격 조건`, `구현 잠금`, SDD 필요 여부, `목표`, `범위`, `기능`, `작업 컨텍스트`를 확인한다.
   - `승격 조건` 체크리스트가 남아 있거나 구현 계획에 직접 필요한 결정 항목이 남아 있으면 상태를 `[스케치]`로 유지하고, 부족한 항목을 `승격 조건` 또는 `결정 필요`에 보강한다.
   - 구현 가능한 목표, 범위, 기능 Task, 필요한 결정 항목, 후속 구현 단위가 정리되면 상태를 `[계획]`으로 전환하고, `승격 조건`은 충족 요약으로 남기거나 `- 없음`으로 정리한다.
   - 승격은 구현 완료가 아니므로 `기능` Task를 자동 완료 처리하지 않는다.

5. **변경 내용 작성**
   - `ROADMAP.md`는 전체 목표, Phase 흐름, 로딩 정책이 바뀔 때만 수정한다.
   - 로컬 `current.md`는 활성 Phase/Milestone 창이 바뀔 때 수정한다.
   - `.gitignore`의 Agent-Ops 관리 block에 `agent-roadmap/current.md`가 있는지 확인하고 없으면 추가한다.
   - `PHASE.md`는 Phase 목표, 상태, Milestone 흐름, Phase 경계가 바뀔 때 수정한다.
   - Milestone 문서는 목표, 상태, 승격 조건, 구현 잠금, 범위, Epic/Task, Task 안의 검증 문구, 완료 리뷰, 범위 제외, 작업 컨텍스트가 바뀔 때 수정한다.
   - 신규 또는 갱신 Milestone이 SDD 대상이면 `구현 잠금`에 `SDD: 필요`, 해당 Milestone 파일 위치 기준 `SDD 문서` Markdown 링크, 잠금 해제 조건을 남기고 같은 흐름에서 `roadmap-sdd create`로 SDD 본문을 작성한다. 사용자 결정이 필요 없고 gate가 충족되면 SDD와 Milestone 잠금을 함께 해제한다.
   - SDD 대상이 아니면 `구현 잠금`에 `SDD: 불필요`와 짧은 사유를 남긴다.
   - 동일/유사 후보가 있으면 기존 항목을 업데이트하고 중복 항목을 만들지 않는다.
   - 새 Milestone은 해당 Phase의 `milestones/` 아래에 만든다.
   - 새 `[스케치]` Milestone은 `승격 조건` 섹션을 포함하고 `구현 잠금`은 `잠금`으로 둔다.
   - 새 Epic은 `기능` 아래 `### Epic: [epic-id] <이름>`으로 만든다.
   - 새 Task는 관련 Epic 아래 `- [ ] [item-id] 설명`으로 만든다. 검증이 필요한 경우에만 같은 항목에 `검증: <명령/확인 방법/기대 결과>`를 붙인다.
   - 새 항목은 레벨별 탐색에서 적절한 기존 후보가 없을 때만 만든다.
   - 완료 체크는 evidence가 있을 때만 `[x]`로 바꾼다.
   - 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이어도 `구현 잠금`이 `해제`가 아니거나 미완료 `결정 필요` 항목이 있으면 Milestone 상태를 `[검토중]`으로 바꾸지 않는다. `완료 리뷰` 또는 `작업 컨텍스트`에 잠금 차단 항목을 남긴다.
   - 모든 기능 Task와 Task 안에 명시된 검증이 evidence와 함께 `[x]`이고 `구현 잠금`도 해제되어 있으면 Milestone 상태를 `[검토중]`으로 바꾸고 `완료 리뷰`에 완료 근거와 남은 차단 항목을 남긴다.
   - `[검토중]` 전환만으로 archive 이동, 로컬 `current.md` 제거, archive 링크 변경을 수행하지 않는다.
   - `agent-ui 상태 반영: 대기`인 Milestone의 완료 리뷰가 `통과` 후보이면 `[완료]` 전환 전에 관련 agent-ui 문서의 `status`를 `구현됨`으로 갱신할 수 있는지 확인한다. 대상 문서, code evidence, 최종 검증 근거, `validate-agent-ui` 결과가 모두 충족될 때만 반영하고 `agent-ui 상태 반영: 완료`로 바꾼다.
   - agent-ui 상태 반영이 필요한데 근거가 부족하거나 `validate-agent-ui`가 통과하지 않으면 Milestone 상태를 `[진행중]` 또는 `[검토중]`으로 유지하고 `완료 리뷰: 보완 필요`와 `agent-ui 상태 반영: 차단: <사유>`를 남긴다.
   - 기능 Task, 검증, 구현 잠금, 완료 근거가 모두 충족되면 `[검토중]`을 `[완료]`로 전환하고 archive 모드를 수행할 수 있다.
   - `locks.yaml`이 있으면 갱신 대상 Milestone identity로 `--find-milestone "<identity>" both "<locks-file>"`를 실행해 이 Milestone이 `locked`인지, `rely-on.target`인지, 관련 lock이 없는지 확인한다.
   - archive 모드이면 파일 이동 전 active Milestone identity를 보존하고, 그 identity로 `--find-milestone "<identity>" both "<locks-file>"`를 먼저 실행한다.
   - 외부 의존 잠금 요청 또는 외부 의존 컨텍스트 동기화가 필요하면 대상 Milestone의 `구현 잠금`을 `잠금`으로 두고 `.agent-roadmap-sync/locks.yaml`을 upsert한다.
   - `.agent-roadmap-sync/locks.yaml`이 없으면 `.agent-roadmap-sync/` 디렉터리와 `locks.yaml` 파일을 만든다.
   - `locks.yaml` entry는 `id=<잠긴-project>:<잠긴-milestone-slug>`, `locked=<잠긴-project>:<잠긴-milestone-path>`, `rely-on.target=<의존-project>:<의존-milestone-path>`, `rely-on.status=<enable|disable>`, `rely-on.note=<사용자 요청 요약>`으로 기록한다.
   - 같은 `id` entry가 있으면 기존 `rely-on` 목록을 보존하고 같은 `target`만 갱신하거나 새 `target`을 추가한다.
   - find 결과가 `none`이면 결과 보고의 `Workspace 잠금`에 `관련 lock 없음`을 남긴다.
   - 갱신한 Milestone identity와 일치하는 `rely-on.target`은 Milestone 상태 기준으로 `enable` 또는 `disable`을 동기화한다.
   - archive 모드에서 보존한 active Milestone identity와 일치하는 `rely-on.target`도 archive 이동 전에 Milestone 상태 기준으로 `enable` 또는 `disable`을 동기화한다.
   - 갱신하거나 선택한 Milestone identity와 일치하는 `locked` entry가 있으면 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고에 남긴다.
   - archive 모드에서 보존한 active Milestone identity와 일치하는 `locked` entry도 archive 이동 전에 모든 `rely-on.status`가 `enable`인지 확인하고 결과 보고에 남긴다.

6. **검증**
   - 로컬 `current.md`의 활성 Phase/Milestone 경로가 실제 파일을 가리키는지 확인한다.
   - 로컬 `current.md`의 활성 항목이 archive 경로를 가리키지 않는지 확인한다.
   - 로컬 `current.md`의 활성 항목이 `[완료]` 또는 `[폐기]` 상태로 남아 있지 않은지 확인한다.
   - `agent-roadmap/current.md`가 git 추적 대상으로 남아 있지 않은지 확인한다.
   - `ROADMAP.md`의 Phase 경로가 실제 `PHASE.md` 파일을 가리키는지 확인한다.
   - 각 `PHASE.md`의 Milestone 경로가 실제 파일을 가리키는지 확인한다.
   - 상태 표기가 표준값인지 확인한다.
   - `[스케치]` Milestone에 `승격 조건`이 있고 `구현 잠금`이 `잠금`인지 확인한다.
   - `[계획]` 이상 Milestone에 `승격 조건` 섹션이 없더라도 오류로 보지 않는다. 섹션이 있으면 `- 없음` 또는 승격 충족 요약인지 확인한다.
   - `[스케치] -> [계획]` 전환을 수행했다면 승격 조건 해소 근거가 Milestone 내용이나 결과 보고에 남았는지 확인한다.
   - `[검토중]` Milestone이 archive 경로로 이동되지 않았는지 확인한다.
   - 모든 기능 Task와 Task 안에 명시된 검증이 `[x]`인 Milestone은 `구현 잠금`이 해제되어야 `[검토중]`이 될 수 있다. 잠금이 남아 있으면 `완료 리뷰` 또는 `작업 컨텍스트`에 잠금 차단 항목이 있는지 확인한다.
   - `[검토중]` Milestone에는 `완료 리뷰` 섹션과 완료 근거/남은 차단 항목이 있는지 확인한다.
   - `agent-ui 상태 반영: 대기`인 Milestone을 `[완료]`로 전환하는 경우, 완료 evidence가 가리키는 agent-ui 문서의 status/code evidence 반영 여부와 `validate-agent-ui` 결과가 완료 리뷰에 남았는지 확인한다.
   - `agent-ui 상태 반영: 대기`가 아닌 Milestone 완료 리뷰에서 agent-ui 문서 status를 변경하지 않았는지 확인한다.
   - 각 Milestone의 `구현 잠금`에 SDD 필요 여부와 사유가 있는지 확인한다.
   - `SDD: 필요` Milestone은 SDD 문서 링크, SDD 파일 존재, 잠금 해제 조건, SDD 사용자 리뷰 상태가 일관되는지 확인한다. 사용자가 명시적으로 SDD 생성을 뒤로 미루지 않았는데 SDD 파일이 없으면 검증 실패로 본다.
   - Epic heading과 Task id 형식이 맞는지 확인한다.
   - 요청 규모가 판정되었고 결과 보고에 남았는지 확인한다.
   - 동일/유사 기존 항목을 검색했고 신규/업데이트 판정이 결과 보고에 남았는지 확인한다.
   - 자동 배치한 신규 작업이면 선택한 후보와 밀린 후보의 근거가 결과 보고에 포함되는지 확인한다.
   - `.agent-roadmap-sync/locks.yaml`을 갱신했다면 `locked`, `rely-on.target`, `rely-on.status`가 채워졌는지 확인한다.
   - 갱신 대상 Milestone에 resolvable한 외부 의존 잠금/선행 Milestone 컨텍스트가 있으면 해당 lock entry가 존재하는지 확인한다.
   - 갱신 대상 Milestone identity가 `locked` 또는 `rely-on.target` 어느 쪽에 있든 결과 보고의 `Workspace 잠금`에 반영했는지 확인한다.
   - `locks.yaml`이 있는데 갱신 대상 Milestone identity가 `locked`와 `rely-on.target` 어느 쪽에도 없으면 `Workspace 잠금: 관련 lock 없음`으로 보고했는지 확인한다.
   - archive 모드이면 이동 전 active Milestone identity로 `locks.yaml`을 검사하고 필요한 `rely-on.status` 동기화 또는 `관련 lock 없음` 보고를 수행했는지 확인한다.
   - 결과 보고와 갱신한 활성 로드맵 문서의 문서/산출물 포인터가 raw path만 남지 않고 Markdown 링크로 작성되었는지 확인한다.
   - 갱신한 활성 로드맵 문서의 Markdown 링크 target에 템플릿 placeholder가 남지 않았는지 확인한다.
   - `git diff --check`로 공백 오류를 확인한다.

7. **결과 보고**
   - 수정한 파일 목록
   - 요청 규모 판정과 근거
   - Phase -> Milestone -> Epic -> Task 탐색 경로와 후보
   - 신규 추가인지 기존 항목 업데이트인지
   - 변경된 Phase / Milestone / 상태
   - 신규 작업의 삽입 단위와 배치 위치
   - 자동 배치한 경우 비교한 후보와 선택 근거
   - 로컬 current.md 활성 창 변경 사항
   - 완료 리뷰 상태와 남은 차단 항목
   - `agent-ui 상태 반영: 대기`인 Milestone이면 agent-ui status 반영 여부와 validate-agent-ui 결과
   - SDD gate 상태와 사용자 리뷰 필요 여부
   - 런타임 완료 이벤트의 `origin-task`가 `m-<milestone-slug>`이면 원래 active task 경로와 매칭된 target Milestone, `Roadmap Completion` Task ids 또는 no-op 사유
   - archive 모드이면 이동 경로와 남긴 링크
   - 확인 필요로 남긴 항목

## 출력 형식

```markdown
## 업데이트 완료

- 모드: <status | milestone | phase | replan | sync | concretize | archive>
- 수정 파일:
  - [ROADMAP.md](agent-roadmap/ROADMAP.md)
  - [current.md](agent-roadmap/current.md) (local)
  - [PHASE.md](agent-roadmap/phase/<phase-slug>/PHASE.md)
  - [<milestone-slug>.md](agent-roadmap/phase/<phase-slug>/milestones/<milestone-slug>.md)
  - [SDD.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/SDD.md) (SDD 작성/갱신 시)
  - [USER_REVIEW.md](agent-roadmap/sdd/<phase-slug>/<milestone-slug>/USER_REVIEW.md) (SDD 사용자 리뷰 요청 시)
  - [archive PHASE.md](agent-roadmap/archive/phase/<phase-slug>/PHASE.md) 또는 [archive Milestone](agent-roadmap/archive/phase/<phase-slug>/milestones/<milestone-slug>.md) (archive 모드)
  - [archive SDD.md](agent-roadmap/archive/sdd/<phase-slug>/<milestone-slug>/SDD.md) (SDD archive 시)

## 변경 사항

- Phase: <변경 없음 | 요약>
- Milestone: <변경 없음 | 요약>
- 삽입 단위: <Phase | Milestone | Epic | Task | 하위 작업 | 작업 컨텍스트/TODO | 변경 없음>
- 규모 판정: <phase | milestone | epic | task | subtask | context | 변경 없음> - <근거>
- 탐색 경로: <Phase 후보 -> Milestone 후보 -> Epic 후보 -> Task 후보 | 해당 없음>
- 신규/업데이트 판정: <신규 생성 | 기존 항목 업데이트 | 변경 없음> - <동일/유사 후보 근거>
- 배치: <사용자 지정 위치 반영 | 자동 배치 위치와 근거 | 변경 없음>
- 배치 후보: <자동 배치 시 1순위/2순위 후보와 선택/제외 근거 | 해당 없음>
- 템플릿 보정: <ROADMAP | local current.md | PHASE | Milestone | 이미 일치 | 변경 없음>
- 구현 잠금: <잠금 유지 | 잠금 추가 | 해제 | 잠금 차단 | 변경 없음>; 결정 필요: <없음 | 항목 요약>
- SDD gate: <불필요 | 필요-작성 전 | 필요-잠금 | 필요-사용자 리뷰 | 필요-승인됨 | 변경 없음>
- 승격 조건: <해당 없음 | 추가/수정/미충족 유지/충족 요약>
- 완료 리뷰: <변경 없음 | 검토중 | 통과 | 보완 필요 | 보류 | 폐기>
- agent-ui 상태 반영: <해당 없음 | 대기 | 완료 | 차단: 사유 | 변경 없음>
- runtime m-task 라우팅: <해당 없음 | origin-task -> target Milestone | target 불명확>
- Workspace 잠금: <변경 없음 | 관련 lock 없음 | entry 생성/갱신 | rely-on enable | rely-on disable | 미충족 | 런타임 해제 대기>
- 활성 항목: <변경 없음 | Phase/Milestone 추가/제거 요약>
- 아카이브: <변경 없음 | 이동 링크와 남긴 링크>
- 상태: <변경 없음 | 이전 -> 이후>
- Epic/Task: <추가/수정/완료/제거 요약>

## TODO 항목

- <남은 차단 항목 또는 `구현 잠금 > 결정 필요`/SDD `USER_REVIEW.md`로 분리한 항목> (해당 시)
```

## 금지 사항

- 로드맵 파일이 없는데 새 구조를 임의로 만들지 않는다. 이 경우 `create-roadmap`을 사용한다.
- evidence 없이 Phase, Milestone, Epic, Task를 `[완료]` 또는 `[검토중]`으로 처리하지 않는다.
- 전체 `ROADMAP.md`를 모든 작업의 필수 로딩 파일로 만들지 않는다.
- `ROADMAP.md`에 Milestone 상세 작업 체크리스트를 남기지 않는다.
- 로컬 `current.md`에 개인별 현재 작업 위치나 완료 상태를 남기지 않는다.
- 로컬 `current.md`에 `agent-roadmap/archive/**` 경로를 남기지 않는다.
- `agent-roadmap/current.md`를 git 추적 대상으로 만들지 않는다.
- archive 문서를 명시 요청 없이 읽거나 최신 템플릿으로 재포맷하지 않는다.
- 완료된 Phase/Milestone 기록을 삭제하지 않는다.
- Epic과 Task를 별도 파일로 분리하지 않는다.
- Phase와 Milestone 이름 또는 파일명에 순번을 강제하지 않는다.
- 에이전트가 확정할 수 없는 결정 항목이 남아 있는데 Milestone의 `구현 잠금`을 `해제`로 바꾸지 않는다.
- `구현 잠금`이 남아 있는 Milestone을 `[검토중]`, `[완료]`, 또는 완료 archive 대상으로 전환하지 않는다. 명시적인 폐기 근거가 있는 `[폐기]` archive는 허용한다.
- `agent-ui 상태 반영: 대기`가 아닌 Milestone 완료 리뷰에서 agent-ui 문서 status를 변경하지 않는다.
- `agent-ui 상태 반영: 대기`인 Milestone이라도 최종 검증과 실제 code evidence 없이 agent-ui status를 `구현됨`으로 바꾸지 않는다.
- 사용자가 지정한 Phase/Milestone/Epic/Task anchor를 무시하지 않는다.
- 사용자가 명시하지 않은 기존 epic-id나 item-id를 바꾸지 않는다.
- `rely-on.status=enable`만으로 다른 프로젝트 Milestone의 `구현 잠금`을 직접 해제하지 않는다.
