<!-- task=m-protocol-evolution-compatibility/04+03_nonce_contract plan=0 tag=API -->

# Plan - API

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

`CODE_REVIEW-local-G04.md`의 구현 에이전트 소유 섹션 작성까지가 구현의 마지막 단계다. 검증을 실행하고 실제 출력/결과를 기록한 뒤 active 파일을 유지한 채 리뷰를 요청한다. 구현 중 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 생기면 직접 질문하지 말고 리뷰 stub의 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 남긴다. 후속 에이전트가 재실행으로 해소할 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

`nonce-boundary`는 wrap 직후 `1`로 돌아가는 기존 정책만으로는 부족하다. 오래 열린 연결에서 nonce wrap 시점에 낮은 nonce의 `sendRequest`가 아직 pending이면 새 outbound packet nonce가 pending correlation key와 충돌할 수 있다. 먼저 문서 계약을 `active pending nonce skip`으로 고정해 언어별 구현이 같은 기준을 따르게 한다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active `CODE_REVIEW-local-G04.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 채팅으로 사용자에게 직접 질문하지 않으며, code-review가 해당 요청의 타당성을 판단하고 필요할 때 `USER_REVIEW.md`를 작성한다.

## Archive Evidence Snapshot

- `agent-task/archive/2026/06/m-protocol-evolution-compatibility/03+01,02_fullname_tests/complete.log`: `fullname-tests` PASS, full matrix record `agent-test/runs/20260616-123431-proto-socket-full-matrix.md`.
- predecessor `03` 완료가 `04+03_nonce_contract` split 의존성을 충족한다.

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/ROADMAP.md`
- `agent-roadmap/milestones/protocol-evolution-compatibility.md`
- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/project/domain/protocol/rules.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/update-roadmap/SKILL.md`
- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`
- `agent-test/local/rules.md`
- `agent-test/local/protocol-smoke.md`
- `agent-test/local/proto-socket-full-matrix.md`
- `PROTOCOL.md`
- `VERSIONING.md`
- `PORTING_GUIDE.md`
- `dart/lib/src/communicator.dart`
- `dart/test/communicator_test.dart`
- `go/communicator.go`
- `go/communicator_nonce_test.go`
- `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`
- `kotlin/src/test/kotlin/com/tokilabs/proto_socket/CommunicatorTest.kt`
- `python/proto_socket/communicator.py`
- `python/test/test_communicator.py`
- `typescript/src/communicator.ts`
- `typescript/test/communicator.test.ts`

### 테스트 환경 규칙

- test_env: `local`
- 적용 규칙: `agent-test/local/rules.md`를 읽었다.
- 매칭 프로필: `agent-test/local/protocol-smoke.md`, `agent-test/local/proto-socket-full-matrix.md`
- 이 문서-only 선행 작업의 필수 검증은 `tools/check_proto_sync.sh`와 `git diff --check`다.
- full matrix는 구현 rollout이 끝나는 `06+04,05_nonce_kotlin_python_ts`에서 실행한다.

### 테스트 커버리지 공백

- 문서 변경 자체는 `tools/check_proto_sync.sh`와 diff whitespace로 확인한다.
- active pending nonce skip 동작은 코드 테스트가 필요하며 이 plan에서는 작성하지 않는다. 해당 공백은 05/06 계획에서 닫는다.

### 심볼 참조

- renamed/removed symbol: none

### 분할 판단

- split decision policy를 먼저 평가했다.
- 공유 task group: `agent-task/m-protocol-evolution-compatibility/`
- `04+03_nonce_contract`: predecessor `03` archive complete log로 충족됨.
- `05+04_nonce_dart_go`: predecessor `04` 필요, 계획 작성 시점에는 미충족.
- `06+04,05_nonce_kotlin_python_ts`: predecessors `04`, `05` 필요, 계획 작성 시점에는 미충족.
- 계약 문서와 언어별 구현은 위험과 검증 단위가 달라 분리한다.

### 범위 결정 근거

- 이 plan은 `PROTOCOL.md`, `VERSIONING.md`, `PORTING_GUIDE.md`만 수정한다.
- 언어별 communicator와 테스트는 05/06에서 수정한다.
- canonical proto schema는 변경하지 않는다.

### 빌드 등급

- `local-G04`: 문서 계약 갱신이며 검증은 deterministic smoke로 충분하다.

## 구현 체크리스트

- [ ] `PROTOCOL.md`의 `nonce` 섹션에 active pending nonce skip 정책과 all-positive-nonces-pending 예외를 명시한다.
- [ ] `VERSIONING.md`의 `nonce Overflow` 정책에 pending 충돌 회피와 호환성 기준을 반영한다.
- [ ] `PORTING_GUIDE.md`의 nonce 공통 구조 설명을 pending skip 기준으로 보강한다.
- [ ] `tools/check_proto_sync.sh`와 `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

이 task는 `03+01,02_fullname_tests` 완료 이후 실행한다. 근거는 `agent-task/archive/2026/06/m-protocol-evolution-compatibility/03+01,02_fullname_tests/complete.log`다.

### [API-1] Nonce Contract 문서화

#### 문제

[PROTOCOL.md](/config/workspace/proto-socket/PROTOCOL.md:159)는 wrap 후 `1` 재발행만 설명한다.

```md
159 ## nonce
161 - Starts at `1` per connection
162 - Increments by `1` on every send call (including requests and responses)
163 - Maximum nonce is `2,147,483,647` (`int32` max), the lowest common signed integer max across supported protocol fields
164 - After issuing `2,147,483,647`, implementations reset the internal counter to `0`; the next emitted packet nonce is `1`
165 - `0` is reserved and must not be emitted as `PacketBase.nonce`, because `responseNonce == 0` means "not a response"
```

#### 해결 방법

`After issuing...` 항목 다음에 후보 nonce가 active pending request nonce와 충돌하면 건너뛰어야 한다는 정책을 추가한다. 모든 양수 int32 nonce가 pending이면 새 outbound packet을 발행하지 말고 오류로 실패해야 한다고 명시한다.

#### 수정 파일 및 체크리스트

- [ ] `PROTOCOL.md`: `## nonce` bullet 보강
- [ ] `VERSIONING.md`: `## nonce Overflow` 정책 보강
- [ ] `PORTING_GUIDE.md`: `nonce 단조 증가` 행 보강

#### 테스트 작성

문서 변경이므로 새 테스트는 작성하지 않는다. 05/06에서 각 언어 boundary regression test를 작성한다.

#### 중간 검증

```bash
tools/check_proto_sync.sh
```

기대 결과: `Proto schemas are in sync.`

### [API-2] Porting 기준 정렬

#### 문제

[PORTING_GUIDE.md](/config/workspace/proto-socket/PORTING_GUIDE.md:20)는 nonce를 단조 증가로만 설명한다.

```md
20 | nonce 단조 증가 | `atomic.Int32` | 연결당 1에서 시작, 송신마다 +1. thread-safe하게 구현 |
```

#### 해결 방법

설명을 `pending request nonce와 충돌하는 후보는 skip`으로 확장하고, thread-safe 구현에서는 candidate 선택과 pending 조회가 같은 임계구역 또는 동등한 안전성을 가져야 한다고 적는다.

#### 수정 파일 및 체크리스트

- [ ] `PORTING_GUIDE.md`: 공통 구조 표의 nonce 행 갱신

#### 테스트 작성

문서 변경이므로 새 테스트는 작성하지 않는다.

#### 중간 검증

```bash
git diff --check
```

기대 결과: 출력 없음, exit code 0.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `PROTOCOL.md` | API-1 |
| `VERSIONING.md` | API-1 |
| `PORTING_GUIDE.md` | API-2 |

## 최종 검증

```bash
tools/check_proto_sync.sh
git diff --check
```

기대 결과: proto sync PASS, whitespace error 없음.

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