<!-- task=provider_neutral_plane_entrypoint/01_pipeline_mapper plan=1 tag=REVIEW_REFACTOR -->

# Provider-Neutral Work Item Task Mapper Review Fix

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

`CODE_REVIEW-cloud-G06.md`의 구현 에이전트 소유 섹션을 채우는 것은 필수다. 구현 후 검증 명령을 실제로 실행하고, 실제 출력과 주요 설계 결정, 계획 대비 변경 사항을 review stub에 기록한 뒤 active 파일을 그대로 둔 채 리뷰 준비 상태로 보고한다. 최종 판정, `.log` 아카이브, `complete.log` 작성, archive 이동은 code-review-skill 전용이다.

## 배경

이 후속 계획은 `code_review_cloud_G06_0.log`의 Required 이슈만 수정한다. 새 provider-neutral mapper가 후속 HTTP Plane entrypoint 전환에서 기존 `buildPlaneCreateTaskInput`을 대체할 예정이므로, 기존 helper처럼 공백 comment/description을 message로 선택하지 않아야 한다.

## 분석 결과

### 읽은 파일

- `agent-task/provider_neutral_plane_entrypoint/01_pipeline_mapper/plan_cloud_G06_0.log`
- `agent-task/provider_neutral_plane_entrypoint/01_pipeline_mapper/code_review_cloud_G06_0.log`
- `services/core/internal/workitem/provider.go`
- `services/core/internal/workitem/provider_test.go`
- `services/core/internal/http/handlers.go`

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

- 현재 `TestBuildCreateTaskInputUsesCommentBeforeDescription`은 정상 comment 우선순위만 검증한다.
- 공백 comment가 있을 때 description으로 fallback하고, 선택된 message가 trim되는지 검증하는 테스트가 없다.

### 범위 결정 근거

- 수정 범위는 `internal/workitem` mapper와 mapper 단위 테스트로 제한한다.
- HTTP handler 전환은 dependent task `02+01_http_plane_entrypoint` 범위이므로 이 후속 계획에서 건드리지 않는다.
- provider-neutral metadata key, payload 구조, workflow/storage 계약은 이전 구현 그대로 유지한다.

### 빌드 등급

- build lane: `cloud-G06`
- review lane: `cloud-G06`
- 근거: 후속 HTTP 전환의 provider-neutral mapper 계약을 바로잡는 correctness/test coverage 수정이며, 기존 route나 외부 API shape는 변경하지 않는다.

## 구현 체크리스트

- [ ] `workitem.firstNonEmpty`가 공백 문자열을 건너뛰고 선택된 message를 trim하도록 수정한다.
- [ ] `BuildCreateTaskInput`의 공백 comment/description fallback 단위 테스트를 추가하고 관련 Go 테스트를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 구현 항목

### [REVIEW_REFACTOR-1] Mapper message 후보 선택에서 공백 입력을 무시한다

#### 문제

`services/core/internal/workitem/provider.go:127`의 새 `firstNonEmpty`는 `s != ""`만 검사한다. 후속 HTTP 전환에서 이 mapper가 기존 `buildPlaneCreateTaskInput`을 대체하면 공백 comment나 description이 payload `message`로 선택되어 실제 description/title fallback을 건너뛰는 회귀가 생긴다.

Before:

```go
func firstNonEmpty(ss ...string) string {
	for _, s := range ss {
		if s != "" {
			return s
		}
	}
	return ""
}
```

After:

```go
func firstNonEmpty(ss ...string) string {
	for _, s := range ss {
		if trimmed := strings.TrimSpace(s); trimmed != "" {
			return trimmed
		}
	}
	return ""
}
```

#### 해결 방법

- `services/core/internal/workitem/provider.go`의 package-local `firstNonEmpty`를 `strings.TrimSpace` 기반으로 수정한다.
- `BuildCreateTaskInput`의 message 선택은 기존 순서 `input.Comment`, `item.DescriptionText`, `item.DescriptionHTML`, `title`를 유지한다.
- `services/core/internal/workitem/provider_test.go`에 공백 comment와 공백 description 후보를 건너뛰는 테스트를 추가한다.
- 기존 provider-neutral metadata/payload 테스트는 유지한다.

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

- [ ] `services/core/internal/workitem/provider.go`의 `firstNonEmpty`를 trim 기반으로 수정한다.
- [ ] `services/core/internal/workitem/provider_test.go`에 whitespace fallback 테스트를 추가한다.
- [ ] `services/core/go.mod`에 dependency 변화가 없음을 확인한다.

#### 테스트 작성

- 수정: `services/core/internal/workitem/provider_test.go`
- 추가 테스트 후보: `TestBuildCreateTaskInputSkipsWhitespaceMessageCandidates`
- 검증 내용:
  - `Comment: "   "`이면 `DescriptionText`로 fallback한다.
  - `DescriptionText: "  description text  "`이면 payload `message`는 `"description text"`다.
  - comment와 text description이 모두 공백이면 HTML description 또는 title로 fallback한다.

#### 중간 검증

```bash
cd services/core && go test -count=1 ./internal/workitem
```

기대 결과: workitem mapper 테스트가 fresh run으로 통과한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/workitem/provider.go` | REVIEW_REFACTOR-1 |
| `services/core/internal/workitem/provider_test.go` | REVIEW_REFACTOR-1 |
| `services/core/go.mod` | REVIEW_REFACTOR-1 dependency 변화 없음 확인 |

## 리뷰어를 위한 체크포인트

- 공백-only comment/description이 payload `message`로 선택되지 않는지 확인한다.
- 선택된 message가 trim된 값으로 저장되는지 확인한다.
- provider-neutral metadata와 external ref 계약이 이전 구현에서 바뀌지 않았는지 확인한다.
- HTTP handler와 route는 이 task에서 바뀌지 않았는지 확인한다.

## 최종 검증

```bash
cd services/core && gofmt -w internal/workitem/*.go
```

기대 결과: 출력 없음. `internal/workitem` Go 파일이 gofmt 적용된다.

```bash
cd services/core && go test -count=1 ./internal/workitem ./internal/workflow
```

기대 결과: 관련 패키지 테스트가 fresh run으로 통과한다.

```bash
git diff --check
```

기대 결과: whitespace error가 없다.

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