<!-- task=m-socket-session-loop/01_client_socket_layer plan=4 tag=REVIEW_REVIEW_REVIEW_REVIEW_API -->

# Plan - REVIEW_REVIEW_REVIEW_REVIEW_API

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

`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채우는 것이 필수 마지막 단계다. 구현 후 검증을 실행하고 실제 출력, 계획 대비 변경, 설계 결정을 review stub에 기록한 뒤 active 파일을 유지하고 리뷰 준비를 보고한다. 사용자 결정, 외부 환경 준비, 범위 충돌 없이는 안전하게 진행할 수 없으면 review stub의 `사용자 리뷰 요청`에 정확한 증거를 남기고 중단한다. `USER_REVIEW.md`, archive, `complete.log` 작성은 code-review 전용이다.

## 배경

네 번째 리뷰도 `FAIL`이다. 소스 코드와 패키지 변경은 이전 검증에서 통과했지만, active review stub이 plan의 마지막 필수 체크리스트 문구를 바꿨고 수동 축약 placeholder 검증도 자기 참조 match를 반환했다. 이번 후속은 `CODE_REVIEW-cloud-G07.md` 산출물 신뢰성만 좁게 복구한다.

## 사용자 리뷰 요청 흐름

구현 중 차단 조건은 active `CODE_REVIEW-*-G??.md`의 `사용자 리뷰 요청` 섹션에 기록한다. code-review가 그 내용을 검증해 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## 분석 결과

### 읽은 파일

- `agent-task/m-socket-session-loop/01_client_socket_layer/code_review_cloud_G07_3.log`
- `agent-task/m-socket-session-loop/01_client_socket_layer/plan_cloud_G07_3.log`

### 실패 근거

- `code_review_cloud_G07_3.log`의 `구현 체크리스트` 마지막 항목이 `plan_cloud_G07_3.log`의 필수 문구와 다르다. review stub은 item text/order를 바꾸면 안 되고 checkbox만 바꿀 수 있다.
- `rg` 기반 placeholder 검증이 no-match 성공 조건을 요구했지만, 실제 출력은 checklist/command/self-reference 및 설명문 match를 반환했다.

### 빌드 등급

- build: `cloud-G07`, review: `cloud-G07`.
- 후속 범위가 stdout/stderr 신뢰성, exit-status, review stub verification trust이므로 G07을 유지한다.

## 구현 체크리스트

- [ ] `CODE_REVIEW-cloud-G07.md`의 `구현 체크리스트` 항목 text/order를 `PLAN-cloud-G07.md`와 정확히 일치시킨다. 검증: `[REVIEW_REVIEW_REVIEW_REVIEW_API-1] 중간 검증`의 checklist parity command.
- [ ] 수동 축약 placeholder 검증을 자기 참조 없이 no-match 성공 조건으로 기록한다. 검증: `[REVIEW_REVIEW_REVIEW_REVIEW_API-2] 중간 검증`의 placeholder marker command.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_REVIEW_REVIEW_API-1] Restore checklist parity

문제: 이전 active review stub은 마지막 필수 checklist item을 영어 문장으로 바꿨다. code-review 규칙은 plan/review `구현 체크리스트` 항목의 text/order 일치를 요구한다.

해결 방법:

- active `CODE_REVIEW-cloud-G07.md`의 `구현 체크리스트`를 이 plan의 checklist와 같은 문구/순서로 둔다.
- 구현 에이전트는 checkbox만 `[ ]`에서 `[x]`로 바꾼다.
- 아래 parity command로 `[x]`와 `[ ]` 차이를 정규화한 뒤 문구/순서를 비교한다.

수정 파일 및 체크리스트:

- [ ] `agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md`

테스트 작성: 새 테스트 없음. review stub 프로토콜 복구 작업이다.

중간 검증:

```bash
python3 - <<'PY'
from pathlib import Path

def checklist(path):
    lines = Path(path).read_text().splitlines()
    start = lines.index("## 구현 체크리스트")
    items = []
    for line in lines[start + 1:]:
        if line.startswith("## ") or line.startswith("### "):
            break
        if line.startswith("- ["):
            items.append(line.replace("- [x]", "- [ ]"))
    return items

plan = checklist("agent-task/m-socket-session-loop/01_client_socket_layer/PLAN-cloud-G07.md")
review = checklist("agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md")
if plan != review:
    print("Checklist mismatch")
    max_len = max(len(plan), len(review))
    for idx in range(max_len):
        p = plan[idx] if idx < len(plan) else "<missing>"
        r = review[idx] if idx < len(review) else "<missing>"
        if p != r:
            print(f"{idx + 1}: plan={p}")
            print(f"{idx + 1}: review={r}")
    raise SystemExit(1)
print(f"Checklist parity OK ({len(plan)} items).")
PY
```

기대 결과: exit 0과 `Checklist parity OK (3 items).`

### [REVIEW_REVIEW_REVIEW_REVIEW_API-2] Replace self-matching placeholder check

문제: 이전 `rg` 명령은 검증 명령 자체와 checklist 설명을 match했다. no-match를 성공 조건으로 쓰려면 검증 명령이 자기 자신을 잡지 않아야 한다.

해결 방법:

- inline Python command에서 검사 문자열을 조합해 만들고, active review file 전체를 검사한다.
- 수동 축약 placeholder로 볼 항목은 단독 ellipsis 라인, 미해소 output placeholder, 깨진 marker 문자열이다.
- command 자체에는 검사 대상 literal을 직접 쓰지 않아 자기 참조 match를 피한다.

수정 파일 및 체크리스트:

- [ ] `agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md`

테스트 작성: 새 테스트 없음.

중간 검증:

```bash
python3 - <<'PY'
from pathlib import Path

path = Path("agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md")
needle_dots = "." * 3
needle_output = "(" + "output" + ")"
needle_broken = "agent-" + "ta##"
matches = []
for lineno, line in enumerate(path.read_text().splitlines(), 1):
    if line.strip() == needle_dots or needle_output in line or needle_broken in line:
        matches.append((lineno, line))
if matches:
    for lineno, line in matches:
        print(f"{lineno}:{line}")
    raise SystemExit(1)
print("No manual placeholder markers found.")
PY
```

기대 결과: exit 0과 `No manual placeholder markers found.`

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md` | REVIEW_REVIEW_REVIEW_REVIEW_API-1, REVIEW_REVIEW_REVIEW_REVIEW_API-2 |

## 최종 검증

```bash
python3 - <<'PY'
from pathlib import Path

def checklist(path):
    lines = Path(path).read_text().splitlines()
    start = lines.index("## 구현 체크리스트")
    items = []
    for line in lines[start + 1:]:
        if line.startswith("## ") or line.startswith("### "):
            break
        if line.startswith("- ["):
            items.append(line.replace("- [x]", "- [ ]"))
    return items

plan = checklist("agent-task/m-socket-session-loop/01_client_socket_layer/PLAN-cloud-G07.md")
review = checklist("agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md")
if plan != review:
    print("Checklist mismatch")
    max_len = max(len(plan), len(review))
    for idx in range(max_len):
        p = plan[idx] if idx < len(plan) else "<missing>"
        r = review[idx] if idx < len(review) else "<missing>"
        if p != r:
            print(f"{idx + 1}: plan={p}")
            print(f"{idx + 1}: review={r}")
    raise SystemExit(1)
print(f"Checklist parity OK ({len(plan)} items).")
PY

python3 - <<'PY'
from pathlib import Path

path = Path("agent-task/m-socket-session-loop/01_client_socket_layer/CODE_REVIEW-cloud-G07.md")
needle_dots = "." * 3
needle_output = "(" + "output" + ")"
needle_broken = "agent-" + "ta##"
matches = []
for lineno, line in enumerate(path.read_text().splitlines(), 1):
    if line.strip() == needle_dots or needle_output in line or needle_broken in line:
        matches.append((lineno, line))
if matches:
    for lineno, line in matches:
        print(f"{lineno}:{line}")
    raise SystemExit(1)
print("No manual placeholder markers found.")
PY
```

기대 결과: 두 명령 모두 exit 0이고 각각 `Checklist parity OK (3 items).`, `No manual placeholder markers found.`를 출력한다.

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