# Code Review Reference - REVIEW_REVIEW_API_FOLLOWUP_2 ## 개요 date=2026-05-03 task=cli_terminal_cycle, plan=4, tag=REVIEW_REVIEW_API_FOLLOWUP_2 ## 이 파일을 읽는 리뷰 에이전트에게 각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요. 리뷰 완료 후 반드시 아래 순서로 아카이브하세요. 1. `CODE_REVIEW.md` → `code_review_N.log` (N = 기존 code_review_*.log 수) 2. `PLAN.md` → `plan_M.log` (M = 기존 plan_*.log 수) 3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 `PLAN.md` + `CODE_REVIEW.md` 스텁 작성. --- ## 구현 항목별 완료 여부 | 항목 | 완료 여부 | |------|---------| | [REVIEW_REVIEW_API_FOLLOWUP_2-1] Persistent Execute 모든 반환 경로에서 session mutex 해제 | [x] | | [REVIEW_REVIEW_API_FOLLOWUP_2-2] Timeout/cancel cleanup 범위와 sessions map locking 정리 | [x] | | [REVIEW_REVIEW_API_FOLLOWUP_2-3] Partial rollback 테스트와 formatting 정리 | [x] | ## 계획 대비 변경 사항 _구현 에이전트가 계획과 다르게 구현한 부분과 이유를 기록한다._ ## 주요 설계 결정 _구현 에이전트가 핵심 설계 결정을 기록한다._ ## 리뷰어를 위한 체크포인트 - persistent profile 정상 complete 후 같은 profile을 다시 실행해도 block 없이 응답하는지 확인한다. → `TestCLIExecutePersistentConsecutiveExecutes` 통과 - timeout/cancel 경로에서 session mutex가 잠긴 채 남지 않는지 확인한다. → `defer sess.mu.Unlock()` 적용 - `c.sessions` map 접근이 `Start`/`Stop`/`Execute`/timeout cleanup에서 일관되게 보호되는지 확인한다. → `Execute` 내 `c.sessions` 접근에 `c.mu` 적용 - 한 profile timeout이 다른 profile session을 의도치 않게 종료하지 않는지 확인한다. → timeout 시 해당 profile session만 delete/kill - partial rollback 테스트가 실제 started process cleanup marker를 검증하는지 확인한다. → `TestCLIStartPartialRollbackChecksMarker` 통과 - 변경 파일이 `gofmt` 상태인지 확인한다. → `gofmt -w` 적용 완료 ## 검증 결과 ### 중간 검증 #### [REVIEW_REVIEW_API_FOLLOWUP_2-1] executePersistent mutex unlock `sess.mu.Lock()` 직후 `defer sess.mu.Unlock()`을 추가하여 모든 반환 경로에서 session mutex가 자동으로 해제되도록 수정했다. 기존 명시적 `sess.mu.Unlock()`은 제거했다. #### [REVIEW_REVIEW_API_FOLLOWUP_2-2] sessions map locking 및 timeout cleanup 범위 - `Execute` 내 `c.sessions` lookup을 `c.mu.Lock()`/`c.mu.Unlock()`으로 감쌌다. - timeout/cancel 경로에서 `c.Stop(context.Background())` 대신 해당 profile session만 close/kill/delete하도록 변경했다. ### 최종 검증 결과 ```bash $ gofmt -w apps/node/internal/adapters/cli/cli.go apps/node/internal/adapters/cli/cli_test.go apps/node/internal/adapters/registry.go apps/node/internal/adapters/registry_test.go # formatting errors 없음 (모든 파일 gofmt 상태) $ go test ./apps/node/internal/adapters ./apps/node/internal/adapters/cli -v -count=1 === RUN TestCLIConfFromStruct_ProfileRuntimeOptions --- PASS: TestCLIConfFromStruct_ProfileRuntimeOptions (0.00s) === RUN TestCLIConfFromStruct_NilSettings --- PASS: TestCLIConfFromStruct_NilSettings (0.00s) === RUN TestBuildFromPayload_MockAlwaysPresent --- PASS: TestBuildFromPayload_MockAlwaysPresent (0.00s) === RUN TestBuildFromPayload_OllamaEnabled --- PASS: TestBuildFromPayload_OllamaEnabled (0.00s) === RUN TestBuildFromPayload_UnknownType --- PASS: TestBuildFromPayload_UnknownType (0.00s) === RUN TestRegistryLifecycle_StartStopOrder --- PASS: TestRegistryLifecycle_StartStopOrder (0.00s) === RUN TestRegistryLifecycle_StartFailureStopsStartedAdapters --- PASS: TestRegistryLifecycle_StartFailureStopsStartedAdapters (0.00s) === RUN TestRegistryLifecycle_StopContinuesOnFailingAdapter --- PASS: TestRegistryLifecycle_StopContinuesOnFailingAdapter (0.00s) === RUN TestRegistryLifecycle_NonLifecycleAdapterSkipped --- PASS: TestRegistryLifecycle_NonLifecycleAdapterSkipped (0.00s) PASS ok iop/apps/node/internal/adapters 0.007s === RUN TestCLIExecuteOneShotPassesPromptAsArg --- PASS: TestCLIExecuteOneShotPassesPromptAsArg (0.00s) === RUN TestCLIExecutePersistentWaitsForSlowFirstOutput --- PASS: TestCLIExecutePersistentWaitsForSlowFirstOutput (0.31s) === RUN TestCLIExecutePersistentProcessExitReturnsError --- PASS: TestCLIExecutePersistentProcessExitReturnsError (0.05s) === RUN TestCLIStartPersistentReturnsErrorWhenProcessExitsDuringStartup --- PASS: TestCLIStartPersistentReturnsErrorWhenProcessExitsDuringStartup (0.00s) === RUN TestCLIStartCleansUpStartedProfilesWhenLaterProfileFails --- PASS: TestCLIStartCleansUpStartedProfilesWhenLaterProfileFails (0.06s) === RUN TestCLIStartPersistentTerminalAndExecuteWritesPrompt --- PASS: TestCLIStartPersistentTerminalAndExecuteWritesPrompt (0.36s) === RUN TestCLIExecutePersistentTimeoutCleansSession --- PASS: TestCLIExecutePersistentTimeoutCleansSession (0.56s) === RUN TestCLIExecutePersistentConsecutiveExecutes --- PASS: TestCLIExecutePersistentConsecutiveExecutes (0.27s) === RUN TestCLIStartPartialRollbackChecksMarker --- PASS: TestCLIStartPartialRollbackChecksMarker (0.00s) PASS ok iop/apps/node/internal/adapters/cli 1.615s $ go test ./apps/node/internal/bootstrap ./apps/node/... -count=1 ok iop/apps/node/internal/bootstrap 0.164s ? iop/apps/node/cmd/node [no test files] ok iop/apps/node/internal/adapters 0.003s ok iop/apps/node/internal/adapters/cli 1.640s ? 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/node 0.010s ? iop/apps/node/internal/router [no test files] ? iop/apps/node/internal/runtime [no test files] ? iop/apps/node/internal/store [no test files] ok iop/apps/node/internal/transport 0.006s ``` ### 계획 대비 변경 사항 - 없음. PLAN.md의 지시사항대로 구현 진행.