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

# Plan - API

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

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

## 배경

`live-cycle-gate`의 `authoring-develop-gate`는 IOP authoring 응답만으로 task를 완료하지 않고, `develop` Milestone push와 provider identity match가 확인될 때만 성공 또는 sync-ready로 판정해야 한다. 현재 scheduler는 Plane-origin authoring model 응답을 받은 뒤 `CompleteTask`를 호출할 수 있어 gate가 runtime status에 반영되지 않는다. 이 작업은 authoring task 완료를 develop/projection 결과로 미루는 최소 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/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-test/plane-dev.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-task/archive/2026/06/m-milestone-work-item-creation-sync/11_creation_sync_orchestrator/complete.log`
- `services/core/internal/scheduler/jobs.go`
- `services/core/internal/scheduler/jobs_test.go`
- `services/core/internal/scheduler/river.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/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/gitosync/bridge.go`
- `services/core/internal/gitosync/bridge_test.go`
- `services/core/internal/gitosync/scanner.go`
- `services/core/internal/gitosync/scanner_test.go`
- `services/core/cmd/server/main.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 변경 필수 검증: `cd services/core && go test ./...`; 보조 검증: `cd services/core && go vet ./...`.
- roadmap/agent-task 문서 변경 검증: `git diff --check`.
- `<확인 필요>` 값은 core-smoke 기준 출력 예시에만 있으며, 이번 plan 명령에는 사용하지 않는다.

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

- Existing tests cover authoring request routing and `DecideAuthoringResult`, but not scheduler task completion being delayed until develop/projection confirmation.
- Existing `RoadmapCreationSyncWorker` tests cover SyncCreation delegation, but not completing the original external-ref task after projection.

### 심볼 참조

- Removed/renamed symbols: none.
- New call sites must be found with `rg --sort path "CompleteTaskByExternalRef|AuthoringCompletion|MetadataKeyAuthoringRunState|RoadmapCreationSyncWorker" services/core/internal services/core/cmd`.

### 분할 판단

- Split policy evaluated before writing. Shared task group: `m-milestone-work-item-creation-sync`.
- `12+11_authoring_develop_gate` depends on archived predecessor `agent-task/archive/2026/06/m-milestone-work-item-creation-sync/11_creation_sync_orchestrator/complete.log`.
- `13+12_slot_terminal_state` depends on this task because slot release policy must consume the final authoring/projection outcome.
- `14+12,13_live_cycle_smoke` depends on this task and slot terminal state because live evidence must observe the final runtime behavior.

### 범위 결정 근거

- Do not implement Plane child ticket creation, `Todo -> In Progress`, Gito proto-socket producer changes, or UI.
- Do not change generic manual/A2A task completion semantics.
- Do not introduce public HTTP routes for `RoadmapCreationSync`; use existing internal scheduler/worker seams.

### 빌드 등급

- `cloud-G07`: scheduler, workflow lifecycle, roadmap sync worker, async completion, and external-ref task finalization cross multiple runtime boundaries.

## 구현 체크리스트

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

### [API-1] Authoring model response must not complete the task

문제: [services/core/internal/scheduler/jobs.go](/config/workspace/nomadcode/services/core/internal/scheduler/jobs.go:127)에서 Plane-origin authoring branch는 model 응답을 result로 반환하고, caller가 이후 `CompleteTask`를 호출한다.

해결 방법:

Before:

```go
// services/core/internal/scheduler/jobs.go:140
result := map[string]any{
	"message":                  generated.Text,
	"mode":                     "authoring_run",
	"model":                    generated.Model,
	"response_id":              generated.ID,
	"authoring_run_state":      "in_progress",
	"authoring_run_updated_at": time.Now().UTC().Format(time.RFC3339),
}
return raw, "authoring run completed", nil
```

After:

```go
// Shape only; choose local names that fit the final code.
decision := authoring.DecideAuthoringResult(authoring.DecisionInput{BridgeSuccess: true})
if decision.State == "in_progress" {
	_, err := w.Lifecycle.MergeTaskMetadata(ctx, task.ID, map[string]any{
		workflow.MetadataKeyAuthoringRunState: "in_progress",
		workflow.MetadataKeyStatusReason:      decision.Reason,
		workflow.MetadataKeyWaitType:          "develop_match",
	})
	return nil
}
```

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/jobs.go`: authoring branch를 terminal/non-terminal outcome으로 분리한다.
- [ ] `services/core/internal/scheduler/jobs_test.go`: model response-only path가 `CompleteTask`를 호출하지 않는 regression test를 추가한다.
- [ ] `services/core/internal/workflow/lifecycle.go`: 필요한 경우 running task metadata merge가 status를 유지하는지 test와 맞춘다.

테스트 작성: `TestWorkKeepsAuthoringTaskRunningUntilDevelopMatch` 추가. model response-only 입력에서 `completed` call count가 0이고 metadata에 `authoring_run_state=in_progress`, `wait_type=develop_match`가 남는지 확인한다.

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

### [API-2] Creation sync projection finalizes the originating task

문제: [services/core/internal/scheduler/roadmap_sync_jobs.go](/config/workspace/nomadcode/services/core/internal/scheduler/roadmap_sync_jobs.go:61)는 projection 결과를 로그로만 남기며, 원래 Plane external ref task의 완료 상태를 갱신하지 않는다.

해결 방법:

Before:

```go
// services/core/internal/scheduler/roadmap_sync_jobs.go:61
res, err := w.Sync.SyncCreation(ctx, roadmapsyncpipeline.SyncCreationInput{...})
if err != nil {
	return err
}
```

After:

```go
// Shape only; keep the seam narrow and testable.
if isProjectionTerminal(res.Action) && w.TaskFinalizer != nil {
	if err := w.TaskFinalizer.CompleteByExternalRef(ctx, string(args.Ref.Provider), args.Ref.ID, result); err != nil {
		return err
	}
}
```

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/roadmap_sync_jobs.go`: optional finalizer interface를 추가하고 projected/complete action에서 호출한다.
- [ ] `services/core/internal/scheduler/river.go`: worker construction에 finalizer를 주입한다.
- [ ] `services/core/cmd/server/main.go`: workflow/lifecycle 기반 finalizer wiring을 추가한다.
- [ ] `services/core/internal/workflow/service.go`: `CompleteTaskByExternalRef` 또는 동등한 좁은 API를 추가한다.
- [ ] `services/core/internal/scheduler/river_test.go`: finalizer wiring regression을 추가한다.

테스트 작성: `TestRoadmapCreationSyncWorkerFinalizesExternalTaskOnProjected`와 `TestRoadmapCreationSyncWorkerDoesNotFinalizeNotReady` 추가.

중간 검증: `cd services/core && go test -count=1 ./internal/scheduler ./internal/workflow ./internal/roadmapsyncpipeline`.

## 의존 관계 및 구현 순서

1. `11_creation_sync_orchestrator`는 archived `complete.log`로 충족됨.
2. 먼저 scheduler의 non-terminal authoring outcome을 만든다.
3. 그 다음 creation sync worker finalizer를 붙인다.
4. 마지막으로 server/river wiring과 regression test를 닫는다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/scheduler/jobs.go` | API-1 |
| `services/core/internal/scheduler/jobs_test.go` | API-1 |
| `services/core/internal/workflow/service.go` | API-2 |
| `services/core/internal/workflow/lifecycle.go` | API-1, API-2 |
| `services/core/internal/scheduler/roadmap_sync_jobs.go` | API-2 |
| `services/core/internal/scheduler/river.go` | API-2 |
| `services/core/internal/scheduler/river_test.go` | API-2 |
| `services/core/cmd/server/main.go` | API-2 |

## 최종 검증

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

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