<!-- task=m-operator-headless-workflow-validation/01_scenario_core plan=1 tag=REVIEW_OPS -->

# Plan - REVIEW_OPS Scenario Core Follow-up

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

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이 필수다. 구현 후 검증을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 충돌로 막히면 review stub의 `사용자 리뷰 요청` 섹션에 근거를 채우고 멈춘다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

첫 구현은 `apps/cli` scenario parser와 validate command의 핵심 동작을 추가했고 focused CLI 검증은 원격에서 통과했다. 코드 리뷰는 두 가지 Required 공백을 발견했다.

- `plan_cloud_G07_0.log`의 테스트 커버리지 분석은 invalid duration 거부 테스트를 요구했지만 `apps/cli/internal/operator/scenario_test.go`에 해당 테스트가 없다.
- 필수 operations smoke인 `bin/test`는 원격 host에서 `protoc-gen-go` 미설치로 exit code 1을 반환했으므로, milestone task를 PASS 처리할 검증 신뢰도가 아직 닫히지 않았다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 형식으로 기록한다. code-review가 해당 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md`
- Task ids:
  - `scenario-format`: operator scenario를 YAML 또는 동등한 파일 형식으로 표현한다.
- Completion mode: check-on-pass

## 리뷰 근거

- Archived plan: `agent-task/m-operator-headless-workflow-validation/01_scenario_core/plan_cloud_G07_0.log`
- Archived review: `agent-task/m-operator-headless-workflow-validation/01_scenario_core/code_review_cloud_G07_0.log`
- Verdict: FAIL
- Required issues:
  - invalid duration test coverage missing.
  - `bin/test` required smoke not yet passing because `protoc-gen-go` is absent on the remote test host PATH.

## 범위 결정 근거

- 이 follow-up은 `apps/cli` test coverage와 원격 검증 신뢰도만 닫는다.
- `services/api/**`, `services/worker/**`, `packages/contracts/proto/**`, `apps/client/**`는 수정하지 않는다.
- `protoc-gen-go` 준비가 필요하면 repo source가 아니라 원격 test host toolchain 준비로 처리한다. toolchain 준비가 사용자만 할 수 있는 정책/권한 문제로 막힐 때만 `사용자 리뷰 요청`을 채운다.
- `bin/test`가 toolchain 준비 뒤 source 문제로 실패하면 해당 실패를 숨기지 말고 정확한 stdout/stderr와 함께 필요한 최소 코드 수정으로 처리한다.

## 빌드 등급

- build lane: `cloud-G07`, review lane: `cloud-G07`.
- 이유: `bin/test`, codegen toolchain, stdout/stderr evidence, exit-status contract를 다루는 terminal-agent follow-up이다.

## 구현 체크리스트

- [ ] `apps/cli/internal/operator/scenario_test.go`에 invalid duration rejection test를 추가하고 원격 focused CLI test에서 통과를 확인한다.
- [ ] 원격 ALT checkout root에서 `protoc-gen-go`를 확인/준비한 뒤 `bin/test`를 exit code 0으로 완주하고 stdout/stderr를 기록한다.
- [ ] 원격 ALT checkout root에서 scenario validate command를 재실행해 출력 계약을 재확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 변경 및 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_OPS-1] Invalid Duration Test Coverage

#### 문제

`plan_cloud_G07_0.log`의 테스트 커버리지 분석은 invalid duration을 덮어야 한다고 기록했지만 현재 테스트는 정상 fixture, unknown action, missing step id만 검증한다. `operator.Duration.UnmarshalYAML`이 실제로 invalid duration을 거부하더라도 테스트가 없어 schema 회귀를 잡지 못한다.

#### 해결 방법

- `apps/cli/internal/operator/scenario_test.go`에 invalid timeout YAML을 `ParseScenario`로 입력하는 테스트를 추가한다.
- 테스트 이름 예: `TestParseScenarioRejectsInvalidDuration`.
- 입력 예:

```yaml
name: invalid_timeout
timeout: not-a-duration
steps:
  - id: hello
    action: hello
```

- 기대: error가 nil이 아니고 `invalid timeout` 또는 duration parse 실패를 식별할 수 있는 문자열을 포함한다.

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

- [ ] `apps/cli/internal/operator/scenario_test.go`: invalid duration rejection test를 추가한다.

#### 중간 검증

원격 ALT checkout root 기준:

```bash
(cd apps/cli && go test -count=1 ./...)
```

기대 결과: exit code 0. `internal/operator` 테스트가 cache 없이 실행된다.

### [REVIEW_OPS-2] Operations Smoke Verification Trust

#### 문제

첫 구현의 최종 검증에서 `bin/test`는 `contracts-gen: required command not found: protoc-gen-go`로 실패했다. 대체 모듈 테스트는 유용한 근거지만, operations smoke profile의 필수 command인 `bin/test` 자체가 exit code 0으로 완주했다는 증거를 대체하지 못한다.

#### 해결 방법

- 원격 ALT checkout root에서 테스트용 PATH를 잡고 `command -v protoc-gen-go`를 먼저 실행한다.
- 없으면 generated Go 파일에 기록된 버전과 맞춰 `go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11`로 host toolchain을 준비하고 `$HOME/go/bin`이 PATH에 포함됐는지 확인한다.
- 이후 `bin/test`를 그대로 재실행한다.
- `bin/test`가 drift나 source 문제로 실패하면 실패 stdout/stderr를 기록하고, 이 follow-up 범위에서 필요한 최소 수정만 수행한다.

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

- [ ] 원격 host에서 `command -v protoc-gen-go` 결과를 기록한다.
- [ ] 필요한 경우 `go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11`로 `protoc-gen-go`를 준비한다.
- [ ] `bin/test`를 exit code 0으로 완주하고 실제 stdout/stderr를 review stub에 붙인다.

#### 중간 검증

원격 ALT checkout root 기준:

```bash
command -v protoc-gen-go
bin/test
```

기대 결과: `command -v protoc-gen-go`는 경로를 출력하고 exit code 0. `bin/test`는 contracts check, Go module tests, Flutter tests를 모두 통과하고 exit code 0.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/cli/internal/operator/scenario_test.go` | REVIEW_OPS-1 |
| 원격 test host toolchain evidence | REVIEW_OPS-2 |

## 최종 검증

모든 명령은 원격 ALT checkout root 기준으로 실행한다. 현재 local shell에서 직접 실행하지 않는다.

```bash
export PATH="$HOME/SDK/flutter/bin:$HOME/SDK/flutter/bin/cache/dart-sdk/bin:/opt/homebrew/bin:/usr/local/bin:/usr/local/go/bin:$HOME/go/bin:$PATH"
command -v protoc-gen-go
(cd apps/cli && go test -count=1 ./...)
(cd apps/cli && go run ./cmd/alt operator scenario validate --file testdata/operator/api_connection_smoke.yaml)
bin/test
```

기대 결과: 모든 명령 exit code 0. `bin/test`가 contracts check, Go module tests, Flutter tests를 통과한다. 원격 host toolchain 준비가 권한/정책상 불가능하면 pass가 아니라 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 사용자에게 필요한 결정, 재개 조건을 남긴다.

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