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

# Code Review Reference - API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only.

## 개요

date=2026-06-15
task=m-milestone-work-item-creation-sync/12+11_authoring_develop_gate, plan=0, tag=API

## 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

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.

1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` → `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` → `plan_cloud_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-milestone-work-item-creation-sync/12+11_authoring_develop_gate/`로 이동한다.
4. PASS이고 task group이 `m-milestone-work-item-creation-sync`이면 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [API-1] Authoring model response must not complete the task | [x] |
| [API-2] Creation sync projection finalizes the originating task | [x] |

## 구현 체크리스트

- [x] Plane-origin authoring task가 model response-only 상태에서 `completed`로 전이되지 않고 `running` + `authoring_run_state=in_progress` + wait reason을 유지하도록 scheduler/workflow 경계를 수정한다.
- [x] `RoadmapCreationSyncWorker`가 `SyncActionProjected` 또는 already-complete outcome에서 원래 Plane external ref task를 완료할 수 있는 finalizer seam을 추가한다.
- [x] model bridge error, push failure, dirty workspace, conflict 같은 failure category는 task failure metadata로 남기고 Plane `Todo` projection으로 넘어가지 않도록 테스트한다.
- [x] `cd services/core && go test -count=1 ./internal/scheduler ./internal/workflow ./internal/authoring ./internal/roadmapsyncpipeline ./internal/gitosync`를 통과시킨다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_0.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_0.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리를 archive로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

- `workflow.Service`와 `scheduler.Client` 간의 순환 참조를 해결하기 위해 `workflow.Service`에 `SetEnqueuer(enqueuer TaskEnqueuer)` 메서드를 새로 추가하고, `main.go`에서 지연 바인딩(lazy wiring) 방식을 통해 생성 및 주입 순서를 조정하였습니다.
- `CompleteByExternalRef` 메서드명을 가이드라인에 맞게 `CompleteTaskByExternalRef`로 일원화하여 인터페이스 호환을 마쳤습니다.

## 주요 설계 결정

- `RoadmapCreationSyncWorker` 내부에서 사용할 `TaskFinalizer` 인터페이스를 `CompleteTaskByExternalRef` 메서드명을 갖도록 설계하여 `workflow.Service`가 이를 직접적으로 호환하도록 만들었습니다.
- `Workflow` 서비스의 `CompleteTaskByExternalRef`는 concurrency-safe 하도록 기존 `WithExternalRefLock` 뮤텍스 락 메커니즘을 그대로 활용하도록 설계했습니다. 또한 이미 `completed` 상태인 경우에는 중복 처리를 방지하기 위해 no-op으로 즉시 반환하도록 설계했습니다.

## 사용자 리뷰 요청

- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음

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

- model response-only authoring task가 `completed`로 전이되지 않는지 확인한다.
- projection terminal outcome만 원래 external-ref task를 완료하는지 확인한다.
- not_ready/conflict/self-mutation outcome에서 provider side effect와 task completion이 섞이지 않는지 확인한다.

## 검증 결과

### API-1 중간 검증
```text
$ cd services/core && go test -count=1 ./internal/scheduler ./internal/workflow
ok  	github.com/nomadcode/nomadcode-core/internal/scheduler	2.015s
ok  	github.com/nomadcode/nomadcode-core/internal/workflow	0.004s
```

### API-2 중간 검증
```text
$ cd services/core && go test -count=1 ./internal/scheduler ./internal/workflow ./internal/roadmapsyncpipeline
ok  	github.com/nomadcode/nomadcode-core/internal/scheduler	2.010s
ok  	github.com/nomadcode/nomadcode-core/internal/workflow	0.003s
ok  	github.com/nomadcode/nomadcode-core/internal/roadmapsyncpipeline	0.004s
```

### 최종 검증
```text
$ cd services/core && go test -count=1 ./internal/scheduler ./internal/workflow ./internal/authoring ./internal/roadmapsyncpipeline ./internal/gitosync
ok  	github.com/nomadcode/nomadcode-core/internal/scheduler	2.012s
ok  	github.com/nomadcode/nomadcode-core/internal/workflow	0.006s
ok  	github.com/nomadcode/nomadcode-core/internal/authoring	0.004s
ok  	github.com/nomadcode/nomadcode-core/internal/roadmapsyncpipeline	0.004s
ok  	github.com/nomadcode/nomadcode-core/internal/gitosync	0.006s

$ cd services/core && go test ./...
ok  	github.com/nomadcode/nomadcode-core/cmd/plane-smoke	(cached)
?   	github.com/nomadcode/nomadcode-core/cmd/server	[no test files]
ok  	github.com/nomadcode/nomadcode-core/internal/adapters/a2a	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/adapters/jira	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/adapters/mattermost	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/adapters/openai	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/adapters/plane	(cached)
?   	github.com/nomadcode/nomadcode-core/internal/agent	[no test files]
ok  	github.com/nomadcode/nomadcode-core/internal/authoring	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/config	(cached)
?   	github.com/nomadcode/nomadcode-core/internal/db	[no test files]
ok  	github.com/nomadcode/nomadcode-core/internal/gitoevents	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/gitosync	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/http	(cached)
?   	github.com/nomadcode/nomadcode-core/internal/model	[no test files]
ok  	github.com/nomadcode/nomadcode-core/internal/notification	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/projectsync	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/protosocket	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/roadmapsync	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/roadmapsyncpipeline	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/scheduler	2.013s
ok  	github.com/nomadcode/nomadcode-core/internal/storage	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/workflow	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/workitem	(cached)
ok  	github.com/nomadcode/nomadcode-core/internal/workitempipeline	(cached)

$ cd services/core && go vet ./...
(No output)

$ git diff --check
(No output)
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Fail
  - completeness: Fail
  - test coverage: Fail
  - API contract: Pass
  - code quality: Pass
  - plan deviation: Fail
  - verification trust: Pass
- 발견된 문제:
  - Required: [services/core/internal/scheduler/roadmap_sync_jobs.go:86](/config/workspace/nomadcode/services/core/internal/scheduler/roadmap_sync_jobs.go:86)의 finalizer payload가 `action`/`reason`만 넘기고 있어, [services/core/internal/workflow/lifecycle.go:213](/config/workspace/nomadcode/services/core/internal/workflow/lifecycle.go:213)에서 완료 시 promote하는 `authoring_run_state`가 계속 기존 `in_progress`로 남습니다. 같은 lifecycle은 [services/core/internal/workflow/lifecycle.go:226](/config/workspace/nomadcode/services/core/internal/workflow/lifecycle.go:226)에서 `summary`만 `status_reason`으로 반영하므로, completed task metadata가 `waiting for pushed develop milestone match`류 stale reason을 유지할 수도 있습니다. `SyncActionProjected`/`SyncActionComplete` finalizer result에 `summary`, `authoring_run_state=succeeded`, 갱신 timestamp를 포함하고, running authoring task가 external-ref finalizer 이후 `completed` + succeeded metadata로 닫히는 regression test를 추가하세요.
  - Required: [services/core/internal/scheduler/jobs.go:433](/config/workspace/nomadcode/services/core/internal/scheduler/jobs.go:433)의 authoring failure path는 `authoring_failure_type`만 기록하고, 계획에서 요구한 failure category metadata를 기록하지 않습니다. [services/core/internal/workflow/model.go:59](/config/workspace/nomadcode/services/core/internal/workflow/model.go:59)의 `MetadataKeyAuthoringFailureCategory` 상수는 현재 참조되지 않아 model bridge error가 `bridge_failed`로 남지 않습니다. authoring failure metadata에 `authoring_failure_category`를 채우고, model bridge error path에서 `authoring_run_state=failed`, `authoring_failure_type`, `authoring_failure_category=bridge_failed`가 함께 저장되는 test를 추가하세요.
- 다음 단계: WARN/FAIL 후속 plan/review 파일을 작성한다.
