<!-- task=m-external-integration/02+01_nomadcode_core_iop_smoke plan=1 tag=REVIEW_NC-IOP-SMOKE -->

# Plan: REVIEW_NC-IOP-SMOKE

## 작업 범위

이 follow-up은 `NC-IOP-SMOKE` 1차 리뷰에서 FAIL된 검증 신뢰도 문제만 닫는다. NomadCode Core metadata 전달 코드와 unit test는 이미 통과했으므로, 변경은 필요한 경우 remote runner 실행/검증 절차와 좁은 설정 drift 정리에 한정한다. 목표는 standard remote runner에서 현재 NomadCode checkout과 현재 Core 컨테이너가 실제 IOP Edge Responses listener를 바라보는 상태를 확인한 뒤, 같은 실행 흐름에서 task create/enqueue/poll smoke를 다시 수행하는 것이다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/external-integration/milestones/external-integration.md`
- 완료 대상 Task id: `iop-responses`

## 리뷰 결과 요약

- 1차 리뷰 판정: FAIL
- Required issue: `./bin/docker-up -d`가 Core 컨테이너를 재빌드/재시작한 뒤 `MODEL_BASE_URL`이 기본 Ollama URL로 돌아갔고, 기록된 task create/enqueue/poll 결과는 재시작 이전 컨테이너에서 나온 증거라 완료 근거로 신뢰할 수 없다.
- 리뷰어가 재확인한 상태: remote Core 컨테이너의 현재 `MODEL_BASE_URL`은 IOP Edge가 아니라 기본 Ollama URL이다. remote `go test ./... && go vet ./...`와 캐시 없는 핵심 패키지 테스트는 통과했다.

## 범위 결정 근거

- 코드 변경 자체는 `services/core/internal/adapters/openai/client.go`, `services/core/internal/adapters/openai/client_test.go`, `services/core/internal/scheduler/jobs_test.go`의 metadata 전달/검증 범위로 충분하다.
- Milestone 완료 주장에는 실제 remote Core compose가 IOP Edge로 붙어 task를 완료한 증거가 필요하다.
- credential, private endpoint, raw secret은 기록하지 않는다. 필요한 값은 runner 환경의 ignored local secret 또는 현재 shell/env에서 로드하되 출력에는 redaction 또는 non-secret alias만 남긴다.
- 구현 중 사용자만 결정할 항목이나 사용자 소유 secret 준비가 필요하다고 확인되면 직접 질문하지 말고 `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션을 채운 뒤 중단한다.

## 구현 계획

1. remote runner checkout의 `git rev-parse --abbrev-ref HEAD`, `git rev-parse HEAD`, relevant file `git status --short`를 기록한다. 로컬 검증 대상과 달라서 smoke 의미가 흔들리면 안전하게 동기화하거나, 동기화 불가 사유를 사용자 리뷰 요청에 남긴다.
2. remote IOP Edge listener의 `/healthz`, `/v1/models`, `POST /v1/responses` smoke를 다시 수행한다. 이때 요청 metadata에는 secret이 아닌 marker를 사용하고, 실제 응답 body를 sanitized 형태로 기록한다.
3. Core compose를 `NOMADCODE_CORE_HOST_PORT=18010`과 실제 IOP Edge OpenAI-compatible listener용 `MODEL_BASE_URL`로 기동한다. `AUTH_PASSWORD` 등 secret은 출력하지 않는다.
4. `docker inspect` 또는 동등한 명령으로 현재 `nomadcode-core-nomadcode-core-1` 컨테이너의 `MODEL_BASE_URL`, `MODEL_NAME`, `MODEL_CONTEXT_SIZE`, `MODEL_TIMEOUT_SEC`가 기대 상태인지 확인한다. `AUTH_PASSWORD`와 token류는 출력하지 않는다.
5. 같은 컨테이너 실행 이후 Core `/healthz`와 authenticated `/readyz`를 확인한다.
6. 위 env 확인 이후 새 Core smoke task를 생성하고 enqueue한다. `GET /api/tasks/{id}`를 poll 해서 `status=completed`, result `mode=openai_responses`, `message` 또는 `response_id`가 IOP Edge 응답과 일치함을 기록한다.
7. Core metadata 전달 근거를 같은 run과 연결한다. 가능하면 IOP Edge sanitized runtime log에서 Core-created task id/source marker를 확인하고, 불가능하면 Core unit test와 IOP metadata parser evidence의 한계를 명시한다.
8. remote `go test ./... && go vet ./...` 또는 최소 캐시 없는 핵심 패키지 테스트를 재실행하고 실제 stdout/stderr를 붙인다.

## 구현 체크리스트

- [ ] remote runner checkout/head/status를 확인하고, 현재 NomadCode source가 이 task에서 검증할 source와 동기화됐음을 검증 결과에 기록한다.
- [ ] IOP Edge listener의 `/healthz`, `/v1/models`, `POST /v1/responses` smoke를 실제 remote listener 기준으로 재수집한다.
- [ ] Core compose를 `NOMADCODE_CORE_HOST_PORT=18010`과 실제 IOP Edge용 `MODEL_BASE_URL`로 기동하고, 현재 컨테이너 env가 그 값을 가진다는 증거를 기록한다.
- [ ] Core `/healthz`와 authenticated `/readyz`를 현재 컨테이너 기동 이후에 확인한다.
- [ ] 새 Core task create/enqueue/poll을 현재 IOP 연결 컨테이너에서 수행하고 `completed`, `mode=openai_responses`, IOP 응답 marker를 기록한다.
- [ ] Core-created task의 `task_id`, `source` metadata가 IOP boundary까지 전달됐다는 sanitized runtime evidence 또는 명확한 test evidence를 기록한다.
- [ ] local/remote Go 검증을 재실행하고 실제 stdout/stderr를 붙인다.
- [ ] raw secret, token, private endpoint 원문을 tracked docs, roadmap, final report에 남기지 않는다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 검증 계획

- Local focused regression: `cd /config/workspace/nomadcode/services/core && go test -count=1 ./internal/adapters/openai ./internal/scheduler`
- Remote baseline: `ssh toki@toki-labs.com "zsh -lc 'cd \$HOME/agent-work/nomadcode/services/core && go test ./... && go vet ./...'"`.
- IOP remote smoke: `/healthz`, `/v1/models`, `POST /v1/responses` against the active Edge listener.
- Core remote smoke: after `docker inspect` confirms IOP `MODEL_BASE_URL`, run `POST /api/tasks`, `POST /api/tasks/{id}/enqueue`, and `GET /api/tasks/{id}` polling to `completed`.

## 리뷰어 체크포인트

- Core create/enqueue/poll evidence must occur after the recorded Core container env check.
- `MODEL_BASE_URL` must point to the actual IOP Edge OpenAI-compatible listener for the smoke run, not the default Ollama endpoint.
- Remote checkout evidence must be good enough to know which source was tested.
- Verification output must be actual stdout/stderr, not summarized-only package status.
- No raw password, token, or private endpoint should appear in final report or roadmap.
