iop/agent-task/cli_terminal_cycle/CODE_REVIEW.md
toki 4bece3fb2d fix(cli): mutex unlock and session cleanup for persistent Execute (REVIEW_REVIEW_API_FOLLOWUP_2)
- [2-1] executePersistent: add defer sess.mu.Unlock() so all return paths
  release the session mutex. Remove explicit unlock calls.
- [2-2] Protect c.sessions map access in Execute with c.mu. Replace
  c.Stop() in timeout/cancel path with per-session close/kill/delete so
  only the affected profile session is cleaned up.
- [2-3] Add TestCLIExecutePersistentConsecutiveExecutes to verify the
  same persistent profile can be executed consecutively without blocking.
  Apply gofmt to all adapter files.
2026-05-03 15:01:57 +09:00

6.1 KiB

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.mdcode_review_N.log (N = 기존 code_review_*.log 수)
  2. PLAN.mdplan_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에서 일관되게 보호되는지 확인한다. → Executec.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 범위

  • Executec.sessions lookup을 c.mu.Lock()/c.mu.Unlock()으로 감쌌다.
  • timeout/cancel 경로에서 c.Stop(context.Background()) 대신 해당 profile session만 close/kill/delete하도록 변경했다.

최종 검증 결과

$ 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의 지시사항대로 구현 진행.