<!-- task=m-milestone-work-item-creation-sync/12+11_authoring_develop_gate plan=1 tag=REVIEW_API -->

# Plan - REVIEW_API

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

구현의 마지막 단계는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 내용과 검증 출력으로 채우는 것이다. 검증을 실행하고, active 파일을 유지한 채 리뷰 준비 상태로 보고한다. 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 진행할 수 없을 때는 review stub의 `사용자 리뷰 요청`에 근거를 기록하고 멈춘다. 구현 중 사용자에게 직접 질문하거나 `USER_REVIEW.md`, `complete.log`, archive log를 만들지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 증거 공백은 사용자 리뷰 요청이 아니라 검증 결과에 기록한다.

## 배경

이 후속 작업은 `code_review_cloud_G07_0.log`의 Required 문제만 닫는다. 현재 implementation은 authoring task를 model response-only 상태에서 completed로 만들지 않는 gate는 만들었지만, develop projection 이후 finalizer가 authoring metadata를 성공 상태로 닫지 못한다. 또한 authoring failure path가 계획에서 요구한 failure category metadata를 남기지 않아 runtime 상태 판정 근거가 불완전하다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 프롬프트는 금지되며, 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:
  - `authoring-develop-gate`: IOP authoring 응답만으로 task 완료를 단정하지 않고, `develop` Milestone push와 provider identity match가 확인될 때 authoring 성공 또는 sync-ready로 판정된다.
- 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/rules/project/domain/core/rules.md`
- `agent-ops/rules/project/domain/workspace-ops/rules.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-test/local/rules.md`
- `agent-test/local/core-smoke.md`
- `agent-test/local/workspace-ops-smoke.md`
- `agent-task/m-milestone-work-item-creation-sync/12+11_authoring_develop_gate/plan_cloud_G07_0.log`
- `agent-task/m-milestone-work-item-creation-sync/12+11_authoring_develop_gate/code_review_cloud_G07_0.log`
- `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/11_creation_sync_orchestrator/complete.log`
- `services/core/cmd/server/main.go`
- `services/core/internal/scheduler/jobs.go`
- `services/core/internal/scheduler/jobs_test.go`
- `services/core/internal/scheduler/river.go`
- `services/core/internal/scheduler/river_test.go`
- `services/core/internal/scheduler/roadmap_sync_jobs.go`
- `services/core/internal/workflow/service.go`
- `services/core/internal/workflow/lifecycle.go`
- `services/core/internal/workflow/model.go`
- `services/core/internal/workflow/service_test.go`
- `services/core/internal/authoring/request.go`
- `services/core/internal/authoring/result.go`
- `services/core/internal/authoring/result_test.go`
- `services/core/internal/roadmapsyncpipeline/service.go`
- `services/core/internal/roadmapsyncpipeline/service_test.go`
- `services/core/internal/roadmapsync/plane_projection_test.go`
- `services/core/internal/gitosync/bridge.go`
- `services/core/internal/gitosync/bridge_test.go`

### 테스트 환경 규칙

- `test_env=local`.
- `agent-test/local/rules.md` present/read.
- Matched profiles: `agent-test/local/core-smoke.md`, `agent-test/local/workspace-ops-smoke.md`.
- Core 필수 검증: `go test ./...` from `services/core`.
- 보조 검증: `go vet ./...` from `services/core`.
- workspace/task artifact 검증: `git diff --check`.
- Fresh focused regression에는 `-count=1`을 사용한다. 전체 `go test ./...`는 cache output 허용.

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

- `RoadmapCreationSyncWorker` projected/complete finalizer payload가 authoring completion metadata를 담는지 검증하지 않는다.
- `workflow.Service.CompleteTaskByExternalRef`가 running authoring task의 stale `authoring_run_state=in_progress`와 wait reason을 completed/succeeded metadata로 닫는지 검증하지 않는다.
- `TestMarkFailedWithTaskAuthoringRecordsState`는 failure state/timestamp만 보고 `authoring_failure_category`를 검증하지 않는다.

### 심볼 참조

- Renamed/removed symbols: none.
- New/changed symbol call sites:
  - `CompleteTaskByExternalRef`: `services/core/internal/scheduler/roadmap_sync_jobs.go`, `services/core/internal/scheduler/river_test.go`, `services/core/internal/workflow/service.go`.
  - `MetadataKeyAuthoringFailureCategory`: currently only declared in `services/core/internal/workflow/model.go`; implementation call site missing.
  - `MetadataKeyAuthoringRunState`: used in scheduler, lifecycle, tests, and must be present in finalizer result payload.

### 분할 판단

- Split decision policy evaluated. This is a follow-up inside existing dependent subtask `12+11_authoring_develop_gate`; create no new sibling directory.
- Predecessor `11_creation_sync_orchestrator` is satisfied by `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/11_creation_sync_orchestrator/complete.log`.
- Both Required issues affect the same runtime boundary and the same focused verification set, so keeping one follow-up plan avoids artificial coordination overhead.

### 범위 결정 근거

- Do not add new public HTTP/proto-socket APIs.
- Do not change Plane projection ordering, Gito scanner behavior, child ticket creation, or UI.
- Do not alter generic manual/A2A task completion behavior beyond metadata accepted by existing lifecycle completion.

### 빌드 등급

- `cloud-G07`: runtime scheduler/workflow metadata, external-ref finalization, and verification trust cross multiple core packages.

## 구현 체크리스트

- [ ] Finalizer projected/complete payload가 authoring completion metadata와 summary를 포함하고, external-ref completion 후 stale `in_progress` metadata가 남지 않도록 수정한다.
- [ ] Authoring failure path가 `authoring_failure_category`를 task failure metadata로 남기도록 수정하고 regression test를 보강한다.
- [ ] `go test -count=1 ./internal/scheduler ./internal/workflow ./internal/authoring ./internal/roadmapsyncpipeline ./internal/gitosync`를 통과시킨다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_API-1] Finalizer completion metadata

문제: [services/core/internal/scheduler/roadmap_sync_jobs.go](/config/workspace/nomadcode/services/core/internal/scheduler/roadmap_sync_jobs.go:86)의 `resultMap`은 `action`과 `reason`만 담는다. [services/core/internal/workflow/lifecycle.go](/config/workspace/nomadcode/services/core/internal/workflow/lifecycle.go:213)는 `authoring_run_state`가 result에 있을 때만 task metadata로 promote하고, [services/core/internal/workflow/lifecycle.go](/config/workspace/nomadcode/services/core/internal/workflow/lifecycle.go:226)는 `summary`만 `status_reason`으로 저장한다. 따라서 finalizer completion 후 task status는 `completed`여도 metadata가 `authoring_run_state=in_progress`와 stale wait reason을 유지할 수 있다.

해결 방법:

Before:

```go
// services/core/internal/scheduler/roadmap_sync_jobs.go:86
resultMap := map[string]any{
	"action": string(res.Action),
	"reason": res.Reason,
}
```

After:

```go
// Shape only; keep exact names local to the final code.
resultMap := map[string]any{
	"action": string(res.Action),
	"reason": res.Reason,
	"summary": res.Reason,
	workflow.MetadataKeyAuthoringRunState: "succeeded",
	workflow.MetadataKeyAuthoringRunUpdatedAt: time.Now().UTC().Format(time.RFC3339),
}
```

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/roadmap_sync_jobs.go`: finalizer payload에 `summary`, `authoring_run_state=succeeded`, updated timestamp를 추가한다.
- [ ] `services/core/internal/scheduler/river_test.go`: projected payload assertion을 보강하고 `SyncActionComplete`도 finalizer를 호출하며 동일 metadata를 담는 test를 추가한다.
- [ ] `services/core/internal/workflow/service_test.go`: running authoring task fixture로 `CompleteTaskByExternalRef`가 status completed, `agent_run_state=completed`, `wait_type` 제거, `status_reason=<summary>`, `authoring_run_state=succeeded`를 남기는 regression test를 추가한다.

테스트 작성: `TestRoadmapCreationSyncWorkerFinalizesExternalTaskOnComplete`와 `TestServiceCompleteTaskByExternalRefPromotesAuthoringMetadata`를 추가한다.

중간 검증: `go test -count=1 ./internal/scheduler ./internal/workflow` from `services/core`가 PASS.

### [REVIEW_API-2] Authoring failure category metadata

문제: [services/core/internal/scheduler/jobs.go](/config/workspace/nomadcode/services/core/internal/scheduler/jobs.go:433)의 authoring failure metadata는 `authoring_run_state`, `authoring_run_updated_at`, `authoring_failure_type`만 저장한다. [services/core/internal/workflow/model.go](/config/workspace/nomadcode/services/core/internal/workflow/model.go:59)의 `MetadataKeyAuthoringFailureCategory`는 선언되어 있지만 call site가 없어, model bridge error가 `bridge_failed` category로 남지 않는다.

해결 방법:

Before:

```go
// services/core/internal/scheduler/jobs.go:435
failInput.ExtraMetadata = map[string]any{
	workflow.MetadataKeyAuthoringRunState:     "failed",
	workflow.MetadataKeyAuthoringRunUpdatedAt: time.Now().UTC().Format(time.RFC3339),
	workflow.MetadataKeyAuthoringFailureType:  string(failureType),
}
```

After:

```go
// Shape only; keep classification consistent with authoring.DecideAuthoringResult.
decision := authoring.DecideAuthoringResult(authoring.DecisionInput{BridgeSuccess: false})
failInput.ExtraMetadata = map[string]any{
	workflow.MetadataKeyAuthoringRunState:        decision.State,
	workflow.MetadataKeyAuthoringRunUpdatedAt:    time.Now().UTC().Format(time.RFC3339),
	workflow.MetadataKeyAuthoringFailureType:     string(failureType),
	workflow.MetadataKeyAuthoringFailureCategory: decision.FailureCategory,
}
```

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/jobs.go`: authoring task failure metadata에 `MetadataKeyAuthoringFailureCategory`를 추가한다.
- [ ] `services/core/internal/scheduler/jobs_test.go`: `TestMarkFailedWithTaskAuthoringRecordsState`가 `authoring_failure_category=bridge_failed`를 assert하도록 보강한다.

테스트 작성: 기존 `TestMarkFailedWithTaskAuthoringRecordsState`에 category assertion을 추가한다.

중간 검증: `go test -count=1 ./internal/scheduler ./internal/authoring` from `services/core`가 PASS.

## 의존 관계 및 구현 순서

1. `REVIEW_API-1`을 먼저 적용해 successful completion metadata를 닫는다.
2. `REVIEW_API-2`를 적용해 failure metadata를 닫는다.
3. focused tests, full core tests, vet, diff check 순서로 검증한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/scheduler/roadmap_sync_jobs.go` | REVIEW_API-1 |
| `services/core/internal/scheduler/river_test.go` | REVIEW_API-1 |
| `services/core/internal/workflow/service_test.go` | REVIEW_API-1 |
| `services/core/internal/scheduler/jobs.go` | REVIEW_API-2 |
| `services/core/internal/scheduler/jobs_test.go` | REVIEW_API-2 |

## 최종 검증

- `go test -count=1 ./internal/scheduler ./internal/workflow ./internal/authoring ./internal/roadmapsyncpipeline ./internal/gitosync` from `services/core`
- `go test ./...` from `services/core`
- `go vet ./...` from `services/core`
- `git diff --check` from repository root

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