<!-- task=m-milestone-work-item-creation-sync/03+01,02_project_binding_checkout plan=1 tag=API -->

# Implementation Plan - API

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

구현 완료는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운 뒤에만 성립한다. 검증을 실행하고, 실제 변경/출력을 기록하고, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 종료 처리, log rename, `complete.log`, archive 이동은 code-review 스킬 전용이다. 구현 중 사용자만 결정할 수 있는 범위 변경, 외부 환경/secret 준비, scope 충돌이 있으면 review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 적고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하거나 `USER_REVIEW.md`를 만들지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 공백은 사용자 리뷰 요청이 아니다.

## 배경

Project sync 설정과 workspace slot 저장소가 준비되면 Plane-origin 요청은 더 이상 요청 body만으로 git/workspace를 해석하면 안 된다. 같은 Plane project의 티켓은 같은 git/workspace 설정을 사용해야 하고, 실제 작업 slot은 독립 checkout 경로로 계획되어야 한다. 이 plan은 `project-bind`와 `workspace-checkout` Task를 함께 닫는 후속 binding 작업이다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 해당 섹션은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 형식을 따른다. 구현 에이전트는 직접 사용자 프롬프트를 만들지 않고, code-review가 사용자 리뷰 요청의 타당성과 실제 `USER_REVIEW.md` 작성을 판단한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
- Task ids:
  - `project-bind`: Plane-origin 생성 동기화가 project sync 설정을 통해 Plane project, git repository, 작업 workspace를 해석하도록 한다.
  - `workspace-checkout`: Git repository checkout 정책을 project sync 설정과 연결한다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/private/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-roadmap/current.md`
- `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
- `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md`
- `agent-ops/rules/project/domain/core/rules.md`
- `agent-ops/rules/project/domain/workspace-ops/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/core-smoke.md`
- `agent-test/local/workspace-ops-smoke.md`
- `.gitignore`
- `services/core/internal/projectsync/config.go`
- `services/core/internal/projectsync/config_test.go`
- `services/core/internal/workitempipeline/service.go`
- `services/core/internal/workitempipeline/service_test.go`
- `services/core/internal/http/handlers.go`
- `services/core/cmd/server/main.go`
- `services/core/internal/storage/store.go`

### 테스트 환경 규칙

- 선택한 `test_env`: `local`.
- `agent-test/local/rules.md`를 읽었다. core 변경은 `agent-test/local/core-smoke.md` 기준으로 최소 `cd services/core && go test ./...`가 필수다.
- workspace-ops는 plan/review artifact 작성에만 닿으므로 `agent-test/local/workspace-ops-smoke.md` 기준 `git diff --check`를 최종 확인에 포함한다.
- 이 plan은 checkout process 실행 자체를 만들지 않도록 제한한다. process control을 구현하게 되면 `cloud-G07` 판단을 유지하고 검증 명령에 focused process tests를 추가해야 한다.

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

- 현재 `workitempipeline.Service`는 provider reader와 task creator만 가진다(`services/core/internal/workitempipeline/service.go:21`). Project config resolver, slot reserver, checkout plan을 다루는 테스트가 없다.
- HTTP handler는 provider registry만 조립한다(`services/core/internal/http/handlers.go:39`). Project sync resolver wiring 테스트가 없다.
- 실제 git checkout 실행은 이 plan 범위가 아니다. checkout policy는 계획 객체와 path/remote/branch 검증으로 테스트한다.

### 심볼 참조

- none. 기존 symbol rename/remove는 없다. `workitempipeline.New` signature를 바꾸는 경우 call site는 `services/core/internal/http/handlers.go:51`, `services/core/internal/workitempipeline/service_test.go:41`, `services/core/cmd/server/main.go:109` 경유 handler wiring을 모두 갱신한다.

### 분할 판단

- split decision policy를 평가했다. 공유 task group은 `agent-task/m-milestone-work-item-creation-sync/`다.
- `01_project_sync_store`: predecessor. Project sync 설정 DB 저장소를 만든다.
- `02+01_workspace_slot_store`: predecessor. Slot 상태 저장과 원자 예약을 만든다.
- `03+01,02_project_binding_checkout`: 현재 plan. predecessor `01`, `02`: missing active/archive `complete.log`. 구현은 두 predecessor PASS 후 시작한다.

### 범위 결정 근거

- Plane ticket authoring run 실행, IOP CLI 호출, Plane Todo projection은 첫 Epic 밖의 후속 Epic/Task다.
- 실제 `git clone`, `git fetch`, `git checkout` 프로세스 실행은 하지 않는다. 이 plan은 config와 reserved slot에서 checkout plan을 산출하는 정책 경계까지만 둔다.
- UI 구현은 `settings-ui` Task의 후속 후보로 남기고 이 plan에서 제외한다.

### 빌드 등급

- `cloud-G07`: storage 결과를 pipeline/handler wiring에 연결하고 checkout policy를 세우는 cross-boundary 작업이다. 실제 terminal checkout 실행은 제외하지만, 선행 plan 산출물과 여러 call site 맥락을 안전하게 붙여야 한다.

## 구현 체크리스트

- [x] Plane-origin 생성 동기화가 project sync 설정 resolver를 통해 Plane project, git repository, workspace를 해석하도록 한다. 검증: 같은 Plane project 안의 티켓은 같은 git/workspace 설정을 사용하며, 다른 Plane project와 섞이지 않는다.
- [x] Git checkout policy를 project sync 설정과 workspace slot에 연결한다. 검증: git remote는 project sync 설정에서 읽고, 각 slot은 같은 remote의 독립 checkout path를 기본으로 확보하며, 일반 단일 운용에서는 `000`을 사용한다.
- [x] Binding/checkout policy 테스트를 작성한다.
- [x] `cd services/core && go test -count=1 ./...`와 `git diff --check`를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- 이 subtask 디렉터리 이름은 `03+01,02_project_binding_checkout`이므로 predecessor는 `01_project_sync_store`, `02+01_workspace_slot_store` 두 개다.
- 구현 시작 전 같은 task group의 `01_project_sync_store/complete.log`와 `02+01_workspace_slot_store/complete.log`가 active 또는 archive 경로에 있어야 한다. 현재 확인 시 두 predecessor completion은 missing이다.

### [API-1] Project sync resolver binding

- 문제: `workitempipeline.Service`는 provider work item을 task로 바꾸지만 project sync 설정을 읽지 않는다(`services/core/internal/workitempipeline/service.go:30`). milestone은 Plane project별 sync 설정으로 Plane project, git repository, 작업 workspace를 해석하라고 요구한다(`agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md:52`).
- 해결 방법: `workitempipeline`에 좁은 interface를 추가한다. 예: `ProjectConfigResolver.ResolveProjectSyncConfig(ctx, workitem.Ref) (projectsync.Config, error)`. Service input 처리 중 normalized ref로 resolver를 호출하고, 설정 없음이면 task creation으로 넘어가지 않는다. 같은 provider/tenant/project는 같은 config를 반환하고 다른 project는 분리된 config를 쓰도록 테스트한다.
- 수정 파일 및 체크리스트:
  - [x] `services/core/internal/workitempipeline/service.go`
  - [x] `services/core/internal/workitempipeline/service_test.go`
  - [x] 필요한 경우 `services/core/internal/http/handlers.go` (API-3에서 wiring과 함께 수정)
- 테스트 작성: fake resolver로 same project/different project behavior, resolver error propagation, no config blocks task creation을 테스트한다.
- 중간 검증: `cd services/core && go test -count=1 ./internal/workitempipeline ./internal/projectsync`.

### [API-2] Checkout policy object from config and slot

- 문제: `projectsync.Config`는 git remote, source branch, workspace path를 갖지만(`services/core/internal/projectsync/config.go:25`), slot별 독립 checkout path와 연결된 policy 객체가 없다. milestone은 git remote를 project sync 설정에서 읽고 slot별 독립 checkout을 기본으로 하라고 요구한다(`agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md:56`).
- 해결 방법: `projectsync.CheckoutPlan` 또는 동등한 타입을 추가한다. 입력은 normalized config와 reserved slot이다. 출력은 remote URL, source branch, project workspace root, slot path, slot index를 담는다. 실제 git process는 실행하지 않는다.
- 수정 파일 및 체크리스트:
  - [x] `services/core/internal/projectsync/config.go` 또는 `checkout.go` (신규 `checkout.go` 선택)
  - [x] `services/core/internal/projectsync/config_test.go` 또는 `checkout_test.go` (신규 `checkout_test.go` 선택)
- 테스트 작성: `000` 기본 slot, `001` 병렬 slot, remote/branch passthrough, invalid config/slot reject를 테스트한다.
- 중간 검증: `cd services/core && go test -count=1 ./internal/projectsync`.

### [API-3] Handler/server wiring for project sync dependencies

- 문제: HTTP handler는 provider reader만 받아 pipeline service를 만든다(`services/core/internal/http/handlers.go:39`). Server wiring도 provider만 넘긴다(`services/core/cmd/server/main.go:109`). Resolver와 slot reserver가 wiring되지 않으면 runtime path에서 binding이 적용되지 않는다.
- 해결 방법: predecessor에서 추가한 storage methods를 handler 또는 pipeline options로 주입한다. nil dependency는 명시적으로 sync 설정 없음/서비스 미구성 오류로 실패하게 하고, 기존 provider-neutral task creation test를 갱신한다.
- 수정 파일 및 체크리스트:
  - [x] `services/core/internal/http/handlers.go`
  - [x] `services/core/internal/http/handlers_test.go`
  - [x] `services/core/cmd/server/main.go`
- 테스트 작성: handler test에 configured resolver path, missing project sync 설정 path, provider mismatch 유지 test를 추가한다.
- 중간 검증: `cd services/core && go test -count=1 ./internal/http ./internal/workitempipeline`.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/workitempipeline/service.go` | API-1 |
| `services/core/internal/workitempipeline/service_test.go` | API-1 |
| `services/core/internal/projectsync/config.go` 또는 `services/core/internal/projectsync/checkout.go` | API-2 |
| `services/core/internal/projectsync/config_test.go` 또는 `services/core/internal/projectsync/checkout_test.go` | API-2 |
| `services/core/internal/http/handlers.go` | API-3 |
| `services/core/internal/http/handlers_test.go` | API-3 |
| `services/core/cmd/server/main.go` | API-3 |

## 최종 검증

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

기대 결과: 두 명령 모두 exit code 0. Go test cache output은 허용하지 않으므로 `-count=1`을 유지한다.

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