<!-- task=flutter_first_client_consolidation/02_contract_boundary plan=1 tag=REVIEW_API -->

# Review Follow-up Plan - Flutter/Core Contract Boundary

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

`CODE_REVIEW-cloud-G05.md`의 구현 에이전트 소유 섹션을 반드시 채우세요. 구현 후 검증 명령의 실제 stdout/stderr를 기록하고 active 파일을 그대로 둔 채 리뷰 준비 상태로 보고하세요. 종결 처리와 archive 이동은 code-review-skill 전용입니다.

## 배경

이전 리뷰에서 Plane 통합 task 생성 응답의 `external_id` 예시가 실제 core 응답과 다른 것으로 확인되었다. 이 후속 작업은 contracts 후보 문서의 해당 예시만 current shape에 맞게 고친다.

## 분석 결과

### 읽은 파일

- `agent-ops/roadmap/current.md`
- `agent-ops/roadmap/milestones/flutter-first-client-consolidation.md`
- `agent-ops/rules/project/domain/contracts/rules.md`
- `agent-ops/rules/project/domain/core/rules.md`
- `agent-task/flutter_first_client_consolidation/02_contract_boundary/plan_cloud_G05_0.log`
- `agent-task/flutter_first_client_consolidation/02_contract_boundary/code_review_cloud_G05_0.log`
- `packages/contracts/README.md`
- `packages/contracts/notes/flutter-core-api-candidates.md`
- `services/core/internal/http/router.go`
- `services/core/internal/http/handlers.go`
- `services/core/internal/http/handlers_test.go`
- `services/core/internal/workflow/model.go`
- `services/core/internal/workflow/service.go`
- `services/core/internal/workflow/service_test.go`
- `services/core/internal/storage/store.go`
- `services/core/internal/db/models.go`
- `services/core/internal/db/tasks.sql.go`
- `services/core/internal/workitem/provider.go`
- `services/core/internal/workitem/provider_test.go`
- `services/core/internal/workitempipeline/service.go`
- `services/core/internal/workitempipeline/service_test.go`

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

- 문서 예시 수정만 수행한다. automated test는 추가하지 않고 deterministic search와 `bin/test`로 검증한다.
- 기존 `services/core/internal/workitem/provider_test.go`는 `External.ID`가 work item id임을 간접 확인한다.

### 심볼 참조

- renamed/removed symbol 없음.
- 관련 생성 경로는 `workitem.BuildCreateTaskInput` -> `workflow.CreateTaskInput.External.ID` -> `storage.CreateTaskInput.ExternalID` -> HTTP response `external_id`다.

### 분할 판단

split decision policy를 평가했다. 이전 task의 단일 Required 문서 불일치만 고치며 파일 1개 수정으로 닫히므로 새 subtask 분할은 만들지 않는다.

### 범위 결정 근거

수정 범위는 `packages/contracts/notes/flutter-core-api-candidates.md`의 Plane 통합 응답 예시와 필요한 짧은 설명으로 제한한다. core handler, workflow/storage, Flutter client 구현은 변경하지 않는다.

### 빌드 등급

build lane: `cloud-G05`, review lane: `cloud-G05`. 공유 API 후보 문서의 계약 정확성 수정이며 후속 Flutter 구현의 기준이 되므로 cloud review를 유지한다.

## 구현 체크리스트

- [ ] Plane 통합 task 생성 응답의 `external_id` 예시를 실제 core current shape에 맞춘다.
- [ ] 중간 검증과 최종 검증을 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_API-1] Plane external_id 응답 예시 수정

문제: `packages/contracts/notes/flutter-core-api-candidates.md:164`는 `POST /api/integrations/plane/tasks` 응답의 `external_id`를 `plane/my-workspace/project-uuid-string/work-item-id-string`로 기록한다. 실제 core는 `services/core/internal/workitem/provider.go:177`에서 `External.ID`를 `ref.ID`로 설정하고 `services/core/internal/http/handlers.go:124`에서 이 값을 그대로 응답한다.

해결 방법: 응답 예시의 `external_id`를 `work-item-id-string`으로 바꾼다. 필요하면 workspace/project/provider 조합은 `external_metadata`에 보관된다는 짧은 note를 추가한다.

Before:

```markdown
160   {
161     "id": "task-uuid-string",
162     "status": "pending",
163     "external_provider": "plane",
164     "external_id": "plane/my-workspace/project-uuid-string/work-item-id-string"
165   }
```

After:

```markdown
160   {
161     "id": "task-uuid-string",
162     "status": "pending",
163     "external_provider": "plane",
164     "external_id": "work-item-id-string"
165   }
```

수정 파일 및 체크리스트:
- [ ] `packages/contracts/notes/flutter-core-api-candidates.md`

테스트 작성: skip. 문서 예시 수정이며 core 동작 변경이 없다.

중간 검증:

```bash
rg --sort path -n '"external_id": "work-item-id-string"|external_metadata' packages/contracts/notes/flutter-core-api-candidates.md
! rg --sort path -n '"external_id": "plane/my-workspace/project-uuid-string/work-item-id-string"' packages/contracts/notes/flutter-core-api-candidates.md
```

예상 결과: 수정된 `external_id` 예시가 검색되고, composite `external_id` 응답 예시는 검색되지 않는다. 만약 composite 형식을 설명 note에 남기면 응답 예시가 아님을 문장으로 명확히 해야 한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/contracts/notes/flutter-core-api-candidates.md` | REVIEW_API-1 |

## 최종 검증

```bash
rg --sort path -n '"external_id": "work-item-id-string"|external_metadata|flutter-core-api-candidates' packages/contracts
! rg --sort path -n '"external_id": "plane/my-workspace/project-uuid-string/work-item-id-string"' packages/contracts
bin/test
```

예상 결과: contracts 문서가 실제 Plane task response shape를 가리키고, `bin/test`는 설치된 toolchain 기준으로 통과 또는 명시적 skip만 출력한다.

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