<!-- task=m-backtest-scenario-automation/07+05_result_poll_remote plan=0 tag=TEST -->

# Result Poll Remote Evidence Plan

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

검증을 실행한 뒤 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션에 실제 stdout/stderr를 채운다. active 파일을 유지하고 리뷰 준비를 보고한다. 최종 판정, archive, `complete.log` 작성은 code-review 전용이다. 사용자 소유 환경/secret 준비가 필요하면 직접 묻지 말고 review stub의 `사용자 리뷰 요청`에 근거를 남긴다.

## 배경

작은 선행 수정으로 `backtest_result_summary.yaml`은 start 직후 result를 조회하지 않고 `poll_backtest_run`으로 terminal `succeeded`에 도달한 뒤 result를 조회하도록 바뀌었다. 하지만 로드맵 Task의 완료 기준은 원격 runner에서 실제 API socket 대상으로 exit code 0과 result summary key evidence를 기록하는 것이다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 prompt는 금지이며 code-review가 user review gate를 소유한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/backtest-loop/milestones/backtest-scenario-automation.md`
- Task ids:
  - `result-poll`: `backtest_result_summary.yaml`이 terminal status 도달 후 result를 조회하도록 flaky 구간을 제거하고 원격 JSONL evidence를 기록한다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/backtest-loop/milestones/backtest-scenario-automation.md`
- `agent-test/local/rules.md`
- `agent-test/local/operations-smoke.md`
- `agent-test/local/api-smoke.md`
- `agent-test/local/worker-smoke.md`
- `apps/cli/internal/operator/scenario.go`
- `apps/cli/internal/operator/runner.go`
- `apps/cli/internal/operator/handoff_test.go`
- `apps/cli/testdata/operator/backtest_result_summary.yaml`
- `apps/cli/testdata/operator/expected/backtest_result_summary.jsonl`
- `apps/cli/testdata/operator/headless_validation.md`

### 테스트 환경 규칙

`test_env=local`이다. operations/api/worker smoke profile을 읽었다. local regression은 `go test -count=1 ./apps/cli/internal/operator ./apps/cli/internal/cli`이고, 완료 검증은 원격 API socket 대상 CLI scenario run이다. raw endpoint/secret은 task artifact에 기록하지 않는다.

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

- local test는 fixture 순서와 JSONL key를 검증하지만 실제 원격 API/worker/DB/KIS runtime의 flake 제거를 보장하지 않는다.
- 원격 API socket 값과 secret env는 private runtime 상태이므로 review stub에는 sanitized command/output만 남긴다.

### 심볼 참조

none. 작은 fixture/test 수정은 이미 적용됐고 rename/remove 없음.

### 분할 판단

`07+05_result_poll_remote`는 `05+04_runtime_startup` 완료 후 독립적으로 실행 가능하다. `06+05_matrix_seed`와 같은 predecessor를 공유하지만 matrix seed 완료에 의존하지 않는다.

### 범위 결정 근거

runtime startup은 predecessor가 소유한다. matrix seed는 sibling plan이 소유한다. 이 작업은 `backtest_result_summary.yaml` 원격 evidence와 필요 시 handoff 문서 보강만 완료 대상으로 삼는다.

### 빌드 등급

`cloud-G06`. 코드 범위는 작지만 실제 완료 조건이 원격 runtime evidence라 remote stdout 신뢰성과 secret redaction이 중요하다.

## 의존 관계 및 구현 순서

`07+05_result_poll_remote`는 디렉터리명 기준으로 `05+04_runtime_startup`에 의존한다. 구현 시작 전 `05+04_runtime_startup` complete.log를 확인한다.

## 구현 체크리스트

- [ ] `05+04_runtime_startup` complete.log가 있는지 확인하고 경로를 기록한다.
- [ ] local checkout에서 `backtest_result_summary.yaml`이 `start -> poll -> result` 순서인지 확인한다.
- [ ] 원격 runner의 `apps/cli`에서 `backtest_result_summary.yaml`을 원격 API socket 대상으로 실행하고 exit code 0을 기록한다.
- [ ] 원격 JSONL에 `run_status=succeeded`, `starting_cash`, `ending_equity`, `total_return`, `trade_count`가 포함되는지 실제 출력으로 기록한다.
- [ ] 필요하면 `apps/cli/testdata/operator/headless_validation.md`에 result-poll remote evidence 절차를 raw 값 없이 보강한다.
- [ ] `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [TEST-1] Remote result summary polls before result read

#### 문제

[agent-roadmap/phase/backtest-loop/milestones/backtest-scenario-automation.md](/config/workspace/alt/agent-roadmap/phase/backtest-loop/milestones/backtest-scenario-automation.md:51)는 원격 runner에서 `run_status=succeeded`와 result summary keys를 함께 기록해야 한다고 요구한다. [apps/cli/testdata/operator/backtest_result_summary.yaml](/config/workspace/alt/apps/cli/testdata/operator/backtest_result_summary.yaml:29)는 poll step을 추가했고 [apps/cli/testdata/operator/backtest_result_summary.yaml](/config/workspace/alt/apps/cli/testdata/operator/backtest_result_summary.yaml:37)는 result 조회를 그 뒤로 둔다. 원격 API/worker가 실제로 terminal status 이후 result를 제공하는지는 아직 evidence가 없다.

#### 해결 방법

`05+04_runtime_startup`이 완료된 원격 runtime을 그대로 사용한다. `apps/cli`에서 `go run ./cmd/alt operator scenario run --file testdata/operator/backtest_result_summary.yaml --api-url "ws://127.0.0.1:18030/socket" --output jsonl`을 실행하고, JSONL에 poll line의 `run_status=succeeded`와 result line summary keys가 함께 있는지 기록한다.

#### 수정 파일 및 체크리스트

- [ ] `apps/cli/testdata/operator/headless_validation.md` - 필요 시 remote result-poll evidence 절차를 raw 값 없이 보강한다.
- [ ] 소스 변경 없음이 맞는지 확인한다. 추가 수정이 생기면 reason과 tests를 기록한다.

#### 테스트 작성

새 unit test는 작성하지 않는다. 이미 `apps/cli/internal/operator/handoff_test.go`가 fixture 순서를 검증하도록 작은 수정이 적용됐다. 이 plan은 원격 runtime evidence를 모으는 작업이다.

#### 중간 검증

```bash
go test -count=1 ./apps/cli/internal/operator ./apps/cli/internal/cli
```

기대 결과: exit code 0.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/cli/testdata/operator/headless_validation.md` | TEST-1, 필요 시 |
| active review stub | TEST-1 evidence 기록 |

## 최종 검증

```bash
git diff --check
go test -count=1 ./apps/cli/internal/operator ./apps/cli/internal/cli
test -f agent-task/m-backtest-scenario-automation/05+04_runtime_startup/complete.log || find agent-task/archive -path '*/m-backtest-scenario-automation/05+04_runtime_startup/complete.log' -print -quit
rg --sort path -n "poll_backtest_run|run_status: succeeded|get_backtest_result" apps/cli/testdata/operator/backtest_result_summary.yaml apps/cli/testdata/operator/headless_validation.md
ssh "$ALT_REMOTE_SSH" "set -euo pipefail; cd \"$ALT_REMOTE_ALT_ROOT/apps/cli\"; go run ./cmd/alt operator scenario run --file testdata/operator/backtest_result_summary.yaml --api-url \"ws://127.0.0.1:18030/socket\" --output jsonl"
```

기대 결과: local commands exit code 0. Remote command exit code 0 and JSONL contains `run_status=succeeded`, `starting_cash`, `ending_equity`, `total_return`, `trade_count`. Go test cache output은 허용하지 않고 `-count=1` fresh run을 사용한다.

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