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

# Implementation Plan - AUTHORING_RUNTIME

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

이 plan의 구현 완료는 active `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운 뒤에만 성립한다. 구현 중 선택된 SDD 결정 또는 선택된 Milestone `구현 잠금 > 결정 필요` 항목이 막히면 채팅으로 묻지 말고 review stub의 `사용자 리뷰 요청` 섹션을 채운 뒤 멈춘다. 환경, secret, 외부 서비스, 검증 증거 부족은 사용자 리뷰 요청이 아니며 `검증 결과` 또는 후속 plan으로 남긴다. archive, `complete.log`, roadmap 갱신은 code-review/runtime 소유다.

## 배경

`authoring-runtime` 에픽의 `iop-long-run` Task는 Plane-origin authoring이 10분 이상 걸리는 IOP Responses 작업을 조기 실패로 확정하지 않도록 요구한다. 현재 core는 모델 HTTP timeout과 scheduler worker timeout이 모두 300초 기본값이고, scheduler가 모든 작업 실행에 같은 `RunTimeout`을 씌운다. 이 plan은 authoring 작업이 generic task timeout에 끌려 실패하지 않게 하고, 10분 이상 작업의 관찰 가능한 metadata를 남기는 foundation 작업만 다룬다.

## 사용자 리뷰 요청 흐름

구현 중 직접 사용자에게 질문하지 않는다. 선택된 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

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/roadmap-sdd/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-roadmap/current.md`
- `agent-roadmap/phase/agent-ops-mcp-control-plane/PHASE.md`
- `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/plane-origin-authoring-roundtrip-sync.md`
- `agent-roadmap/sdd/agent-ops-mcp-control-plane/plane-origin-authoring-roundtrip-sync/SDD.md`
- `agent-ops/rules/project/domain/core/rules.md`
- `agent-ops/rules/project/domain/workspace-ops/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/core-smoke.md`
- `agent-test/local/workspace-ops-smoke.md`
- `agent-test/live-cycle-smoke.md`
- `services/core/internal/config/config.go`
- `services/core/internal/config/config_test.go`
- `services/core/internal/model/model.go`
- `services/core/internal/workflow/model.go`
- `services/core/internal/adapters/openai/client.go`
- `services/core/internal/adapters/openai/client_test.go`
- `services/core/internal/authoring/request.go`
- `services/core/internal/authoring/request_test.go`
- `services/core/internal/authoring/result.go`
- `services/core/internal/authoring/result_test.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/agent/agent.go`
- `services/core/internal/adapters/a2a/client.go`
- `services/core/internal/adapters/a2a/client_test.go`
- `services/core/cmd/server/main.go`
- `services/core/README.md`
- `services/core/docker-compose.yml`
- `services/core/Makefile`
- `services/core/bin/run`
- `services/core/go.mod`

### 테스트 환경 규칙

- test_env: `local`.
- `agent-test/local/rules.md` present/read. Matching profiles read: `agent-test/local/core-smoke.md`, `agent-test/local/workspace-ops-smoke.md`.
- core 필수 검증: `cd services/core && go test ./...`; focused 검증은 `go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...`.
- workspace-ops 문서/task artifact 변경 검증: `git diff --check`.
- `agent-test/live-cycle-smoke.md`는 live gate 참고로 읽었지만 이 plan의 pass 조건에는 포함하지 않는다.

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

- Generic worker timeout은 `services/core/internal/scheduler/jobs_test.go:305`의 `TestWorkMarksTimeoutFailure`가 덮는다.
- Plane-origin authoring이 `RunTimeout` 때문에 조기 `failed`가 되지 않는 회귀 테스트는 없다.
- `MODEL_TIMEOUT_SEC` 기본값과 dev helper/compose/README의 장시간 기준 일관성 테스트는 없다.

### 심볼 참조

- renamed/removed symbol: none.
- 새 config 필드나 model result 필드를 도입하면 `cmd/server/main.go`, `internal/config`, `internal/adapters/openai`, `internal/scheduler` call site를 모두 갱신한다.

### 분할 판단

- split decision policy를 먼저 평가했다.
- 공유 task group: `agent-task/m-plane-origin-authoring-roundtrip-sync`.
- `01_iop_long_run`: independent foundation. scheduler timeout/config/metadata 기준을 먼저 세운다.
- `02+01_iop_progress`: depends on `01`; progress metadata와 streaming/fallback은 timeout foundation 위에서 구현한다. predecessor `01`: missing active/archive `complete.log`.
- `03+01,02_push_command`: depends on `01` and `02`; push-only 단계는 장시간/progress metadata와 completion gate를 재사용한다. predecessors `01`, `02`: missing active/archive `complete.log`.

### 범위 결정 근거

- 포함: authoring long-run timeout policy, default model timeout 문서/helper 일관성, scheduler authoring timeout regression tests.
- 제외: `/v1/responses` streaming/SSE parsing은 `02+01_iop_progress`.
- 제외: push-only workspace agent request는 `03+01,02_push_command`.
- 제외: identity-sync, gito-plane, live-gate 에픽 Task.

### 빌드 등급

- `cloud-G07`: 외부 IOP long-running runtime semantics가 핵심이고 generic task timeout과 authoring terminal state를 분리해야 하므로 cloud lane이 맞다.

## 구현 체크리스트

- [ ] `iop-long-run` 기준으로 authoring 작업은 generic `WORKFLOW_TASK_TIMEOUT_SEC`로 조기 `failed` 처리되지 않고, `MODEL_TIMEOUT_SEC`/helper/docs는 10분 이상 실행 가능한 기본선으로 정리한다. 검증: focused Go tests에서 generic timeout은 유지되고 authoring은 관찰 가능한 in-progress/stale metadata를 남긴다.
- [ ] `services/core/README.md`, `services/core/Makefile`, `services/core/bin/run`, `services/core/docker-compose.yml`의 timeout 설명/기본값이 code default와 충돌하지 않게 갱신한다.
- [ ] `cd services/core && go test -count=1 ./internal/config/... ./internal/scheduler/... ./internal/adapters/openai/...`와 `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [AUTHORING_RUNTIME-1] Authoring long-run timeout foundation

문제:

`services/core/internal/config/config.go:86` and `services/core/internal/config/config.go:105` default both model and workflow task timeout to 300 seconds. `services/core/internal/adapters/openai/client.go:20` and `services/core/internal/adapters/openai/client.go:39` repeat the 300 second model timeout default. `services/core/internal/scheduler/jobs.go:92` applies `RunTimeout` to every task before `w.runTask`, so a Plane-origin authoring call can hit `context.DeadlineExceeded` and `markFailedWithTask` before 10 minutes.

Before:

```go
// services/core/internal/scheduler/jobs.go:92
runCtx := ctx
if w.RunTimeout > 0 {
	var cancel context.CancelFunc
	runCtx, cancel = context.WithTimeout(ctx, w.RunTimeout)
	defer cancel()
}

result, message, err := w.runTask(runCtx, task)
```

해결 방법:

- Add a small scheduler helper that chooses execution context by task type. Generic tasks keep `RunTimeout`; Plane-origin authoring tasks do not inherit the generic worker deadline and instead rely on model timeout/progress/stale metadata.
- Raise model timeout defaults used for IOP Responses authoring to at least 900 seconds in `config`, `openai`, `Makefile`, `bin/run`, `docker-compose.yml`, and README examples. Keep env override behavior.
- Keep `WORKFLOW_TASK_TIMEOUT_SEC` documented as generic worker-attempt timeout; document that Plane-origin authoring is long-running and observed through `authoring_run_state`, `authoring_run_updated_at`, and later stale/progress metadata.
- Add scheduler tests proving a short `RunTimeout` still fails generic model work but does not cancel a Plane-origin authoring model call that completes after that generic timeout.

수정 파일 및 체크리스트:

- [ ] `services/core/internal/scheduler/jobs.go`: extract context selection and exempt authoring tasks from generic `RunTimeout`.
- [ ] `services/core/internal/scheduler/jobs_test.go`: add authoring long-run regression test; keep `TestWorkMarksTimeoutFailure` generic behavior.
- [ ] `services/core/internal/config/config.go`: update model timeout default or introduce named constants if local style stays simple.
- [ ] `services/core/internal/config/config_test.go`: update default assertions and add override assertion if new field/constant is introduced.
- [ ] `services/core/internal/adapters/openai/client.go`: keep client default aligned with config default.
- [ ] `services/core/internal/adapters/openai/client_test.go`: add/adjust timeout-default test if needed.
- [ ] `services/core/README.md`, `services/core/Makefile`, `services/core/bin/run`, `services/core/docker-compose.yml`: update default examples and long-running authoring note.

테스트 작성:

- Write regression tests in `services/core/internal/scheduler/jobs_test.go`.
- Update config/adapter tests for timeout defaults.
- No DB migration test is required; no schema is changed.

중간 검증:

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

Expected: tests pass, including new authoring long-run regression and existing generic timeout failure.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/core/internal/scheduler/jobs.go` | AUTHORING_RUNTIME-1 |
| `services/core/internal/scheduler/jobs_test.go` | AUTHORING_RUNTIME-1 |
| `services/core/internal/config/config.go` | AUTHORING_RUNTIME-1 |
| `services/core/internal/config/config_test.go` | AUTHORING_RUNTIME-1 |
| `services/core/internal/adapters/openai/client.go` | AUTHORING_RUNTIME-1 |
| `services/core/internal/adapters/openai/client_test.go` | AUTHORING_RUNTIME-1 |
| `services/core/README.md` | AUTHORING_RUNTIME-1 |
| `services/core/Makefile` | AUTHORING_RUNTIME-1 |
| `services/core/bin/run` | AUTHORING_RUNTIME-1 |
| `services/core/docker-compose.yml` | 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 behavior changed.

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

Expected: no output.

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