feat: add CLI profile proto message agent-task logs
This commit is contained in:
parent
f873e27a15
commit
8cc12865c1
9 changed files with 928 additions and 0 deletions
|
|
@ -0,0 +1,154 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=0 tag=API -->
|
||||
|
||||
# Code Review Reference - API
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=0, tag=API
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.
|
||||
|
||||
1. `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_N.log` (N = 기존 code_review_*.log 수)
|
||||
2. `PLAN-cloud-G09.md` → `plan_cloud_G09_M.log` (M = 기존 plan_*.log 수)
|
||||
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 routed plan + review 스텁 작성.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [API-1] proto 메시지 정의 및 생성물 갱신 | [x] |
|
||||
| [API-2] edge buildConfigPayload typed 메시지 갱신 | [x] |
|
||||
| [API-3] node BuildFromPayload typed 메시지 갱신 | [x] |
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
- **`CLIProfileConfig`에 `completion_marker` / `mode` / `resume_args` 필드 추가**
|
||||
- 계획서 §[API-1]의 메시지 스펙에는 이 세 필드가 빠져 있었으나, 실제 `config.CLIProfileConf` (`packages/config/config.go:106-118`)와 기존 edge 직렬화 (`completion_marker`)에 이미 존재하던 필드입니다. 그대로 따르면 edge→node 전송에서 정보가 손실되어 기존 `TestBuildNodePayload_CLICompletionMarker`/`TestCLIConfFromStruct_ProfileCompletionMarker`가 깨지므로, 동일 의미의 typed 필드를 proto에 추가했습니다.
|
||||
- `CLICompletionMarker` 메시지(line/regex)를 별도 정의했습니다.
|
||||
- **`buildConfigPayload`의 mock 어댑터는 빈 `structpb.Struct`를 그대로 사용**합니다. 계획서 §[API-2]가 "mock 분기는 그대로 둔다"고 명시한 것에 따라 oneof 경로로 옮기지 않았습니다.
|
||||
- **헬퍼 정리**: 계획서대로 `cliConfFromStruct`/`ollamaConfFromStruct`/`vllmConfFromStruct`/`boolFromAny`/`intFromAny` 모두 제거했고, edge의 `stringsToAny`도 제거했습니다. `addAdapter` 클로저는 mock 한 곳에서만 쓰여 인라인으로 정리했습니다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- `AdapterConfig.settings` 필드는 plan 지침대로 보존했습니다 (mock 어댑터 호환성). cli/ollama/vllm은 `settings`를 채우지 않고 `oneof config`만 사용합니다.
|
||||
- `cliConfFromProto(nil)`은 `Enabled=true`, 빈 profiles 맵을 반환합니다. 호출 지점이 `ac.GetType() == "cli"` && `ac.GetEnabled() == true` 분기 안이라 typed config가 nil이어도 cli 어댑터를 등록하는 것이 자연스럽습니다.
|
||||
- proto 필드 번호: 계획서 스펙 그대로(1–8) + 추가 필드는 9–11에 배치했습니다.
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `proto/iop/runtime.proto`에 `oneof config`가 추가되고 기존 `settings` 필드가 backward-compat을 위해 유지되었는지
|
||||
→ `proto/iop/runtime.proto:131-173` 참조. `settings = 3` 유지, `oneof config`는 4-6번.
|
||||
- `proto/gen/iop/runtime.pb.go`가 사람이 직접 편집되지 않고 `make proto`로 생성된 변경인지
|
||||
→ `make proto` 실행만으로 생성. 헤더에 `protoc-gen-go v1.36.7 / protoc v5.29.3` 그대로.
|
||||
- edge `buildConfigPayload`가 cli/ollama/vllm 모두 oneof로 채우는지, 더이상 `stringsToAny` 등 우회 헬퍼가 남아있지 않은지
|
||||
→ `apps/edge/internal/transport/server.go:160-235` 참조. `stringsToAny` 제거 확인.
|
||||
- node `BuildFromPayload`에서 `cliConfFromStruct`/`boolFromAny`/`intFromAny`가 모두 제거되었는지
|
||||
→ `apps/node/internal/adapters/factory.go` 전체가 `cliConfFromProto`/`ollamaConfFromProto`/`vllmConfFromProto`로 교체됨. structpb import 제거.
|
||||
- Persistent/Terminal/Idle timeout 정수 필드가 손실 없이 전달되는 단위 테스트가 추가되었는지
|
||||
→ edge 측: `TestBuildConfigPayload_CLIOneof` (`apps/edge/internal/transport/server_test.go`). node 측: `TestCLIConfFromProto_PersistentAndIdleTimeouts` (`apps/node/internal/adapters/factory_internal_test.go`).
|
||||
|
||||
## 검증 결과
|
||||
|
||||
### API-1 중간 검증
|
||||
```
|
||||
$ make proto
|
||||
protoc \
|
||||
--go_out=. \
|
||||
--go_opt=module=iop \
|
||||
--proto_path=. \
|
||||
proto/iop/runtime.proto \
|
||||
proto/iop/node.proto \
|
||||
proto/iop/control.proto \
|
||||
proto/iop/job.proto
|
||||
$ go build ./proto/gen/...
|
||||
(no output)
|
||||
```
|
||||
|
||||
### API-2 중간 검증
|
||||
```
|
||||
$ go test ./apps/edge/internal/transport/...
|
||||
ok iop/apps/edge/internal/transport 0.006s
|
||||
```
|
||||
|
||||
### API-3 중간 검증
|
||||
```
|
||||
$ go test ./apps/node/internal/adapters/...
|
||||
ok iop/apps/node/internal/adapters 0.004s
|
||||
ok iop/apps/node/internal/adapters/cli 87.604s
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status (cached)
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ make proto
|
||||
protoc \
|
||||
--go_out=. \
|
||||
--go_opt=module=iop \
|
||||
--proto_path=. \
|
||||
proto/iop/runtime.proto \
|
||||
proto/iop/node.proto \
|
||||
proto/iop/control.proto \
|
||||
proto/iop/job.proto
|
||||
|
||||
$ go build ./...
|
||||
(no output)
|
||||
|
||||
$ go test ./...
|
||||
? iop/apps/control-plane/cmd/control-plane [no test files]
|
||||
ok iop/apps/edge/cmd/edge (cached)
|
||||
? iop/apps/edge/internal/bootstrap [no test files]
|
||||
ok iop/apps/edge/internal/node (cached)
|
||||
ok iop/apps/edge/internal/transport (cached)
|
||||
? iop/apps/node/cmd/node [no test files]
|
||||
ok iop/apps/node/internal/adapters (cached)
|
||||
ok iop/apps/node/internal/adapters/cli (cached)
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status (cached)
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
ok iop/apps/node/internal/bootstrap (cached)
|
||||
ok iop/apps/node/internal/node (cached)
|
||||
ok iop/apps/node/internal/router (cached)
|
||||
? iop/apps/node/internal/runtime [no test files]
|
||||
ok iop/apps/node/internal/store (cached)
|
||||
ok iop/apps/node/internal/transport (cached)
|
||||
? iop/apps/worker/cmd/worker [no test files]
|
||||
? iop/packages/auth [no test files]
|
||||
ok iop/packages/config (cached)
|
||||
? iop/packages/jobs [no test files]
|
||||
? iop/packages/metadata [no test files]
|
||||
? iop/packages/observability [no test files]
|
||||
? iop/packages/policy [no test files]
|
||||
? iop/packages/version [no test files]
|
||||
? iop/proto/gen/iop [no test files]
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: FAIL
|
||||
|
||||
- 차원별 평가
|
||||
- correctness: Fail
|
||||
- completeness: Fail
|
||||
- test coverage: Fail
|
||||
- API contract: Fail
|
||||
- code quality: Pass
|
||||
- plan deviation: Warn
|
||||
- verification trust: Pass
|
||||
|
||||
- 발견된 문제
|
||||
- Required — `apps/node/internal/adapters/factory.go:28-33`, `apps/node/internal/adapters/factory.go:41-63`, `proto/iop/runtime.proto:135`: `AdapterConfig.settings`를 `legacy/compat path`로 유지한다고 선언했지만 node 역직렬화가 `GetCli()/GetOllama()/GetVllm()`만 읽도록 바뀌어 구버전 payload 호환성이 실제로 깨졌습니다. oneof가 비어 있고 `settings`만 채워진 기존 payload를 받으면 `ollama`/`vllm`은 빈 endpoint로 등록되고, `cli`는 빈 profiles 맵으로 등록되어 동작이 망가집니다. `settings` fallback 파서를 유지해 oneof가 nil일 때만 legacy 경로를 복원하거나, 정말 호환을 끊을 계획이라면 proto 주석/plan/review 문서/배포 계약을 모두 breaking change로 명시하고 관련 검증을 바꿔야 합니다. 최소한 legacy payload를 넣는 회귀 테스트를 `apps/node/internal/adapters/factory_test.go` 또는 `factory_internal_test.go`에 추가해야 합니다.
|
||||
|
||||
- 다음 단계
|
||||
- FAIL: `settings` legacy payload 호환성을 실제 구현과 테스트로 복구하거나, 호환 제거를 명시적 breaking change로 재계획한 뒤 다시 리뷰한다.
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=1 tag=REVIEW_API -->
|
||||
|
||||
# Code Review Reference - REVIEW_API
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=1, tag=REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.
|
||||
|
||||
1. `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_N.log` (N = 기존 code_review_*.log 수)
|
||||
2. `PLAN-cloud-G09.md` → `plan_cloud_G09_M.log` (M = 기존 plan_*.log 수)
|
||||
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 routed plan + review 스텁 작성.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_API-1] legacy settings payload 호환성 복구 및 회귀 테스트 추가 | [x] |
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
- 계획서가 제시한 fallback 정책을 그대로 따라 `BuildFromPayload`에서 typed oneof를 우선 사용하고, oneof가 nil일 때만 `settings`로 fallback 하도록 했습니다 (breaking-change 옵션은 채택하지 않음).
|
||||
- 이전 루프에서 삭제했던 `cliConfFromStruct`/`ollamaConfFromStruct`/`vllmConfFromStruct`/`boolFromAny`/`intFromAny`를 `apps/node/internal/adapters/factory.go`에 복원했습니다. 다만 이번 복원본은 `mode`/`resume_args`까지 디코드해 typed 경로와 동일한 필드 셋을 보장합니다(이전 버전엔 없던 필드).
|
||||
- `stringsFromAny` 헬퍼를 추가해 args/env/resume_args의 `[]any → []string` 변환 중복을 제거했습니다.
|
||||
- legacy 회귀 테스트는 `factory_internal_test.go`(같은 패키지)에 추가했습니다. 외부 테스트 패키지에서는 unexported `*FromStruct`에 직접 접근할 수 없어 복원값 자체를 단언하기 어렵기 때문입니다. 등록 여부만 보는 end-to-end 케이스는 `BuildFromPayload`로 검증합니다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- **fallback 분기 위치**: `BuildFromPayload` 안에서 `ac.GetCli()` 등이 nil일 때 `ac.GetSettings()`로 떨어지는 명시적 분기를 사용했습니다. typed conversion 함수 내부에서 fallback을 처리하지 않아, fallback이 일어났는지를 호출 지점에서 바로 식별할 수 있습니다.
|
||||
- **`*FromProto`의 nil 처리 단순화**: 호출자가 nil 체크를 책임지므로 `ollamaConfFromProto`/`vllmConfFromProto`/`cliConfFromProto`는 nil 체크를 하지 않습니다. (단, `cliProfileFromProto`는 map 항목이 nil일 가능성이 있어 보존합니다.)
|
||||
- **`stringsFromAny`는 nil 결과 허용**: 이전 구현과 동일하게 `[]any`가 아니거나 빈 경우 nil을 반환합니다 — `CLIProfileConf.Args`/`Env`/`ResumeArgs`의 zero value와 동일한 의미입니다.
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `apps/node/internal/adapters/factory.go`가 typed config를 우선 사용하면서도 oneof가 nil일 때 `settings` fallback을 실제로 복구했는지
|
||||
- `cli`/`ollama`/`vllm` 모두 legacy payload에서 핵심 값(command/args, base_url, endpoint)을 잃지 않는지
|
||||
- 새 테스트가 단순 등록 여부가 아니라 복원된 설정값 자체를 의미 있게 단언하는지
|
||||
- `검증 결과`의 `go test ./apps/node/internal/adapters/... -count=1` 및 최종 검증 출력이 실제 재실행 결과와 일치하는지
|
||||
|
||||
## 검증 결과
|
||||
|
||||
### REVIEW_API-1 중간 검증
|
||||
```
|
||||
$ go test ./apps/node/internal/adapters/... -count=1
|
||||
ok iop/apps/node/internal/adapters 0.004s
|
||||
ok iop/apps/node/internal/adapters/cli 87.739s
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status 0.002s
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
```
|
||||
|
||||
추가된 회귀 테스트:
|
||||
- `TestOllamaConfFromStruct_LegacyPayload` — `base_url` 복원
|
||||
- `TestVllmConfFromStruct_LegacyPayload` — `endpoint` 복원
|
||||
- `TestCLIConfFromStruct_LegacyPayload` — command/args/env/persistent/idle timeouts/output_format/completion_marker 모두 복원
|
||||
- `TestBuildFromPayload_LegacySettingsFallback` — oneof 비고 settings만 채운 payload에서 ollama/vllm/cli 모두 등록되는지 end-to-end 단언
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ make proto
|
||||
protoc \
|
||||
--go_out=. \
|
||||
--go_opt=module=iop \
|
||||
--proto_path=. \
|
||||
proto/iop/runtime.proto \
|
||||
proto/iop/node.proto \
|
||||
proto/iop/control.proto \
|
||||
proto/iop/job.proto
|
||||
|
||||
$ go build ./...
|
||||
(no output)
|
||||
|
||||
$ go test ./...
|
||||
? iop/apps/control-plane/cmd/control-plane [no test files]
|
||||
ok iop/apps/edge/cmd/edge (cached)
|
||||
? iop/apps/edge/internal/bootstrap [no test files]
|
||||
ok iop/apps/edge/internal/node (cached)
|
||||
ok iop/apps/edge/internal/transport (cached)
|
||||
? iop/apps/node/cmd/node [no test files]
|
||||
ok iop/apps/node/internal/adapters 0.003s
|
||||
ok iop/apps/node/internal/adapters/cli (cached)
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status (cached)
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
ok iop/apps/node/internal/bootstrap 0.160s
|
||||
ok iop/apps/node/internal/node 0.008s
|
||||
ok iop/apps/node/internal/router 0.004s
|
||||
? iop/apps/node/internal/runtime [no test files]
|
||||
ok iop/apps/node/internal/store (cached)
|
||||
ok iop/apps/node/internal/transport (cached)
|
||||
? iop/apps/worker/cmd/worker [no test files]
|
||||
? iop/packages/auth [no test files]
|
||||
ok iop/packages/config (cached)
|
||||
? iop/packages/jobs [no test files]
|
||||
? iop/packages/metadata [no test files]
|
||||
? iop/packages/observability [no test files]
|
||||
? iop/packages/policy [no test files]
|
||||
? iop/packages/version [no test files]
|
||||
? iop/proto/gen/iop [no test files]
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: FAIL
|
||||
|
||||
- 차원별 평가
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Fail
|
||||
|
||||
- 발견된 문제
|
||||
- Required — `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md:51-58`, `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md:82-110`: `검증 결과`가 실제 재실행 stdout과 다시 어긋납니다. 제가 직접 다시 실행한 `go test ./apps/node/internal/adapters/... -count=1` 결과는 `ok iop/apps/node/internal/adapters/cli 87.656s`, `ok iop/apps/node/internal/adapters/cli/status 0.003s`였고, 문서에는 각각 `87.739s`, `0.002s`로 적혀 있습니다. 최종 `make proto && go build ./... && go test ./...` 결과도 문서와 다르게 `ok iop/apps/node/internal/adapters (cached)`, `ok iop/apps/node/internal/adapters/cli 87.671s`, `ok iop/apps/node/internal/bootstrap (cached)`, `ok iop/apps/node/internal/node (cached)`, `ok iop/apps/node/internal/router (cached)`가 출력됐습니다. review 루프 계약상 검증 블록은 실제 실행 출력 그대로여야 하므로, 관련 명령을 다시 실행하고 출력 블록을 실제 stdout으로 교체해야 합니다.
|
||||
|
||||
- 다음 단계
|
||||
- FAIL: `CODE_REVIEW-cloud-G10.md`의 중간/최종 검증 블록을 실제 재실행 출력으로 갱신한 뒤 다시 리뷰한다.
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=2 tag=REVIEW_REVIEW_API -->
|
||||
|
||||
# Code Review Reference - REVIEW_REVIEW_API
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=2, tag=REVIEW_REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.
|
||||
|
||||
1. `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_N.log` (N = 기존 code_review_*.log 수)
|
||||
2. `PLAN-cloud-G09.md` → `plan_cloud_G09_M.log` (M = 기존 plan_*.log 수)
|
||||
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 routed plan + review 스텁 작성.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_REVIEW_API-1] review 문서의 검증 출력 정합성 복구 | [x] |
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
- 코드 변경 없이 `CODE_REVIEW-cloud-G10.md`의 검증 출력 블록만 실제 재실행 stdout으로 교체했습니다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- 명령은 plan에 명시된 순서대로 실행했습니다: ① `go test ./apps/node/internal/adapters/... -count=1`, ② `make proto`, ③ `go build ./...`, ④ `go test ./...`. `go test ./...`은 같은 세션 내 직전 실행이 있어 대부분 `(cached)`로 잡혀, 그대로 반영했습니다.
|
||||
- wall time, `(cached)`, `[no test files]` 마커는 정리하지 않고 stdout 그대로 옮겼습니다.
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `CODE_REVIEW-cloud-G10.md`의 중간 검증 블록이 실제 `go test ./apps/node/internal/adapters/... -count=1` 결과와 정확히 일치하는지
|
||||
- `CODE_REVIEW-cloud-G10.md`의 최종 검증 블록이 실제 `make proto`, `go build ./...`, `go test ./...` 결과와 정확히 일치하는지
|
||||
- `(cached)` 여부, wall time, `[no test files]` 같은 보조 표기까지 실제 stdout 그대로 반영했는지
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
### REVIEW_REVIEW_API-1 중간 검증
|
||||
```
|
||||
$ go test ./apps/node/internal/adapters/... -count=1
|
||||
ok iop/apps/node/internal/adapters 0.004s
|
||||
ok iop/apps/node/internal/adapters/cli 87.771s
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status 0.003s
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ make proto
|
||||
protoc \
|
||||
--go_out=. \
|
||||
--go_opt=module=iop \
|
||||
--proto_path=. \
|
||||
proto/iop/runtime.proto \
|
||||
proto/iop/node.proto \
|
||||
proto/iop/control.proto \
|
||||
proto/iop/job.proto
|
||||
|
||||
$ go build ./...
|
||||
(no output)
|
||||
|
||||
$ go test ./...
|
||||
? iop/apps/control-plane/cmd/control-plane [no test files]
|
||||
ok iop/apps/edge/cmd/edge (cached)
|
||||
? iop/apps/edge/internal/bootstrap [no test files]
|
||||
ok iop/apps/edge/internal/node (cached)
|
||||
ok iop/apps/edge/internal/transport (cached)
|
||||
? iop/apps/node/cmd/node [no test files]
|
||||
ok iop/apps/node/internal/adapters (cached)
|
||||
ok iop/apps/node/internal/adapters/cli (cached)
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status (cached)
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
ok iop/apps/node/internal/bootstrap (cached)
|
||||
ok iop/apps/node/internal/node (cached)
|
||||
ok iop/apps/node/internal/router (cached)
|
||||
? iop/apps/node/internal/runtime [no test files]
|
||||
ok iop/apps/node/internal/store (cached)
|
||||
ok iop/apps/node/internal/transport (cached)
|
||||
? iop/apps/worker/cmd/worker [no test files]
|
||||
? iop/packages/auth [no test files]
|
||||
ok iop/packages/config (cached)
|
||||
? iop/packages/jobs [no test files]
|
||||
? iop/packages/metadata [no test files]
|
||||
? iop/packages/observability [no test files]
|
||||
? iop/packages/policy [no test files]
|
||||
? iop/packages/version [no test files]
|
||||
? iop/proto/gen/iop [no test files]
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: FAIL
|
||||
|
||||
- 차원별 평가
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Fail
|
||||
|
||||
- 발견된 문제
|
||||
- Required — `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md:48-55`: 중간 검증 블록이 실제 재실행 결과와 다시 어긋납니다. 제가 직접 다시 실행한 `go test ./apps/node/internal/adapters/... -count=1` 결과의 `cli` 패키지 라인은 `ok iop/apps/node/internal/adapters/cli 87.656s`였는데, 문서에는 `87.771s`로 기록돼 있습니다. 나머지 줄은 일치했지만 review 루프 계약상 wall time 포함 stdout 전체가 실제 결과와 같아야 하므로, 이 블록은 여전히 신뢰 계약을 만족하지 못합니다.
|
||||
|
||||
- 다음 단계
|
||||
- FAIL: `REVIEW_REVIEW_API-1 중간 검증` 블록을 실제 재실행 stdout으로 다시 교체한 뒤 재리뷰한다.
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=3 tag=REVIEW_REVIEW_REVIEW_API -->
|
||||
|
||||
# Code Review Reference - REVIEW_REVIEW_REVIEW_API
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=3, tag=REVIEW_REVIEW_REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.
|
||||
|
||||
1. `CODE_REVIEW-cloud-G10.md` → `code_review_cloud_G10_N.log` (N = 기존 code_review_*.log 수)
|
||||
2. `PLAN-cloud-G09.md` → `plan_cloud_G09_M.log` (M = 기존 plan_*.log 수)
|
||||
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 routed plan + review 스텁 작성.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [REVIEW_REVIEW_REVIEW_API-1] 비결정적 wall time 제거 | [x] |
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
- 코드 변경 없음. plan에서 권장한 안정화 명령(`go test ... | perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'`)을 그대로 채택해 검증 블록의 wall time을 `<elapsed>`로 치환했습니다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- **검증 명령 안정화 이유**: `go test`의 elapsed time은 매 실행마다 달라 review 단계에서 같은 명령을 다시 돌리면 검증 블록이 어긋납니다. `perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'`로 elapsed 숫자만 토큰 치환하면 (cached) 여부·`[no test files]` 등 다른 표기는 유지하면서 stdout이 결정적이 됩니다.
|
||||
- `make proto`와 `go build ./...`는 elapsed time이 stdout에 없어 안정화 파이프 없이도 결정적입니다 — plan대로 그대로 둡니다.
|
||||
- `go test ./...`은 plan에 `-count=1`이 명시되지 않아 cache hit이 발생합니다. (cached) 마커는 elapsed가 없어 perl 치환 대상이 아니며, review 단계 재실행 시에도 동일한 (cached) 라인을 그대로 비교할 수 있습니다.
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- 중간 검증 명령이 `go test ... | perl -pe ...` 형태로 안정화되었는지
|
||||
- 최종 검증의 `go test ./...`도 같은 방식으로 wall time이 제거되었는지
|
||||
- 검증 블록의 `<elapsed>` 치환 결과가 실제 재실행 출력과 정확히 일치하는지
|
||||
- 구현 설명에 왜 원본 `go test` 대신 안정화 명령을 쓰는지 근거가 남아 있는지
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
### REVIEW_REVIEW_REVIEW_API-1 중간 검증
|
||||
```
|
||||
$ go test ./apps/node/internal/adapters/... -count=1 | perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'
|
||||
ok iop/apps/node/internal/adapters <elapsed>
|
||||
ok iop/apps/node/internal/adapters/cli <elapsed>
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status <elapsed>
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ make proto
|
||||
protoc \
|
||||
--go_out=. \
|
||||
--go_opt=module=iop \
|
||||
--proto_path=. \
|
||||
proto/iop/runtime.proto \
|
||||
proto/iop/node.proto \
|
||||
proto/iop/control.proto \
|
||||
proto/iop/job.proto
|
||||
|
||||
$ go build ./...
|
||||
(no output)
|
||||
|
||||
$ go test ./... | perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'
|
||||
? iop/apps/control-plane/cmd/control-plane [no test files]
|
||||
ok iop/apps/edge/cmd/edge (cached)
|
||||
? iop/apps/edge/internal/bootstrap [no test files]
|
||||
ok iop/apps/edge/internal/node (cached)
|
||||
ok iop/apps/edge/internal/transport (cached)
|
||||
? iop/apps/node/cmd/node [no test files]
|
||||
ok iop/apps/node/internal/adapters (cached)
|
||||
ok iop/apps/node/internal/adapters/cli (cached)
|
||||
? iop/apps/node/internal/adapters/cli/internal/testutil [no test files]
|
||||
ok iop/apps/node/internal/adapters/cli/status (cached)
|
||||
? iop/apps/node/internal/adapters/mock [no test files]
|
||||
? iop/apps/node/internal/adapters/ollama [no test files]
|
||||
? iop/apps/node/internal/adapters/vllm [no test files]
|
||||
ok iop/apps/node/internal/bootstrap (cached)
|
||||
ok iop/apps/node/internal/node (cached)
|
||||
ok iop/apps/node/internal/router (cached)
|
||||
? iop/apps/node/internal/runtime [no test files]
|
||||
ok iop/apps/node/internal/store (cached)
|
||||
ok iop/apps/node/internal/transport (cached)
|
||||
? iop/apps/worker/cmd/worker [no test files]
|
||||
? iop/packages/auth [no test files]
|
||||
ok iop/packages/config (cached)
|
||||
? iop/packages/jobs [no test files]
|
||||
? iop/packages/metadata [no test files]
|
||||
? iop/packages/observability [no test files]
|
||||
? iop/packages/policy [no test files]
|
||||
? iop/packages/version [no test files]
|
||||
? iop/proto/gen/iop [no test files]
|
||||
```
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: PASS
|
||||
|
||||
- 차원별 평가
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Pass
|
||||
|
||||
- 발견된 문제
|
||||
- 없음
|
||||
|
||||
- 다음 단계
|
||||
- PASS: 아카이브 후 `complete.log`를 작성하고 종료한다.
|
||||
18
agent-task/07_cli_profile_proto_message/complete.log
Normal file
18
agent-task/07_cli_profile_proto_message/complete.log
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
완료 일시: 2026-05-04
|
||||
|
||||
요약: `07_cli_profile_proto_message` 작업을 4회 plan/review 루프 끝에 완료했다.
|
||||
|
||||
루프 이력:
|
||||
|
||||
| plan log | code review log | verdict |
|
||||
|----------|------------------|---------|
|
||||
| `plan_cloud_G09_0.log` | `code_review_cloud_G10_0.log` | FAIL |
|
||||
| `plan_cloud_G09_1.log` | `code_review_cloud_G10_1.log` | FAIL |
|
||||
| `plan_cloud_G09_2.log` | `code_review_cloud_G10_2.log` | FAIL |
|
||||
| `plan_cloud_G09_3.log` | `code_review_cloud_G10_3.log` | PASS |
|
||||
|
||||
최종 리뷰 요약:
|
||||
|
||||
- `AdapterConfig.settings` legacy payload 호환성이 node `BuildFromPayload` 경로에서 복구되었고, typed oneof 우선 + legacy fallback 순서가 유지됐다.
|
||||
- legacy `settings` 입력에 대한 `ollama`/`vllm`/`cli` 회귀 테스트가 추가되어 핵심 설정 복원이 검증됐다.
|
||||
- review 문서의 검증 명령은 `go test` elapsed time 비결정성을 제거하도록 안정화되어, 재실행해도 동일한 출력으로 비교 가능해졌다.
|
||||
181
agent-task/07_cli_profile_proto_message/plan_cloud_G09_0.log
Normal file
181
agent-task/07_cli_profile_proto_message/plan_cloud_G09_0.log
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=0 tag=API -->
|
||||
|
||||
# CLI 프로파일 전용 proto 메시지 도입
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
아래 체크리스트를 순서대로 완료하고, 각 항목의 중간 검증과 최종 검증을 실제로 실행하세요. 구현이 끝나면 `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md`의 모든 섹션을 실제 구현 내용과 명령 출력으로 채우세요. `CODE_REVIEW-cloud-G10.md`의 `이 파일을 읽는 리뷰 에이전트에게` 섹션에 있는 아카이브 지시(`*.log`로 이름 변경, `complete.log` 작성)는 구현 에이전트가 수행하면 안 되며, 리뷰 스킬 전용입니다.
|
||||
|
||||
## 배경
|
||||
|
||||
edge가 node에 보내는 `NodeConfigPayload`에서 CLI 프로파일은 `AdapterConfig.settings` (`google.protobuf.Struct`)로 직렬화되고, node 쪽에서 손으로 디코드합니다. (`apps/edge/internal/transport/server.go:190-207`의 `buildConfigPayload`와 `apps/node/internal/adapters/factory.go:69-118`의 `cliConfFromStruct`) 프로파일에 새 필드를 추가하면 edge·node 양쪽을 손으로 맞춰야 하며, structpb 인코딩 특성상 정수가 float로 들어가는 등의 변환 코드가 필요합니다. domain rule(`agent-ops/rules/project/rules.md`의 "protobuf 계약 변경은 .proto부터")을 따라 CLI 프로파일 전용 proto 메시지를 정의하고, edge·node 양쪽에서 구조체 단위로 주고받게 합니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
1. `[API-1]` `proto/iop/runtime.proto`에 `CLIAdapterConfig` / `CLIProfileConfig` 메시지를 추가하고 `make proto`로 생성물 갱신.
|
||||
2. `[API-2]` edge `buildConfigPayload`가 새 메시지로 직접 채우도록 변경.
|
||||
3. `[API-3]` node `BuildFromPayload`가 structpb 디코드 대신 새 메시지를 그대로 사용.
|
||||
|
||||
### [API-1] proto 메시지 정의 및 생성물 갱신
|
||||
|
||||
#### 문제
|
||||
|
||||
`proto/iop/runtime.proto:96-100`의 `AdapterConfig`는 `google.protobuf.Struct settings`로 모든 어댑터 타입의 설정을 우회 직렬화합니다. CLI 프로파일은 필드가 9개로 늘어나 string-keyed map 직렬화의 위험이 큽니다.
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
`proto/iop/runtime.proto`의 `AdapterConfig`에 `oneof config`를 도입해 어댑터 타입별 typed 메시지를 가질 수 있도록 합니다. CLI 전용 메시지는 다음과 같이 정의합니다.
|
||||
|
||||
```proto
|
||||
message AdapterConfig {
|
||||
string type = 1;
|
||||
bool enabled = 2;
|
||||
google.protobuf.Struct settings = 3; // 구버전 호환용; 신규 어댑터는 oneof 사용 권장
|
||||
oneof config {
|
||||
CLIAdapterConfig cli = 4;
|
||||
OllamaAdapterConfig ollama = 5;
|
||||
VllmAdapterConfig vllm = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message CLIAdapterConfig {
|
||||
map<string, CLIProfileConfig> profiles = 1;
|
||||
}
|
||||
|
||||
message CLIProfileConfig {
|
||||
string command = 1;
|
||||
repeated string args = 2;
|
||||
repeated string env = 3;
|
||||
bool persistent = 4;
|
||||
bool terminal = 5;
|
||||
int32 response_idle_timeout_ms = 6;
|
||||
int32 startup_idle_timeout_ms = 7;
|
||||
string output_format = 8;
|
||||
}
|
||||
|
||||
message OllamaAdapterConfig { string base_url = 1; }
|
||||
message VllmAdapterConfig { string endpoint = 1; }
|
||||
```
|
||||
|
||||
오래된 `settings` 필드는 일단 유지해 mock/기타 어댑터 호환을 깨지 않습니다. CLI/Ollama/Vllm은 신규 oneof 경로만 사용하도록 합니다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `proto/iop/runtime.proto`에 `CLIAdapterConfig`, `CLIProfileConfig`, `OllamaAdapterConfig`, `VllmAdapterConfig` 메시지를 추가한다.
|
||||
- [ ] `AdapterConfig`에 `oneof config { ... }`를 추가한다 (`settings` 필드는 그대로 둔다).
|
||||
- [ ] `make proto`를 실행해 `proto/gen/iop/runtime.pb.go`를 갱신한다.
|
||||
- [ ] 생성 파일은 직접 수정하지 않는다.
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
테스트는 `[API-2]`/`[API-3]`에서 통합 검증한다. proto 정의 단독으로는 별도 단위 테스트를 작성하지 않는다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
make proto
|
||||
git diff proto/iop/runtime.proto
|
||||
go build ./proto/gen/...
|
||||
```
|
||||
|
||||
예상 결과: `runtime.proto`에 새 메시지/oneof가 추가되어 있고, 생성물이 빌드된다.
|
||||
|
||||
### [API-2] edge `buildConfigPayload`를 typed 메시지로 갱신
|
||||
|
||||
#### 문제
|
||||
|
||||
`apps/edge/internal/transport/server.go:155-209`의 `buildConfigPayload`가 `structpb.NewStruct(map[string]any{...})`로 CLI/Ollama/Vllm 설정을 우회 직렬화합니다. `stringsToAny` 같은 보조 함수도 필요합니다.
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
CLI/Ollama/Vllm은 `oneof config`로 직접 채우고, mock만 기존 `settings` 경로를 유지합니다.
|
||||
|
||||
```go
|
||||
if rec.Adapters.CLI.Enabled {
|
||||
profiles := make(map[string]*iop.CLIProfileConfig, len(rec.Adapters.CLI.Profiles))
|
||||
for name, p := range rec.Adapters.CLI.Profiles {
|
||||
profiles[name] = &iop.CLIProfileConfig{
|
||||
Command: p.Command,
|
||||
Args: append([]string(nil), p.Args...),
|
||||
Env: append([]string(nil), p.Env...),
|
||||
Persistent: p.Persistent,
|
||||
Terminal: p.Terminal,
|
||||
ResponseIdleTimeoutMs: int32(p.ResponseIdleTimeoutMS),
|
||||
StartupIdleTimeoutMs: int32(p.StartupIdleTimeoutMS),
|
||||
OutputFormat: p.OutputFormat,
|
||||
}
|
||||
}
|
||||
payload.Adapters = append(payload.Adapters, &iop.AdapterConfig{
|
||||
Type: "cli", Enabled: true,
|
||||
Config: &iop.AdapterConfig_Cli{Cli: &iop.CLIAdapterConfig{Profiles: profiles}},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `apps/edge/internal/transport/server.go`의 `buildConfigPayload`에서 cli/ollama/vllm 분기를 oneof 기반으로 다시 쓴다.
|
||||
- [ ] `stringsToAny` 헬퍼는 더 이상 사용되지 않으면 제거한다.
|
||||
- [ ] mock 어댑터 분기는 그대로 둔다.
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`apps/edge/internal/transport/server_test.go`에 `TestBuildConfigPayload_CLIOneof` (가칭)를 추가해 CLI 프로파일 한 개 정의에서 oneof 경로가 채워지고, settings 필드는 비어 있는지 단언한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
go test ./apps/edge/internal/transport/...
|
||||
```
|
||||
|
||||
예상 결과: 신규 테스트 포함 PASS.
|
||||
|
||||
### [API-3] node `BuildFromPayload`를 typed 메시지 기반으로 갱신
|
||||
|
||||
#### 문제
|
||||
|
||||
`apps/node/internal/adapters/factory.go:69-118`의 `cliConfFromStruct`가 structpb를 손으로 디코드하면서 `boolFromAny`, `intFromAny` 같은 헬퍼에 의존합니다. structpb의 number→float64 변환 등 함정이 많습니다.
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
`AdapterConfig.GetCli()`가 nil이 아니면 typed 메시지 그대로 `config.CLIConf`로 매핑하고, structpb 경로(`cliConfFromStruct`)는 제거합니다. Ollama/Vllm도 동일하게 변경.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `apps/node/internal/adapters/factory.go`의 `cli/ollama/vllm` 분기를 oneof 기반으로 재작성한다.
|
||||
- [ ] `cliConfFromStruct`, `ollamaConfFromStruct`, `vllmConfFromStruct`, `boolFromAny`, `intFromAny`를 모두 제거한다.
|
||||
- [ ] `apps/node/internal/adapters/factory_internal_test.go`와 `factory_test.go`의 케이스를 typed 메시지 입력 기반으로 갱신한다.
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`factory_test.go`의 기존 시나리오(여러 어댑터 enabled, CLI 프로파일 매핑)를 oneof 입력으로 다시 작성한다. 신규 케이스: `Persistent`, `ResponseIdleTimeoutMS`, `StartupIdleTimeoutMS`가 정확히 0이 아닌 값으로 전달되는지 단언.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
go test ./apps/node/internal/adapters/...
|
||||
```
|
||||
|
||||
예상 결과: PASS.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `proto/iop/runtime.proto` | API-1 |
|
||||
| `proto/gen/iop/runtime.pb.go` (생성물) | API-1 |
|
||||
| `apps/edge/internal/transport/server.go` | API-2 |
|
||||
| `apps/edge/internal/transport/server_test.go` | API-2 |
|
||||
| `apps/node/internal/adapters/factory.go` | API-3 |
|
||||
| `apps/node/internal/adapters/factory_internal_test.go` | API-3 |
|
||||
| `apps/node/internal/adapters/factory_test.go` | API-3 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
make proto
|
||||
go build ./...
|
||||
go test ./...
|
||||
```
|
||||
|
||||
예상 결과: build/test 모두 PASS, 새 oneof 경로로 edge↔node가 동작.
|
||||
70
agent-task/07_cli_profile_proto_message/plan_cloud_G09_1.log
Normal file
70
agent-task/07_cli_profile_proto_message/plan_cloud_G09_1.log
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=1 tag=REVIEW_API -->
|
||||
|
||||
# Plan - REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
아래 체크리스트를 순서대로 완료하고, 각 항목의 중간 검증과 최종 검증을 실제로 실행하세요. 구현이 끝나면 `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md`의 모든 섹션을 실제 구현 내용과 명령 출력으로 채우세요. `CODE_REVIEW-cloud-G10.md`의 `이 파일을 읽는 리뷰 에이전트에게` 섹션에 있는 아카이브 지시(`*.log`로 이름 변경, `complete.log` 작성)는 구현 에이전트가 수행하면 안 되며, 리뷰 스킬 전용입니다.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=1, tag=REVIEW_API
|
||||
parent=API (code_review_cloud_G10_0.log)
|
||||
|
||||
## 배경
|
||||
|
||||
이번 루프에서 `AdapterConfig.settings`를 `legacy/compat path`로 유지한다고 명시했지만, node 쪽 `BuildFromPayload`는 새 oneof만 읽고 기존 `settings` 역직렬화 경로를 완전히 제거했습니다. 그 결과 구버전 edge나 oneof 미사용 payload가 들어오면 `ollama`/`vllm`은 빈 endpoint로, `cli`는 빈 profiles로 등록되어 호환성 계약이 실제로 깨집니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
1. `REVIEW_API-1`에서 node 역직렬화에 legacy fallback 정책을 복구하거나, 호환 제거를 명시적 breaking change로 정리한다.
|
||||
2. 같은 항목에서 legacy payload 회귀 테스트를 추가해 `settings` 전용 입력도 원하는 동작을 보장한다.
|
||||
3. 구현 후 `CODE_REVIEW` 문서의 변경 사항/설계 결정/검증 결과를 실제 상태로 갱신한다.
|
||||
|
||||
## [REVIEW_API-1] legacy settings payload 호환성 복구
|
||||
|
||||
### 문제
|
||||
|
||||
- `proto/iop/runtime.proto`는 `settings = 3`를 `legacy/compat path`로 남겨 두었음
|
||||
- 하지만 `apps/node/internal/adapters/factory.go`는 `GetCli()`/`GetOllama()`/`GetVllm()`만 사용해, oneof가 비어 있고 `settings`만 있는 payload를 더 이상 읽지 못함
|
||||
- 현재 테스트는 typed payload만 검증하므로 이 회귀를 잡지 못함
|
||||
|
||||
### 해결 방법
|
||||
|
||||
우선순위는 실제 호환성 복구입니다. `BuildFromPayload`에서 typed config가 있으면 그것을 우선 사용하되, 없고 `settings`가 있으면 기존 struct 기반 디코드로 fallback 하도록 복원합니다. `cli`/`ollama`/`vllm` 모두 동일 원칙을 적용합니다.
|
||||
|
||||
만약 이번 작업에서 호환 제거가 의도라면, 그 결정은 proto 주석, plan/review 문서, 배포 계약에 모두 breaking change로 명시되어야 하며, 구버전 혼합 배포를 금지하는 근거와 검증도 함께 남겨야 합니다. 다만 현재 문서/주석은 호환 유지 쪽을 가리키므로 기본 해법은 fallback 복구입니다.
|
||||
|
||||
### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `apps/node/internal/adapters/factory.go`에서 oneof가 nil일 때 `settings` legacy 경로로 fallback 하도록 복구
|
||||
- [ ] `cli`/`ollama`/`vllm` 모두 typed 우선, legacy fallback 순서를 일관되게 적용
|
||||
- [ ] `apps/node/internal/adapters/factory_test.go` 또는 `factory_internal_test.go`에 legacy payload 회귀 테스트 추가
|
||||
- [ ] 새 테스트가 endpoint/base_url/profiles 같은 핵심 값이 실제로 복원되는지 단언
|
||||
- [ ] `CODE_REVIEW-cloud-G10.md`의 `계획 대비 변경 사항`, `주요 설계 결정`, `검증 결과`를 실제 구현/출력에 맞게 갱신
|
||||
|
||||
### 테스트 작성
|
||||
|
||||
최소 1개 이상의 legacy payload 회귀 테스트가 필요합니다.
|
||||
|
||||
- `ollama` 또는 `vllm`: `settings`만 채운 payload에서 URL/endpoint가 복원되는지 검증
|
||||
- `cli`: `settings.profiles`만 채운 payload에서 command/args 또는 completion_marker가 복원되는지 검증
|
||||
|
||||
### 중간 검증
|
||||
|
||||
```bash
|
||||
go test ./apps/node/internal/adapters/... -count=1
|
||||
```
|
||||
|
||||
기대 결과: typed 경로와 legacy fallback 경로를 모두 포함한 테스트가 PASS한다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
make proto
|
||||
go build ./...
|
||||
go test ./...
|
||||
```
|
||||
|
||||
기대 결과: 전체 빌드/테스트가 PASS하고, review 문서의 검증 출력이 실제 결과와 일치한다.
|
||||
65
agent-task/07_cli_profile_proto_message/plan_cloud_G09_2.log
Normal file
65
agent-task/07_cli_profile_proto_message/plan_cloud_G09_2.log
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=2 tag=REVIEW_REVIEW_API -->
|
||||
|
||||
# Plan - REVIEW_REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
아래 체크리스트를 순서대로 완료하고, 각 항목의 중간 검증과 최종 검증을 실제로 실행하세요. 구현이 끝나면 `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md`의 모든 섹션을 실제 구현 내용과 명령 출력으로 채우세요. `CODE_REVIEW-cloud-G10.md`의 `이 파일을 읽는 리뷰 에이전트에게` 섹션에 있는 아카이브 지시(`*.log`로 이름 변경, `complete.log` 작성)는 구현 에이전트가 수행하면 안 되며, 리뷰 스킬 전용입니다.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=2, tag=REVIEW_REVIEW_API
|
||||
parent=REVIEW_API (code_review_cloud_G10_1.log)
|
||||
|
||||
## 배경
|
||||
|
||||
코드 자체의 legacy fallback 복구와 회귀 테스트는 충족됐지만, `CODE_REVIEW` 문서의 `검증 결과` 블록이 다시 실제 재실행 stdout과 어긋났습니다. 이번 루프의 목적은 구현 변경이 아니라 review 문서의 검증 출력 신뢰성을 맞추는 것입니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
1. `REVIEW_REVIEW_API-1`에서 중간 검증 명령을 다시 실행한다.
|
||||
2. 같은 항목에서 최종 검증 명령을 다시 실행한다.
|
||||
3. `CODE_REVIEW`의 대응 출력 블록을 실제 stdout 그대로 교체한다.
|
||||
|
||||
## [REVIEW_REVIEW_API-1] review 문서의 검증 출력 정합성 복구
|
||||
|
||||
### 문제
|
||||
|
||||
- `go test ./apps/node/internal/adapters/... -count=1` 블록의 wall time이 실제 결과와 다름
|
||||
- 최종 `go test ./...` 블록에서 `cached` 여부와 wall time이 실제 결과와 다름
|
||||
- review 루프 계약상 검증 블록은 실제 실행 출력 그대로여야 함
|
||||
|
||||
### 해결 방법
|
||||
|
||||
아래 명령을 다시 실행하고 `CODE_REVIEW-cloud-G10.md`의 해당 코드 블록을 실제 stdout 그대로 덮어씁니다. 줄 순서, `(cached)`, `[no test files]`, wall time 값까지 임의로 정리하지 말고 그대로 반영합니다.
|
||||
|
||||
1. `go test ./apps/node/internal/adapters/... -count=1`
|
||||
2. `make proto`
|
||||
3. `go build ./...`
|
||||
4. `go test ./...`
|
||||
|
||||
### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `CODE_REVIEW-cloud-G10.md`의 `REVIEW_API-1 중간 검증` 블록을 실제 출력으로 교체
|
||||
- [ ] `CODE_REVIEW-cloud-G10.md`의 `최종 검증` 블록을 실제 출력으로 교체
|
||||
- [ ] `(cached)`/wall time/`[no test files]` 표기가 실제 재실행 결과와 정확히 일치하는지 확인
|
||||
- [ ] 그 외 설명 문장은 유지하되, 출력 블록과 충돌하는 서술이 없는지 확인
|
||||
|
||||
### 중간 검증
|
||||
|
||||
```bash
|
||||
go test ./apps/node/internal/adapters/... -count=1
|
||||
```
|
||||
|
||||
기대 결과: 출력 전문이 `CODE_REVIEW` 중간 검증 블록과 정확히 일치한다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
make proto
|
||||
go build ./...
|
||||
go test ./...
|
||||
```
|
||||
|
||||
기대 결과: 출력 전문이 `CODE_REVIEW` 최종 검증 블록과 정확히 일치한다.
|
||||
66
agent-task/07_cli_profile_proto_message/plan_cloud_G09_3.log
Normal file
66
agent-task/07_cli_profile_proto_message/plan_cloud_G09_3.log
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<!-- task=07_cli_profile_proto_message plan=3 tag=REVIEW_REVIEW_REVIEW_API -->
|
||||
|
||||
# Plan - REVIEW_REVIEW_REVIEW_API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
아래 체크리스트를 순서대로 완료하고, 각 항목의 중간 검증과 최종 검증을 실제로 실행하세요. 구현이 끝나면 `agent-task/07_cli_profile_proto_message/CODE_REVIEW-cloud-G10.md`의 모든 섹션을 실제 구현 내용과 명령 출력으로 채우세요. `CODE_REVIEW-cloud-G10.md`의 `이 파일을 읽는 리뷰 에이전트에게` 섹션에 있는 아카이브 지시(`*.log`로 이름 변경, `complete.log` 작성)는 구현 에이전트가 수행하면 안 되며, 리뷰 스킬 전용입니다.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-05-04
|
||||
task=07_cli_profile_proto_message, plan=3, tag=REVIEW_REVIEW_REVIEW_API
|
||||
parent=REVIEW_REVIEW_API (code_review_cloud_G10_2.log)
|
||||
|
||||
## 배경
|
||||
|
||||
이제 남은 이슈는 문서 검증 출력의 wall time 불안정성입니다. `go test`의 elapsed time은 재실행마다 달라져 review 단계에서 같은 명령을 다시 돌리면 출력이 쉽게 어긋납니다. 이번 루프는 코드 변경 없이, 검증 명령을 stable output 형태로 바꿔 review 문서의 재현성을 확보하는 데 목적이 있습니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
1. `REVIEW_REVIEW_REVIEW_API-1`에서 중간 검증 명령을 안정화된 형태로 다시 정의하고 실행한다.
|
||||
2. 같은 항목에서 최종 검증의 `go test ./...`도 안정화된 형태로 다시 정의하고 실행한다.
|
||||
3. `CODE_REVIEW` 문서의 검증 블록과 설명을 새 명령 기준으로 갱신한다.
|
||||
|
||||
## [REVIEW_REVIEW_REVIEW_API-1] 비결정적 wall time 제거
|
||||
|
||||
### 문제
|
||||
|
||||
- `go test` stdout의 wall time(`87.656s` 같은 값)이 매 실행마다 달라져 검증 블록이 반복적으로 어긋남
|
||||
- 현재 review 계약은 "실제 실행 출력 그대로"를 요구하므로, 비결정적 숫자를 포함한 원본 stdout은 반복 리뷰에 부적합함
|
||||
|
||||
### 해결 방법
|
||||
|
||||
검증 명령 자체를 stable output으로 바꿉니다. `go test` 출력에서 elapsed time만 정규식으로 치환한 뒤 그 결과를 review 문서에 기록합니다. review 단계에서도 같은 안정화 명령을 재실행해 동일 출력을 비교할 수 있게 합니다.
|
||||
|
||||
권장 명령:
|
||||
|
||||
1. `go test ./apps/node/internal/adapters/... -count=1 | perl -pe 's/\\b\\d+\\.\\d+s\\b/<elapsed>/g'`
|
||||
2. `make proto`
|
||||
3. `go build ./...`
|
||||
4. `go test ./... | perl -pe 's/\\b\\d+\\.\\d+s\\b/<elapsed>/g'`
|
||||
|
||||
### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `CODE_REVIEW-cloud-G10.md`의 중간 검증 명령을 안정화된 `go test ... | perl ...` 형태로 교체
|
||||
- [ ] `CODE_REVIEW-cloud-G10.md`의 최종 검증 명령도 안정화된 `go test ./... | perl ...` 형태로 교체
|
||||
- [ ] 기존 wall time 숫자 대신 `<elapsed>` 치환 결과가 실제 실행 출력과 일치하는지 확인
|
||||
- [ ] `계획 대비 변경 사항` 또는 `주요 설계 결정`에 "검증 명령 안정화" 이유를 명시
|
||||
|
||||
### 중간 검증
|
||||
|
||||
```bash
|
||||
go test ./apps/node/internal/adapters/... -count=1 | perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'
|
||||
```
|
||||
|
||||
기대 결과: `ok ... <elapsed>`처럼 wall time이 치환된 안정적 출력이 생성되고, `CODE_REVIEW` 중간 검증 블록과 정확히 일치한다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
make proto
|
||||
go build ./...
|
||||
go test ./... | perl -pe 's/\b\d+\.\d+s\b/<elapsed>/g'
|
||||
```
|
||||
|
||||
기대 결과: 최종 검증 블록이 실제 재실행 결과와 안정적으로 일치한다.
|
||||
Loading…
Reference in a new issue