<!-- task=m-plane-origin-authoring-roundtrip-sync/01_iop_long_run plan=1 tag=REVIEW_AUTHORING_RUNTIME -->

# Implementation Plan - REVIEW_AUTHORING_RUNTIME

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

이 plan의 구현 완료는 active `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운 뒤에만 성립한다. 구현 중 선택된 SDD 결정 또는 Milestone lock 결정이 실제 구현을 차단할 때만 review stub의 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 기록한다. 환경, secret, 외부 서비스, 검증 증거 부족은 사용자 리뷰 요청이 아니며 `검증 결과` 또는 후속 plan으로 남긴다. archive, `complete.log`, roadmap 갱신은 code-review/runtime 소유다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다.

## 배경

직전 루프는 Plane-origin authoring 작업이 generic `WORKFLOW_TASK_TIMEOUT_SEC`에 의해 10분 전에 조기 실패하지 않도록 `RunTimeout` 우회와 `MODEL_TIMEOUT_SEC=900` 기본값 정리를 구현했다. focused tests와 `git diff --check`는 통과했지만, active `Roadmap Targets`/`Spec Targets`는 `iop-long-run`과 SDD `S02` 완료를 주장한다. SDD `S02`는 timeout뿐 아니라 retry, queue 대기 timeout, stale 판단 기준 및 evidence를 요구하므로, 현재 상태로 PASS하면 milestone/spec completion이 과대 기록된다.

## 사용자 리뷰 요청 흐름

구현 중 직접 사용자에게 질문하지 않는다. 선택된 SDD 결정 또는 Milestone lock 결정이 실제 구현을 차단할 때만 active `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 기록한다. code-review가 해당 요청을 검증하고 필요 시 `USER_REVIEW.md`를 작성한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md`
- Task ids:
  - `iop-long-run`: IOP Responses 호출이 10분 이상 걸릴 수 있는 작업을 실패로 조기 확정하지 않도록 timeout, retry, queue timeout, stale 판단 기준을 재정의한다.
- Completion mode: check-on-pass

## Spec Targets

- SDD: `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
- Acceptance scenarios:
  - `S02`: task=`iop-long-run`; evidence=`core config/scheduler test or smoke evidence for long-running timeout/retry/stale metadata behavior`
- Completion mode: spec-check-on-pass

## Archive Evidence Snapshot

- Current archived plan: `agent-task/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/plan_cloud_G07_0.log`
- Current archived review: `agent-task/m-plane-origin-authoring-roundtrip-sync/01_iop_long_run/code_review_cloud_G07_0.log`
- Verdict: FAIL
- Required summary:
  - `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md:83` and `:103` require `S02/iop-long-run` evidence for timeout, retry, queue waiting, and stale behavior. The implemented code only records `authoring_run_state`/`authoring_run_updated_at` and skips generic `RunTimeout`; it does not close configured stale threshold, queue timeout, or retry decision evidence.
- Affected files from prior loop:
  - `services/core/internal/scheduler/jobs.go`
  - `services/core/internal/scheduler/jobs_test.go`
  - `services/core/internal/config/config.go`
  - `services/core/internal/config/config_test.go`
  - `services/core/internal/adapters/openai/client.go`
  - `services/core/internal/adapters/openai/client_test.go`
  - `services/core/README.md`
  - `services/core/Makefile`
  - `services/core/bin/run`
  - `services/core/docker-compose.yml`
- Verification evidence:
  - `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...` passed in the review checkout.
  - `git diff --check` passed with no output in the review checkout.
- Roadmap/spec carryover:
  - Keep the same `Roadmap Targets` and `Spec Targets` only if this follow-up closes the full `iop-long-run`/`S02` completion evidence. If implementation intentionally remains a foundation-only slice, remove completion claims and explain why in `범위 결정 근거`; do not PASS with over-broad completion targets.
- Narrow reread allowed:
  - The next implementer may read only the archived files named above if exact prior-loop wording is needed. Do not search `agent-task/archive/**`.

## 범위 결정 근거

- 포함: Plane-origin authoring의 timeout/retry/queue/stale 판단 기준을 코드, docs, tests에서 명시하고 `S02` completion evidence가 과대 기록되지 않게 한다.
- 포함: 직전 루프의 `RunTimeout` 우회와 `MODEL_TIMEOUT_SEC=900` 기본값은 유지하되, 그 위에 부족한 SDD evidence를 닫는다.
- 제외: `/v1/responses` streaming/fallback progress 구현은 `02+01_iop_progress` 범위다.
- 제외: push-only workspace agent request와 remote `develop` 검증은 `03+01,02_push_command` 범위다.
- 제외: live full-cycle smoke는 이 follow-up의 pass 조건이 아니다.

## 빌드 등급

- `cloud-G07`: 외부 IOP long-running runtime semantics와 SDD completion evidence 신뢰가 핵심이며, timeout/retry/stale 판단이 scheduler/config/docs/tests에 걸쳐 있어 cloud lane이 맞다.

## 구현 체크리스트

- [ ] `iop-long-run`/`S02` 완료 주장에 맞게 Plane-origin authoring의 timeout, retry, queue 대기 timeout, stale 판단 기준을 코드 또는 명시적 config/docs로 닫는다. 검증: focused tests에서 generic timeout 유지, authoring non-premature failure, stale/queue/retry metadata 또는 판단 evidence가 함께 확인된다.
- [ ] `services/core/README.md`와 관련 config/helper/docs가 `MODEL_TIMEOUT_SEC`, `WORKFLOW_TASK_TIMEOUT_SEC`, River retry, authoring stale/queue 기준을 서로 충돌 없이 설명한다.
- [ ] `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...`와 `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_AUTHORING_RUNTIME-1] Complete S02 timeout/retry/stale policy evidence

문제:

직전 구현은 authoring task에 generic `RunTimeout`을 적용하지 않으므로 10분 전 조기 `failed` 문제는 줄였다. 그러나 active target은 `iop-long-run` 전체 완료이고, SDD `S02` evidence는 timeout, retry, queue 대기, stale 판단 기준을 요구한다. 현재 코드와 문서는 `authoring_run_updated_at`을 남기지만 stale threshold가 어디서 설정되는지, queue 대기를 언제 stale/timeout으로 판단하는지, retryable 판단이 long-running authoring에 어떤 metadata로 확인되는지 닫지 않는다.

Before:

```go
// services/core/internal/scheduler/jobs.go
if _, isAuthoring := authoring.TaskCheckoutMetadata(task); isAuthoring {
	_ = w.Lifecycle.MergeTaskMetadata(ctx, taskID, map[string]any{
		workflow.MetadataKeyAuthoringRunState:     "in_progress",
		workflow.MetadataKeyAuthoringRunUpdatedAt: time.Now().UTC().Format(time.RFC3339),
	})
}
```

해결 방법:

- 기존 `RunTimeout` 우회는 유지한다.
- 기존 구조에 맞는 최소 단위로 authoring long-run observation policy를 명시한다. 가능한 방향은 다음 중 코드베이스에 가장 작은 변경으로 맞는 것을 택한다:
  - config/default 상수 또는 helper로 authoring stale threshold/queue wait threshold를 드러내고 README에 기록한다.
  - queue 상태 task와 running authoring task에서 `authoring_run_updated_at`, task `UpdatedAt`, attempt/retryable metadata를 어떻게 판단하는지 scheduler/workflow 테스트가 검증할 수 있게 한다.
  - 실제 monitor 구현이 아직 후속 범위라면 active `Roadmap Targets`/`Spec Targets` 완료 주장을 유지하지 말고, 이번 follow-up에서 완료 evidence를 foundation-only로 축소한다. 단, `check-on-pass`를 유지하려면 `S02` evidence를 닫아야 한다.
- tests는 단순 존재 확인이 아니라 다음을 구분해야 한다:
  - generic task는 짧은 `RunTimeout`에서 timeout failure와 `retryable` metadata를 유지한다.
  - Plane-origin authoring은 generic `RunTimeout`으로 failed가 되지 않는다.
  - Plane-origin authoring의 stale/queue/retry 판단 기준이 metadata 또는 helper output으로 관찰 가능하다.
- docs/helper default는 code default와 같은 숫자와 의미를 사용한다. `WORKFLOW_TASK_TIMEOUT_SEC`는 generic worker attempt timeout, `MODEL_TIMEOUT_SEC`는 IOP Responses HTTP 실행 bound, authoring stale/queue 기준은 별도 의미로 설명한다.

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/jobs.go` 또는 인접 helper: authoring long-run observation policy가 코드에서 확인 가능하게 한다.
- [ ] `services/core/internal/scheduler/jobs_test.go`: S02 evidence를 timeout/retry/stale/queue 관점으로 보강한다.
- [ ] `services/core/internal/config/config.go`와 `services/core/internal/config/config_test.go`: 새 threshold/config를 도입하는 경우 default와 env override를 검증한다.
- [ ] `services/core/README.md`, `services/core/Makefile`, `services/core/bin/run`, `services/core/docker-compose.yml`: default와 설명이 code와 충돌하지 않게 갱신한다.
- [ ] 필요 시 `services/core/internal/adapters/openai/client.go`와 `client_test.go`: model timeout default alignment가 깨지지 않는지 유지한다.

테스트 작성:

- focused scheduler/config tests를 우선한다.
- 새 config key를 도입하면 override test를 추가한다.
- DB migration test는 schema 변경이 없으면 필요 없다.

중간 검증:

```sh
cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
```

Expected: tests pass without cache, and new/updated tests explicitly cover `S02` completion evidence.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/scheduler/jobs.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/internal/scheduler/jobs_test.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/internal/config/config.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/internal/config/config_test.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/internal/adapters/openai/client.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/internal/adapters/openai/client_test.go` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/README.md` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/Makefile` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/bin/run` | REVIEW_AUTHORING_RUNTIME-1 |
| `services/core/docker-compose.yml` | REVIEW_AUTHORING_RUNTIME-1 |

## 최종 검증

```sh
cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...
```

Expected: pass; Go test cache is not acceptable because timeout/stale/retry behavior changed.

```sh
git diff --check
```

Expected: no output.

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