feat: protocol evolution compatibility task - nonce contract plan
This commit is contained in:
parent
21eed0e2ab
commit
7f7840bc47
9 changed files with 1136 additions and 4 deletions
57
PROTOCOL.md
57
PROTOCOL.md
|
|
@ -101,6 +101,33 @@ Changing heartbeat timing semantics, response behavior, or disconnect rules is a
|
|||
|
||||
---
|
||||
|
||||
## Optional Capability Announcement
|
||||
|
||||
Implementations may define an application-level `ProtoSocketHello` message, or an equivalent project-specific hello message, to announce protocol and implementation capabilities after connection open.
|
||||
|
||||
This message is optional and non-blocking in protocol `0.1`:
|
||||
|
||||
- It is a normal `PacketBase` payload sent through the existing `typeName` routing path.
|
||||
- It must not be required before normal messages, requests, responses, or heartbeats can flow.
|
||||
- Peers that do not recognize its `typeName` may ignore it according to their normal unknown-message policy.
|
||||
- Implementations must not treat a missing hello message as a protocol error in `0.1`.
|
||||
|
||||
Recommended payload fields:
|
||||
|
||||
```protobuf
|
||||
message ProtoSocketHello {
|
||||
string protocolVersion = 1; // e.g. "0.1"
|
||||
repeated string capabilities = 2; // stable capability tokens
|
||||
map<string, string> implementation = 3; // optional language/library metadata
|
||||
}
|
||||
```
|
||||
|
||||
Capability tokens should be stable ASCII strings such as `std_error.v1` or `ws.wss`. Application-specific tokens should use a project prefix to avoid collisions.
|
||||
|
||||
Promoting this message to a required handshake is a future protocol-version decision and is not part of protocol `0.1`.
|
||||
|
||||
---
|
||||
|
||||
## typeName Convention
|
||||
|
||||
`typeName` uses the protobuf full message name on the send side.
|
||||
|
|
@ -167,6 +194,30 @@ Requester Responder
|
|||
- Both sides can be requester and responder simultaneously on the same connection
|
||||
- For a given `typeName` on one connection, register it with either `addListener` or `addRequestListener`, not both. Mixed registration is ambiguous and rejected by the Dart and Go implementations.
|
||||
|
||||
### Standard Error Response Convention
|
||||
|
||||
Implementations may define a `ProtoSocketError` message, or an equivalent project-specific error message, for request handlers that fail before producing the expected response.
|
||||
|
||||
Recommended payload fields:
|
||||
|
||||
```protobuf
|
||||
message ProtoSocketError {
|
||||
string code = 1; // stable machine-readable error code
|
||||
string message = 2; // safe human-readable message
|
||||
string detail = 3; // optional non-sensitive detail
|
||||
string debug = 4; // optional local/debug-only detail
|
||||
}
|
||||
```
|
||||
|
||||
When used as a request failure response:
|
||||
|
||||
- The packet's `responseNonce` should be set to the failing request's `nonce`.
|
||||
- The packet's `typeName` should identify the error message, for example `proto_socket.ProtoSocketError` if this becomes a shared common message in a future schema.
|
||||
- A requester that understands the convention should complete the pending request with a typed error instead of waiting for timeout.
|
||||
- A requester that does not understand the convention may see an expected-response type mismatch or may continue to timeout, depending on its current response handling.
|
||||
|
||||
Protocol `0.1` does not require every request handler failure to send an error response. Adding a common error message to the canonical proto schema requires parser map updates and cross-language tests before it can become a shared compatibility contract.
|
||||
|
||||
---
|
||||
|
||||
## Receive Ordering and Backpressure
|
||||
|
|
@ -195,6 +246,12 @@ A single receive coordinator dequeues packets one at a time and dispatches them:
|
|||
|
||||
**Ordering guarantee**: for a given connection, listeners and request handlers are invoked strictly in packet arrival order. Automatic responses are enqueued into the write queue in the same order their triggering requests were dispatched.
|
||||
|
||||
### Response Correlation Path
|
||||
|
||||
Packets with `responseNonce > 0` complete an already-pending request and do not invoke listeners or request handlers. Implementations may therefore complete those pending requests through a direct correlation path before or instead of the listener/request-handler FIFO queue.
|
||||
|
||||
This response path does not weaken the listener/request-handler ordering guarantee: packets that dispatch to `addListener` or `addRequestListener` must still be processed in arrival order, and automatic responses produced by request handlers must still be enqueued in request-dispatch order. Implementations that enqueue response packets in the same inbound queue must produce equivalent pending-request completion semantics.
|
||||
|
||||
### Close, Drain, and Cancel
|
||||
|
||||
- When `Close()` is called, the implementation stops accepting new inbound packets and drains the already-enqueued packets in the inbound queue before tearing down the receive coordinator.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ Proto Socket tracks protocol compatibility separately from language package vers
|
|||
|
||||
`0.1` is the current compatibility contract for the checked-in available implementations. The wire format does not carry a protocol version field yet; compatibility is verified by shared proto definitions, unit tests, and cross-language tests.
|
||||
|
||||
Protocol `0.1` also allows optional application-level convention messages for capability announcement and request error reporting. These conventions do not change the required handshake or the `PacketBase` wire fields unless they are promoted in a later protocol version.
|
||||
|
||||
## Protocol Version
|
||||
|
||||
The protocol version describes the wire-format and behavior contract that every language implementation must satisfy:
|
||||
|
|
@ -61,9 +63,27 @@ Examples of non-breaking changes:
|
|||
- Adding optional fields to application messages when older peers can ignore them.
|
||||
- Adding a new language implementation that passes the existing protocol and cross-language tests.
|
||||
- Tightening tests or documentation without changing wire behavior.
|
||||
- Adding an optional hello/capability message that peers may ignore and that is not required before normal traffic.
|
||||
- Adding an optional standard error response convention, provided older peers can still fail by timeout or existing response type-mismatch behavior.
|
||||
|
||||
Backward-compatible message additions require updated parser maps and cross-language tests before release.
|
||||
|
||||
## Optional Capability Announcement
|
||||
|
||||
`ProtoSocketHello`, or an equivalent project-specific message, is a candidate convention for announcing:
|
||||
|
||||
- `protocolVersion`
|
||||
- stable `capabilities` tokens
|
||||
- optional implementation metadata
|
||||
|
||||
In protocol `0.1`, this message is not a required handshake. A peer must be able to send and receive normal messages without first receiving a hello/capability message. Making a hello message mandatory, changing connection readiness semantics, or disconnecting older peers that do not send it requires a protocol-version review.
|
||||
|
||||
## Standard Error Response Convention
|
||||
|
||||
`ProtoSocketError`, or an equivalent project-specific message, is a candidate convention for request handler failures. A supported error response should carry the original request nonce in `responseNonce`, a stable error code, a safe message, and optional detail/debug fields.
|
||||
|
||||
In protocol `0.1`, implementations may continue to report handler failure as timeout, response type mismatch, or implementation-specific errors. Requiring all handlers to emit a shared error response, or requiring every requester to treat a particular error message type specially, requires parser map updates, cross-language tests, and compatibility review.
|
||||
|
||||
## nonce Overflow
|
||||
|
||||
`nonce` and `responseNonce` fields are protobuf `int32` values (signed 32-bit).
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ wire message identity를 full proto name으로 정렬하고, legacy simple name
|
|||
|
||||
현재 `PacketBase`의 단순성을 유지하면서, future protocol capability를 안전하게 추가할 수 있는 경계를 만든다.
|
||||
|
||||
- [ ] [hello-cap] `ProtoSocketHello` 또는 동등한 비차단 version/capability message 후보를 `PROTOCOL.md`와 `VERSIONING.md`에 문서화한다. 후보 payload에는 `protocolVersion`, `capabilities`, 선택적 implementation metadata를 포함한다. 구버전 peer가 모르면 무시할 수 있는 경로로 두고, 이 마일스톤에서 필수 handshake로 승격하지 않는다.
|
||||
- [ ] [std-error] `ProtoSocketError` 또는 동등한 표준 오류 응답 convention을 문서화한다. 후보 payload에는 stable error code, message, 선택적 detail/debug field를 포함한다. request handler 실패가 timeout만으로 보이지 않게 하되, 구버전 peer와의 mismatch 처리를 명시하고, 이 마일스톤에서 모든 handler가 오류 응답을 강제 송신하도록 바꾸지는 않는다.
|
||||
- [x] [hello-cap] `ProtoSocketHello` 또는 동등한 비차단 version/capability message 후보를 `PROTOCOL.md`와 `VERSIONING.md`에 문서화한다. 후보 payload에는 `protocolVersion`, `capabilities`, 선택적 implementation metadata를 포함한다. 구버전 peer가 모르면 무시할 수 있는 경로로 두고, 이 마일스톤에서 필수 handshake로 승격하지 않는다.
|
||||
- [x] [std-error] `ProtoSocketError` 또는 동등한 표준 오류 응답 convention을 문서화한다. 후보 payload에는 stable error code, message, 선택적 detail/debug field를 포함한다. request handler 실패가 timeout만으로 보이지 않게 하되, 구버전 peer와의 mismatch 처리를 명시하고, 이 마일스톤에서 모든 handler가 오류 응답을 강제 송신하도록 바꾸지는 않는다.
|
||||
- [ ] [nonce-boundary] nonce wrap 시 pending request nonce와 충돌하지 않도록 active pending nonce skip 정책과 boundary 테스트를 보강한다.
|
||||
- [ ] [ordering-doc] response completion이 pending correlation 경로로 queue를 우회할 수 있음을 `Receive Ordering and Backpressure` 계약에 명확히 기록한다. listener/request handler dispatch FIFO 보장과 구분한다.
|
||||
- [x] [ordering-doc] response completion이 pending correlation 경로로 queue를 우회할 수 있음을 `Receive Ordering and Backpressure` 계약에 명확히 기록한다. listener/request handler dispatch FIFO 보장과 구분한다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
|
|
@ -90,4 +90,4 @@ wire message identity를 full proto name으로 정렬하고, legacy simple name
|
|||
- 선행 작업: 프로토콜 기준선
|
||||
- 후속 작업: 필요 시 protocol `0.2` 또는 `1.0` compatibility release planning
|
||||
- 확인 필요: 없음
|
||||
- 작업 현황 동기화(2026-06-16): `01_proto_fullname_foundation`, `02+01_legacy_alias`, `03+01,02_fullname_tests`가 모두 PASS 완료되어 `proto-package-sync`, `fullname-type`, `legacy-alias`, `fullname-tests`를 반영했다. 근거는 `agent-task/archive/2026/06/m-protocol-evolution-compatibility/01_proto_fullname_foundation/complete.log`, `agent-task/archive/2026/06/m-protocol-evolution-compatibility/02+01_legacy_alias/complete.log`, `agent-task/archive/2026/06/m-protocol-evolution-compatibility/03+01,02_fullname_tests/complete.log`다. 다음 미완료 범위는 evolution Epic의 `hello-cap`, `std-error`, `nonce-boundary`, `ordering-doc`이다.
|
||||
- 작업 현황 동기화(2026-06-16): `01_proto_fullname_foundation`, `02+01_legacy_alias`, `03+01,02_fullname_tests`가 모두 PASS 완료되어 `proto-package-sync`, `fullname-type`, `legacy-alias`, `fullname-tests`를 반영했다. 근거는 `agent-task/archive/2026/06/m-protocol-evolution-compatibility/01_proto_fullname_foundation/complete.log`, `agent-task/archive/2026/06/m-protocol-evolution-compatibility/02+01_legacy_alias/complete.log`, `agent-task/archive/2026/06/m-protocol-evolution-compatibility/03+01,02_fullname_tests/complete.log`다. evolution Epic의 `hello-cap`, `std-error`, `ordering-doc`는 `PROTOCOL.md`/`VERSIONING.md` 문서 반영과 `tools/check_proto_sync.sh` PASS로 직접 완료 처리했다. 남은 미완료 범위는 `nonce-boundary`이며, 구현 계획은 `agent-task/m-protocol-evolution-compatibility/04+03_nonce_contract/`, `agent-task/m-protocol-evolution-compatibility/05+04_nonce_dart_go/`, `agent-task/m-protocol-evolution-compatibility/06+04,05_nonce_kotlin_python_ts/`에 split 작성했다.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
<!-- task=m-protocol-evolution-compatibility/04+03_nonce_contract plan=0 tag=API -->
|
||||
|
||||
# Code Review Reference - API
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-16
|
||||
task=m-protocol-evolution-compatibility/04+03_nonce_contract, plan=0, tag=API
|
||||
|
||||
## 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 의존성을 충족한다.
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-local-G04.md` -> `code_review_local_G04_N.log`, `PLAN-local-G04.md` -> `plan_local_G04_M.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-protocol-evolution-compatibility/04+03_nonce_contract/`로 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [API-1] Nonce Contract 문서화 | [ ] |
|
||||
| [API-2] Porting 기준 정렬 | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] `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의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `nonce` 계약이 active pending request nonce skip을 명확히 요구하는지 확인한다.
|
||||
- 포팅 가이드가 새 언어 구현 기준으로 충분한지 확인한다.
|
||||
- proto schema를 변경하지 않았는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
|
||||
### API-1 중간 검증
|
||||
```bash
|
||||
$ tools/check_proto_sync.sh
|
||||
(output)
|
||||
```
|
||||
|
||||
### API-2 중간 검증
|
||||
```bash
|
||||
$ git diff --check
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ tools/check_proto_sync.sh
|
||||
$ git diff --check
|
||||
(output)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## 섹션 소유권
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute archive, complete.log, or task-directory archive move steps |
|
||||
| Archive Evidence Snapshot | Fixed at stub creation | Implementing agent uses it as default prior-loop context |
|
||||
| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` to `[x]` only |
|
||||
| 구현 체크리스트 | Implementing agent | Check `[ ]` to `[x]` only; final checkbox is mandatory |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
|
||||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Review focus areas |
|
||||
| 검증 결과 | Implementing agent | Fill command output only |
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
<!-- 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<!-- task=m-protocol-evolution-compatibility/05+04_nonce_dart_go plan=0 tag=API -->
|
||||
|
||||
# Code Review Reference - API
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-16
|
||||
task=m-protocol-evolution-compatibility/05+04_nonce_dart_go, plan=0, tag=API
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-cloud-G06.md` -> `code_review_cloud_G06_N.log`, `PLAN-cloud-G06.md` -> `plan_cloud_G06_M.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-protocol-evolution-compatibility/05+04_nonce_dart_go/`로 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [API-1] Dart pending nonce skip | [ ] |
|
||||
| [API-2] Go pending nonce skip | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 04번 predecessor `complete.log`가 존재하는지 확인하고, 없으면 구현을 시작하지 않고 리뷰 stub에 차단 근거를 남긴다.
|
||||
- [ ] Dart `Communicator.nextNonce()`가 active `_pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정한다.
|
||||
- [ ] Dart `communicator_test.dart`에 wrap 후 `1`이 pending이면 다음 send/request nonce가 `2`가 되는 regression test를 추가한다.
|
||||
- [ ] Go `Communicator`의 nonce 선택이 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정한다.
|
||||
- [ ] Go `communicator_nonce_test.go`에 wrap 후 pending nonce skip regression test를 추가한다.
|
||||
- [ ] `cd dart && dart test test/communicator_test.dart`, `cd go && go test ./...`, `git diff --check`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- Dart와 Go 모두 active pending nonce와 충돌하는 candidate를 skip하는지 확인한다.
|
||||
- Go call site error handling이 deadlock이나 swallowed error를 만들지 않는지 확인한다.
|
||||
- Regression tests가 단순 wrap이 아니라 pending collision을 실제로 재현하는지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
|
||||
### API-1 중간 검증
|
||||
```bash
|
||||
$ cd dart && dart test test/communicator_test.dart
|
||||
(output)
|
||||
```
|
||||
|
||||
### API-2 중간 검증
|
||||
```bash
|
||||
$ cd go && go test ./...
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ cd dart && dart test test/communicator_test.dart
|
||||
$ cd go && go test ./...
|
||||
$ git diff --check
|
||||
(output)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## 섹션 소유권
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute archive, complete.log, or task-directory archive move steps |
|
||||
| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` to `[x]` only |
|
||||
| 구현 체크리스트 | Implementing agent | Check `[ ]` to `[x]` only; final checkbox is mandatory |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
|
||||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Review focus areas |
|
||||
| 검증 결과 | Implementing agent | Fill command output only |
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
<!-- task=m-protocol-evolution-compatibility/05+04_nonce_dart_go plan=0 tag=API -->
|
||||
|
||||
# Plan - API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-cloud-G06.md`의 구현 에이전트 소유 섹션 작성까지가 구현의 마지막 단계다. 검증을 실행하고 실제 출력/결과를 기록한 뒤 active 파일을 유지한 채 리뷰를 요청한다. 구현 중 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 생기면 직접 질문하지 말고 리뷰 stub의 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 남긴다. 후속 에이전트가 재실행으로 해소할 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.
|
||||
|
||||
## 배경
|
||||
|
||||
Dart와 Go는 현재 `nonce` wrap 후 후보 값이 active pending request nonce인지 확인하지 않는다. 이 작업은 reference 역할을 하는 두 구현에서 pending skip 정책을 먼저 구현하고, 같은 실패 모드를 잡는 boundary regression test를 추가한다. 나머지 언어 rollout과 full matrix는 06번 작업에서 이어간다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 차단은 active `CODE_REVIEW-cloud-G06.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 채팅으로 사용자에게 직접 질문하지 않으며, code-review가 해당 요청의 타당성을 판단하고 필요할 때 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 읽은 파일
|
||||
|
||||
- `agent-roadmap/current.md`
|
||||
- `agent-roadmap/ROADMAP.md`
|
||||
- `agent-roadmap/milestones/protocol-evolution-compatibility.md`
|
||||
- `agent-ops/rules/project/domain/protocol/rules.md`
|
||||
- `agent-ops/skills/common/plan/SKILL.md`
|
||||
- `agent-test/local/rules.md`
|
||||
- `agent-test/local/proto-socket-full-matrix.md`
|
||||
- `dart/lib/src/communicator.dart`
|
||||
- `dart/test/communicator_test.dart`
|
||||
- `go/communicator.go`
|
||||
- `go/communicator_nonce_test.go`
|
||||
- `PROTOCOL.md`
|
||||
- `VERSIONING.md`
|
||||
- `PORTING_GUIDE.md`
|
||||
|
||||
### 테스트 환경 규칙
|
||||
|
||||
- test_env: `local`
|
||||
- 적용 규칙: `agent-test/local/rules.md`를 읽었다.
|
||||
- 매칭 프로필: `agent-test/local/proto-socket-full-matrix.md`
|
||||
- 이 split의 직접 검증은 Dart/Go focused tests다. full matrix는 모든 언어 rollout이 끝나는 06번에서 실행한다.
|
||||
|
||||
### 테스트 커버리지 공백
|
||||
|
||||
- Dart: 기존 `nonce wraps after int32 max without emitting zero`, `sendRequest matches response at nonce wrap boundary`는 단순 wrap만 검증하고 active pending nonce skip은 검증하지 않는다.
|
||||
- Go: 기존 `TestNonceWrapsAfterInt32MaxWithoutEmittingZero`, `TestSendRequestNonceWrapsAtInt32Max`는 단순 wrap만 검증하고 active pending nonce skip은 검증하지 않는다.
|
||||
- Kotlin/Python/TypeScript는 06번에서 다룬다.
|
||||
|
||||
### 심볼 참조
|
||||
|
||||
- renamed/removed symbol: none
|
||||
- Go에서 `nextNonce()` 시그니처를 변경한다면 call sites는 [go/communicator.go](/config/workspace/proto-socket/go/communicator.go:305), [go/communicator.go](/config/workspace/proto-socket/go/communicator.go:318), [go/communicator.go](/config/workspace/proto-socket/go/communicator.go:614)이다.
|
||||
|
||||
### 분할 판단
|
||||
|
||||
- split decision policy를 먼저 평가했다.
|
||||
- 공유 task group: `agent-task/m-protocol-evolution-compatibility/`
|
||||
- `04+03_nonce_contract`: 선행 계약 문서 작업.
|
||||
- `05+04_nonce_dart_go`: 이 plan. predecessor `04`가 필요하며 계획 작성 시점에는 active plan만 있고 `complete.log`는 없다.
|
||||
- `06+04,05_nonce_kotlin_python_ts`: 04/05 완료 후 실행.
|
||||
- Dart/Go는 reference 구현 경계이고 Kotlin/Python/TypeScript와 테스트 러너가 달라 별도 리뷰 단위로 분리한다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 이 plan은 Dart와 Go communicator 및 focused nonce tests만 수정한다.
|
||||
- Kotlin/Python/TypeScript는 06번에서 수정한다.
|
||||
- cross-language crosstest 기대값은 바꾸지 않는다. nonce 충돌은 동일 언어 unit boundary로 검증한다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- `cloud-G06`: protocol/concurrency 성격의 동작 변경이고 Go는 atomic + pending map 경계를 함께 검토해야 한다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 04번 predecessor `complete.log`가 존재하는지 확인하고, 없으면 구현을 시작하지 않고 리뷰 stub에 차단 근거를 남긴다.
|
||||
- [ ] Dart `Communicator.nextNonce()`가 active `_pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정한다.
|
||||
- [ ] Dart `communicator_test.dart`에 wrap 후 `1`이 pending이면 다음 send/request nonce가 `2`가 되는 regression test를 추가한다.
|
||||
- [ ] Go `Communicator`의 nonce 선택이 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정한다.
|
||||
- [ ] Go `communicator_nonce_test.go`에 wrap 후 pending nonce skip regression test를 추가한다.
|
||||
- [ ] `cd dart && dart test test/communicator_test.dart`, `cd go && go test ./...`, `git diff --check`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
`05+04_nonce_dart_go`는 디렉터리명 기준 predecessor `04`를 요구한다. 구현 전 `agent-task/m-protocol-evolution-compatibility/04+03_nonce_contract/complete.log` 또는 matching archive complete log를 확인한다.
|
||||
|
||||
### [API-1] Dart pending nonce skip
|
||||
|
||||
#### 문제
|
||||
|
||||
[dart/lib/src/communicator.dart](/config/workspace/proto-socket/dart/lib/src/communicator.dart:69)는 max 뒤 `1`로 돌아가지만 `_pendingRequests`를 보지 않는다.
|
||||
|
||||
```dart
|
||||
69 int nextNonce() {
|
||||
70 if (_nonce >= maxNonce) {
|
||||
71 _nonce = 0;
|
||||
72 }
|
||||
73 _nonce += 1;
|
||||
74 return _nonce;
|
||||
75 }
|
||||
```
|
||||
|
||||
[dart/lib/src/communicator.dart](/config/workspace/proto-socket/dart/lib/src/communicator.dart:210)는 이 값을 바로 pending key로 등록한다.
|
||||
|
||||
```dart
|
||||
210 final requestNonce = nextNonce();
|
||||
213 _pendingRequests[requestNonce] = _PendingRequest(
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
`nextNonce()`에서 후보 nonce를 만들고 `_pendingRequests.containsKey(candidate)`이면 계속 진행한다. 최대 `maxNonce`번 시도해도 후보가 없으면 `StateError('no available nonce: all positive int32 nonces are pending')`를 던진다. 이 메서드는 `send`, `sendRequest`, 자동 response가 공통으로 사용하므로 모든 outbound nonce가 active pending key를 피한다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `dart/lib/src/communicator.dart`: bounded candidate loop 추가
|
||||
- [ ] `dart/test/communicator_test.dart`: pending skip regression 추가
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`dart/test/communicator_test.dart`에 새 테스트를 추가한다. 절차: nonce를 `maxNonce`, pending request key `1`을 만든 뒤 응답하지 않은 상태에서 `send()` 또는 두 번째 `sendRequest()`를 호출해 새 packet nonce가 `2`인지 확인한다. 기존 pending request는 timeout이 길게 걸리지 않게 `closeForTest()`로 정리한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
cd dart && dart test test/communicator_test.dart
|
||||
```
|
||||
|
||||
기대 결과: communicator tests PASS.
|
||||
|
||||
### [API-2] Go pending nonce skip
|
||||
|
||||
#### 문제
|
||||
|
||||
[go/communicator.go](/config/workspace/proto-socket/go/communicator.go:187)는 atomic counter만 보고 후보 nonce를 반환한다.
|
||||
|
||||
```go
|
||||
187 func (c *Communicator) nextNonce() int32 {
|
||||
188 for {
|
||||
189 current := c.nonce.Load()
|
||||
190 var next int32
|
||||
191 if current >= MaxNonce {
|
||||
192 next = 1
|
||||
193 } else {
|
||||
194 next = current + 1
|
||||
195 }
|
||||
196 if c.nonce.CompareAndSwap(current, next) {
|
||||
197 return next
|
||||
198 }
|
||||
199 }
|
||||
200 }
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
Go는 `pendingRequests`가 mutex로 보호되므로 candidate 확정 시 pending map 확인도 안전하게 수행한다. 권장 구현은 `nextNonce() (int32, error)`로 바꾸고, 후보가 pending에 있으면 다음 후보를 계속 찾는다. `Send`, `SendRequest`, `AddRequestListenerTyped`의 response path는 새 error를 처리해야 한다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `go/communicator.go`: `nextNonce` pending skip 및 call site error 처리
|
||||
- [ ] `go/communicator_nonce_test.go`: pending skip regression 추가
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`go/communicator_nonce_test.go`에 `TestNextNonceSkipsActivePendingAfterWrap`를 추가한다. 절차: nonce를 `MaxNonce`, pending request key `1`을 만든 뒤 다음 send/request가 nonce `2`를 발행하는지 확인한다. 직접 map을 조작하는 대신 첫 `SendRequestTyped`를 시작해 pending `1`을 만들고 응답하지 않은 상태에서 `Send`를 호출한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
cd go && go test ./...
|
||||
```
|
||||
|
||||
기대 결과: root/go test packages PASS.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `dart/lib/src/communicator.dart` | API-1 |
|
||||
| `dart/test/communicator_test.dart` | API-1 |
|
||||
| `go/communicator.go` | API-2 |
|
||||
| `go/communicator_nonce_test.go` | API-2 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
cd dart && dart test test/communicator_test.dart
|
||||
cd go && go test ./...
|
||||
git diff --check
|
||||
```
|
||||
|
||||
기대 결과: Dart communicator tests PASS, Go tests PASS, whitespace error 없음.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
<!-- task=m-protocol-evolution-compatibility/06+04,05_nonce_kotlin_python_ts plan=0 tag=API -->
|
||||
|
||||
# Code Review Reference - API
|
||||
|
||||
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
|
||||
> The task is NOT complete until every implementation-owned section below is filled in.
|
||||
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
|
||||
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
|
||||
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves.
|
||||
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-review.
|
||||
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
|
||||
> Follow the ownership table at the bottom of this file for which sections you own.
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-06-16
|
||||
task=m-protocol-evolution-compatibility/06+04,05_nonce_kotlin_python_ts, plan=0, tag=API
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/milestones/protocol-evolution-compatibility.md`
|
||||
- Task ids:
|
||||
- `nonce-boundary`: nonce wrap 시 pending request nonce와 충돌하지 않도록 active pending nonce skip 정책과 boundary 테스트를 보강한다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.
|
||||
|
||||
1. 판정을 append한다.
|
||||
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
|
||||
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-protocol-evolution-compatibility/06+04,05_nonce_kotlin_python_ts/`로 이동한다.
|
||||
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
|
||||
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [API-1] Kotlin pending nonce skip | [ ] |
|
||||
| [API-2] Python pending nonce skip | [ ] |
|
||||
| [API-3] TypeScript pending nonce skip | [ ] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 04번과 05번 predecessor `complete.log`가 모두 존재하는지 확인하고, 없으면 구현을 시작하지 않고 리뷰 stub에 차단 근거를 남긴다.
|
||||
- [ ] Kotlin `Communicator.nextNonce()`가 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] Python `Communicator.next_nonce()`가 active `_pending_requests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] TypeScript `Communicator.nextNonce()`가 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] `cd kotlin && ./gradlew test`, `cd python && python3 -m pytest -q`, `cd typescript && npm run check && npm test`를 실행한다.
|
||||
- [ ] `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`과 `git diff --check`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/{task_name}/`를 `agent-task/archive/YYYY/MM/{task_name}/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/{task_group}/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._
|
||||
|
||||
- 상태: 없음
|
||||
- 사유 유형: 없음
|
||||
- 결정 필요: 없음
|
||||
- 차단 근거: 없음
|
||||
- 실행한 검증/명령: 없음
|
||||
- 자동 후속 불가 이유: 없음
|
||||
- 재개 조건: 없음
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- Kotlin/Python/TypeScript가 같은 pending skip 의미를 구현하는지 확인한다.
|
||||
- 새 테스트가 pending collision을 실제로 만든 뒤 다음 nonce가 `2`로 넘어가는지 확인한다.
|
||||
- full matrix record가 실제 PASS이고 `nonce-boundary` Roadmap Targets를 체크할 근거가 충분한지 확인한다.
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
필수 규칙:
|
||||
- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다.
|
||||
- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다.
|
||||
- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다.
|
||||
|
||||
### API-1 중간 검증
|
||||
```bash
|
||||
$ cd kotlin && ./gradlew test
|
||||
(output)
|
||||
```
|
||||
|
||||
### API-2 중간 검증
|
||||
```bash
|
||||
$ cd python && python3 -m pytest -q
|
||||
(output)
|
||||
```
|
||||
|
||||
### API-3 중간 검증
|
||||
```bash
|
||||
$ cd typescript && npm run check && npm test
|
||||
(output)
|
||||
```
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ cd kotlin && ./gradlew test
|
||||
$ cd python && python3 -m pytest -q
|
||||
$ cd typescript && npm run check && npm test
|
||||
$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all
|
||||
$ git diff --check
|
||||
(output)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
> If anything is blank, go back and fill it in before saving this file.
|
||||
> Leave review-agent-only sections unchanged.
|
||||
|
||||
## 섹션 소유권
|
||||
|
||||
| Section | Owner | Note |
|
||||
|---------|-------|------|
|
||||
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute archive, complete.log, or task-directory archive move steps |
|
||||
| Roadmap Targets | Fixed at stub creation | Implementing agent must not modify; code-review copies it into `complete.log` as Roadmap Completion only on PASS |
|
||||
| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` to `[x]` only |
|
||||
| 구현 체크리스트 | Implementing agent | Check `[ ]` to `[x]` only; final checkbox is mandatory |
|
||||
| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section |
|
||||
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content |
|
||||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Review focus areas |
|
||||
| 검증 결과 | Implementing agent | Fill command output only |
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
<!-- task=m-protocol-evolution-compatibility/06+04,05_nonce_kotlin_python_ts plan=0 tag=API -->
|
||||
|
||||
# Plan - API
|
||||
|
||||
## 이 파일을 읽는 구현 에이전트에게
|
||||
|
||||
`CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션 작성까지가 구현의 마지막 단계다. 검증을 실행하고 실제 출력/결과를 기록한 뒤 active 파일을 유지한 채 리뷰를 요청한다. 구현 중 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 생기면 직접 질문하지 말고 리뷰 stub의 `사용자 리뷰 요청` 섹션에 근거와 재개 조건을 남긴다. 후속 에이전트가 재실행으로 해소할 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.
|
||||
|
||||
## 배경
|
||||
|
||||
04번 계약과 05번 Dart/Go 기준 구현이 완료되면 Kotlin, Python, TypeScript도 같은 pending nonce skip 정책으로 정렬해야 한다. 이 작업은 남은 세 언어의 boundary regression test를 추가하고 full matrix로 cross-language 호환성을 확인한다. PASS 시 현재 마일스톤의 `nonce-boundary` Task 완료 근거가 된다.
|
||||
|
||||
## 사용자 리뷰 요청 흐름
|
||||
|
||||
구현 중 차단은 active `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 구현 에이전트는 채팅으로 사용자에게 직접 질문하지 않으며, code-review가 해당 요청의 타당성을 판단하고 필요할 때 `USER_REVIEW.md`를 작성한다.
|
||||
|
||||
## Roadmap Targets
|
||||
|
||||
- Milestone: `agent-roadmap/milestones/protocol-evolution-compatibility.md`
|
||||
- Task ids:
|
||||
- `nonce-boundary`: nonce wrap 시 pending request nonce와 충돌하지 않도록 active pending nonce skip 정책과 boundary 테스트를 보강한다.
|
||||
- Completion mode: check-on-pass
|
||||
|
||||
## 분석 결과
|
||||
|
||||
### 읽은 파일
|
||||
|
||||
- `agent-roadmap/current.md`
|
||||
- `agent-roadmap/ROADMAP.md`
|
||||
- `agent-roadmap/milestones/protocol-evolution-compatibility.md`
|
||||
- `agent-ops/rules/project/domain/protocol/rules.md`
|
||||
- `agent-ops/skills/common/plan/SKILL.md`
|
||||
- `agent-test/local/rules.md`
|
||||
- `agent-test/local/proto-socket-full-matrix.md`
|
||||
- `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`
|
||||
- `PROTOCOL.md`
|
||||
- `VERSIONING.md`
|
||||
- `PORTING_GUIDE.md`
|
||||
|
||||
### 테스트 환경 규칙
|
||||
|
||||
- test_env: `local`
|
||||
- 적용 규칙: `agent-test/local/rules.md`를 읽었다.
|
||||
- 매칭 프로필: `agent-test/local/proto-socket-full-matrix.md`
|
||||
- 직접 검증: Kotlin/Python/TypeScript focused tests.
|
||||
- 최종 검증: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`
|
||||
|
||||
### 테스트 커버리지 공백
|
||||
|
||||
- Kotlin: 기존 `testNonceWrapsAfterIntMaxWithoutEmittingZero`, `testSendRequestNonceWrapsAtInt32Max`는 active pending nonce skip을 검증하지 않는다.
|
||||
- Python: 기존 `test_nonce_wraps_after_int32_max_without_emitting_zero`, `test_send_request_nonce_wraps_at_int32_max`는 active pending nonce skip을 검증하지 않는다.
|
||||
- TypeScript: 기존 `nonce wraps after int32 max without emitting zero`, `sendRequest nonce wraps at int32 max`는 active pending nonce skip을 검증하지 않는다.
|
||||
- full matrix는 cross-language smoke를 보장하지만 wrap boundary 자체는 focused unit tests가 담당한다.
|
||||
|
||||
### 심볼 참조
|
||||
|
||||
- renamed/removed symbol: none
|
||||
- Kotlin `nextNonce()` call sites: [Communicator.kt](/config/workspace/proto-socket/kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt:304), [Communicator.kt](/config/workspace/proto-socket/kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt:316), [Communicator.kt](/config/workspace/proto-socket/kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt:683)
|
||||
- Python `next_nonce()` call sites: [communicator.py](/config/workspace/proto-socket/python/proto_socket/communicator.py:306), [communicator.py](/config/workspace/proto-socket/python/proto_socket/communicator.py:319), [communicator.py](/config/workspace/proto-socket/python/proto_socket/communicator.py:549)
|
||||
- TypeScript `nextNonce()` call sites: [communicator.ts](/config/workspace/proto-socket/typescript/src/communicator.ts:404), [communicator.ts](/config/workspace/proto-socket/typescript/src/communicator.ts:419), [communicator.ts](/config/workspace/proto-socket/typescript/src/communicator.ts:610)
|
||||
|
||||
### 분할 판단
|
||||
|
||||
- split decision policy를 먼저 평가했다.
|
||||
- 공유 task group: `agent-task/m-protocol-evolution-compatibility/`
|
||||
- `06+04,05_nonce_kotlin_python_ts`: 이 plan. predecessor `04`, `05`가 모두 필요하며 계획 작성 시점에는 active plan만 있고 `complete.log`는 없다.
|
||||
- 06번은 최종 rollout과 full matrix를 포함하므로 `Roadmap Targets`를 가진다.
|
||||
|
||||
### 범위 결정 근거
|
||||
|
||||
- 이 plan은 Kotlin/Python/TypeScript communicator와 focused tests를 수정한다.
|
||||
- Dart/Go는 05번 완료 결과를 전제로 하며 이 plan에서 다시 수정하지 않는다.
|
||||
- proto schema와 crosstest expected count는 변경하지 않는다.
|
||||
|
||||
### 빌드 등급
|
||||
|
||||
- `cloud-G07`: 세 async runtime에 같은 protocol/concurrency 정책을 적용하고 full matrix evidence까지 수집한다.
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] 04번과 05번 predecessor `complete.log`가 모두 존재하는지 확인하고, 없으면 구현을 시작하지 않고 리뷰 stub에 차단 근거를 남긴다.
|
||||
- [ ] Kotlin `Communicator.nextNonce()`가 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] Python `Communicator.next_nonce()`가 active `_pending_requests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] TypeScript `Communicator.nextNonce()`가 active `pendingRequests` 키와 충돌하는 후보 nonce를 건너뛰도록 수정하고 regression test를 추가한다.
|
||||
- [ ] `cd kotlin && ./gradlew test`, `cd python && python3 -m pytest -q`, `cd typescript && npm run check && npm test`를 실행한다.
|
||||
- [ ] `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`과 `git diff --check`를 실행한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 의존 관계 및 구현 순서
|
||||
|
||||
`06+04,05_nonce_kotlin_python_ts`는 디렉터리명 기준 predecessors `04`, `05`를 요구한다. 구현 전 다음 중 하나로 각각의 완료를 확인한다.
|
||||
|
||||
- `agent-task/m-protocol-evolution-compatibility/04+03_nonce_contract/complete.log` 또는 matching archive complete log
|
||||
- `agent-task/m-protocol-evolution-compatibility/05+04_nonce_dart_go/complete.log` 또는 matching archive complete log
|
||||
|
||||
### [API-1] Kotlin pending nonce skip
|
||||
|
||||
#### 문제
|
||||
|
||||
[Communicator.kt](/config/workspace/proto-socket/kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt:234)는 atomic counter만 보고 후보 nonce를 반환한다.
|
||||
|
||||
```kotlin
|
||||
234 internal fun nextNonce(): Int {
|
||||
235 while (true) {
|
||||
236 val current = nonce.get()
|
||||
237 val next = if (current >= MAX_NONCE) 1 else current + 1
|
||||
238 if (nonce.compareAndSet(current, next)) return next
|
||||
239 }
|
||||
240 }
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
후보를 CAS로 확보한 뒤 `rwLock.read { pendingRequests.containsKey(candidate) }`를 확인하고, pending이면 다음 후보를 찾는다. 모든 positive int32 nonce가 pending인 경우 `IllegalStateException`을 던진다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`: pending skip 구현
|
||||
- [ ] `kotlin/src/test/kotlin/com/tokilabs/proto_socket/CommunicatorTest.kt`: skip regression 추가
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`testNextNonceSkipsActivePendingAfterWrap`를 추가한다. nonce를 `Int.MAX_VALUE`, 첫 request로 pending `1`을 만든 뒤 다음 send가 nonce `2`를 발행하는지 확인한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
cd kotlin && ./gradlew test
|
||||
```
|
||||
|
||||
기대 결과: BUILD SUCCESSFUL.
|
||||
|
||||
### [API-2] Python pending nonce skip
|
||||
|
||||
#### 문제
|
||||
|
||||
[communicator.py](/config/workspace/proto-socket/python/proto_socket/communicator.py:186)는 wrap 후 `1`을 반환하지만 `_pending_requests`를 확인하지 않는다.
|
||||
|
||||
```python
|
||||
186 def next_nonce(self) -> int:
|
||||
187 if self._nonce >= MAX_NONCE:
|
||||
188 self._nonce = 0
|
||||
189 self._nonce += 1
|
||||
190 return self._nonce
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
`next_nonce()`에서 bounded loop를 사용해 candidate가 `_pending_requests`에 있으면 skip한다. asyncio 단일 event loop 내 상태 변경이므로 별도 lock은 추가하지 않는다. 후보가 없으면 `RuntimeError` 또는 `ValueError`로 실패한다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `python/proto_socket/communicator.py`: pending skip 구현
|
||||
- [ ] `python/test/test_communicator.py`: skip regression 추가
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`test_next_nonce_skips_active_pending_after_wrap`를 추가한다. `_nonce = MAX_NONCE`, 첫 `send_request`로 pending `1`을 만들고, 응답 전 `send()`를 호출해 두 번째 packet nonce가 `2`인지 확인한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
cd python && python3 -m pytest -q
|
||||
```
|
||||
|
||||
기대 결과: pytest PASS.
|
||||
|
||||
### [API-3] TypeScript pending nonce skip
|
||||
|
||||
#### 문제
|
||||
|
||||
[communicator.ts](/config/workspace/proto-socket/typescript/src/communicator.ts:284)는 wrap 후 `1`을 반환하지만 `pendingRequests`를 확인하지 않는다.
|
||||
|
||||
```ts
|
||||
284 private nextNonce(): number {
|
||||
285 if (this.nonce >= Communicator.MAX_NONCE) {
|
||||
286 this.nonce = 0;
|
||||
287 }
|
||||
288 this.nonce += 1;
|
||||
289 return this.nonce;
|
||||
290 }
|
||||
```
|
||||
|
||||
#### 해결 방법
|
||||
|
||||
`nextNonce()`에서 bounded loop를 사용해 candidate가 `pendingRequests.has(candidate)`이면 skip한다. JavaScript event loop 상태라 별도 mutex는 추가하지 않는다. 후보가 없으면 `Error`를 던지고 send/sendRequest promise가 reject되게 한다.
|
||||
|
||||
#### 수정 파일 및 체크리스트
|
||||
|
||||
- [ ] `typescript/src/communicator.ts`: pending skip 구현
|
||||
- [ ] `typescript/test/communicator.test.ts`: skip regression 추가
|
||||
|
||||
#### 테스트 작성
|
||||
|
||||
`nextNonce skips active pending request nonce after wrap`를 추가한다. private state cast로 `nonce = MAX_NONCE`, 첫 `sendRequest`로 pending `1`을 만들고 두 번째 send가 nonce `2`를 발행하는지 확인한다.
|
||||
|
||||
#### 중간 검증
|
||||
|
||||
```bash
|
||||
cd typescript && npm run check && npm test
|
||||
```
|
||||
|
||||
기대 결과: typecheck/test PASS.
|
||||
|
||||
## 수정 파일 요약
|
||||
|
||||
| 파일 | 항목 |
|
||||
|------|------|
|
||||
| `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt` | API-1 |
|
||||
| `kotlin/src/test/kotlin/com/tokilabs/proto_socket/CommunicatorTest.kt` | API-1 |
|
||||
| `python/proto_socket/communicator.py` | API-2 |
|
||||
| `python/test/test_communicator.py` | API-2 |
|
||||
| `typescript/src/communicator.ts` | API-3 |
|
||||
| `typescript/test/communicator.test.ts` | API-3 |
|
||||
|
||||
## 최종 검증
|
||||
|
||||
```bash
|
||||
cd kotlin && ./gradlew test
|
||||
cd python && python3 -m pytest -q
|
||||
cd typescript && npm run check && npm test
|
||||
bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all
|
||||
git diff --check
|
||||
```
|
||||
|
||||
기대 결과: Kotlin/Python/TypeScript focused tests PASS, full matrix PASS, whitespace error 없음.
|
||||
|
||||
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
Loading…
Reference in a new issue