<!-- task=m-milestone-work-item-creation-sync/03+02_develop_match plan=0 tag=API -->

# Plan - API Develop Milestone Match

## 이 파일을 읽는 구현 에이전트에게

`CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 반드시 채운다. 검증 명령을 실행하고 실제 출력과 구현 메모를 남긴 뒤 active 파일을 유지한 채 리뷰 준비를 보고한다. 사용자 전용 결정이나 외부 환경 차단은 review stub의 `사용자 리뷰 요청`에 근거를 기록하고 멈춘다. 구현 중 사용자에게 직접 질문하지 않는다.

## 배경

Plane Todo projection은 slot local 변경이나 push 실패만으로 진행하면 안 된다. source of truth는 `branches/develop` 또는 remote `develop`에 반영된 `agent-roadmap` Milestone이다. 이 plan은 pushed Milestone scan과 provider work item identity match를 구현한다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active review stub의 `사용자 리뷰 요청`에 기록한다. code-review가 요청 타당성을 검증한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
- Task ids:
  - `cycle-develop-sync`: sync layer가 `branches/develop` 또는 remote `develop`에서 pushed Milestone을 감지하고 원래 Plane 티켓 identity와 매칭한다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/domain/core/rules.md`
- `agent-ops/rules/project/domain/contracts/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/core-smoke.md`
- `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
- `services/core/internal/projectsync/config.go`
- `services/core/internal/projectsync/checkout.go`
- `services/core/internal/workitempipeline/service.go`
- `services/core/internal/workitem/provider.go`
- `services/core/internal/storage/project_sync_settings.go`
- `services/core/internal/storage/workspace_slots.go`
- `services/core/migrations/00004_create_project_sync_settings.sql`
- `services/core/migrations/00005_create_workspace_slots.sql`
- `packages/contracts/notes/flutter-core-api-candidates.md`

### 테스트 환경 규칙

- test_env: `local`.
- `agent-test/local/rules.md`, `agent-test/local/core-smoke.md` 읽음.
- core 코드 변경 필수 검증: `cd services/core && go test ./...`.
- migration/query 변경이 있으면 SQLC 생성 파일과 storage tests를 함께 갱신한다.

### 테스트 커버리지 공백

- 실제 remote `develop` fetch/push e2e는 제외하고 fake git scanner로 branch/path/revision matching을 검증한다.
- Milestone Markdown parsing은 parser unit test를 추가해야 한다.

### 심볼 참조

- renamed/removed symbols: none.

### 분할 판단

- 이 plan은 `03+02_develop_match`이며 predecessor `02_iop_authoring_bridge` complete.log가 필요하다. 현재 missing.
- Plane mutation과 retry 정책은 04/05에서 분리한다.

### 범위 결정 근거

- Plane comment/body/status update는 제외한다.
- duplicate 재처리 정책은 identity persistence의 최소 unique constraint까지만 포함하고 full retry는 05에서 처리한다.

### 빌드 등급

- build: `cloud-G07`. git/roadmap scan, provider identity, DB shape가 맞물리는 cross-module 작업이다.

## 구현 체크리스트

- [ ] `develop` branch workspace 또는 remote revision scan 결과를 표현하는 `roadmapsync` domain model을 추가한다.
- [ ] Milestone 파일에서 provider, tenant, project, work item id, milestone path/id를 추출하는 parser를 추가한다.
- [ ] pushed/scanned Milestone이 원래 Plane work item identity와 일치할 때만 projection-ready result를 반환한다.
- [ ] slot local dirty path나 push 실패 result는 projection-ready가 아니도록 테스트한다.
- [ ] `cd services/core && go test ./...`와 `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- `02_iop_authoring_bridge`의 `complete.log`가 필요하다. 현재 missing.

### [API-1] Roadmap Sync Identity Model

#### 문제

contract note는 sync identity 후보를 정의하지만([flutter-core-api-candidates.md](/config/workspace/nomadcode/packages/contracts/notes/flutter-core-api-candidates.md:347)), core에는 이를 담는 typed domain이 없다.

#### 해결 방법

`services/core/internal/roadmapsync` 패키지를 추가하고 `Identity`, `Revision`, `ScanResult`, `ProjectionCandidate`를 정의한다. provider-neutral shape는 contract note의 필드를 따른다.

#### 수정 파일 및 체크리스트

- [ ] `services/core/internal/roadmapsync/identity.go`
- [ ] `services/core/internal/roadmapsync/identity_test.go`

#### 테스트 작성

- valid milestone identity normalize test.
- missing provider/work item id reject test.

#### 중간 검증

```bash
cd services/core && go test ./internal/roadmapsync
```

### [API-2] Milestone Identity Parser

#### 문제

Milestone은 provider와 Plane work item id가 Milestone 작업 컨텍스트에 남아야 match 가능하다고 한다([milestone-work-item-creation-sync.md](/config/workspace/nomadcode/agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md:89)). 현재 Milestone Markdown에서 identity를 읽는 parser가 없다.

#### 해결 방법

첫 slice에서는 명시 섹션 또는 bullet 형식의 `Provider identity` block을 읽는 작고 엄격한 parser를 만든다. ad hoc string scan은 parser 내부로 제한하고, 외부 API는 typed result만 반환한다.

#### 수정 파일 및 체크리스트

- [ ] `services/core/internal/roadmapsync/milestone_parser.go`
- [ ] `services/core/internal/roadmapsync/milestone_parser_test.go`

#### 테스트 작성

- provider/work item id가 있으면 identity 반환.
- identity가 없거나 mismatched provider면 projection candidate를 만들지 않음.

#### 중간 검증

```bash
cd services/core && go test ./internal/roadmapsync
```

### [API-3] Develop Projection Candidate Gate

#### 문제

[services/core/internal/workitempipeline/service.go](/config/workspace/nomadcode/services/core/internal/workitempipeline/service.go:89)는 slot을 예약하고 task metadata를 남길 뿐, `branches/develop` 반영 여부를 확인하지 않는다.

#### 해결 방법

`roadmapsync.MatchDevelopMilestone`을 추가한다. 입력은 develop workspace path/revision, changed files, expected work item identity이며 출력은 projection-ready 여부와 reason이다. slot local path만 들어온 경우 false를 반환한다.

#### 수정 파일 및 체크리스트

- [ ] `services/core/internal/roadmapsync/develop_match.go`
- [ ] `services/core/internal/roadmapsync/develop_match_test.go`

#### 테스트 작성

- changed file이 `agent-roadmap/phase/*/milestones/*.md`이고 identity가 맞으면 ready.
- slot path, feature branch, identity mismatch, missing push revision은 not ready.

#### 중간 검증

```bash
cd services/core && go test ./internal/roadmapsync
```

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/roadmapsync/identity.go` | API-1 |
| `services/core/internal/roadmapsync/identity_test.go` | API-1 |
| `services/core/internal/roadmapsync/milestone_parser.go` | API-2 |
| `services/core/internal/roadmapsync/milestone_parser_test.go` | API-2 |
| `services/core/internal/roadmapsync/develop_match.go` | API-3 |
| `services/core/internal/roadmapsync/develop_match_test.go` | API-3 |

## 최종 검증

```bash
cd services/core && go test ./...
git diff --check
```

Go test cache output is acceptable for unchanged packages; changed packages must appear in output or be rerun directly as 중간 검증.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
