<!-- task=m-inbound-queue-ordering/07_python_gateway plan=3 tag=REVIEW_REVIEW_REVIEW_API -->

# Code Review Reference - REVIEW_REVIEW_REVIEW_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.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.

## 개요

date=2026-06-02
task=m-inbound-queue-ordering/07_python_gateway, plan=3, tag=REVIEW_REVIEW_REVIEW_API

## Roadmap Targets

- Milestone: `agent-roadmap/milestones/inbound-queue-ordering.md`
- Task ids:
  - `python-gateway`: Python process/asyncio worker gateway 후보를 적용한다.
- Completion mode: check-on-pass

## 이 파일을 읽는 리뷰 에이전트에게

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [REVIEW_REVIEW_REVIEW_API-1] delayed close race test and review sync | [x] |

## 구현 체크리스트

- [x] Python test에 asyncio gateway worker yield를 지연시키는 close race 회귀 검증을 추가하거나 기존 `test_gateway_close_lifecycle_in_flight`를 강화한다.
- [x] 지연 조건에서도 close 후 `_inbound_queue.qsize() == 0`, `_receive_task.done() == True`, `_gateway_tasks` empty, listener 처리 결과가 기대와 일치함을 검증한다.
- [x] active `CODE_REVIEW-cloud-G08.md`의 구현 항목별 완료 여부와 구현 체크리스트를 이 plan의 항목 텍스트/순서와 일치시킨다.
- [x] 중간 검증으로 `cd python && python3 -m pytest -q test/test_communicator.py`를 실행한다.
- [x] 최종 검증으로 `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`을 실행한다.
- [x] `git diff --check`를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G08_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G08_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [x] PASS이면 active task 디렉터리 `agent-task/m-inbound-queue-ordering/07_python_gateway/`를 `agent-task/archive/YYYY/MM/m-inbound-queue-ordering/07_python_gateway/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [x] PASS이고 task group이 `m-inbound-queue-ordering`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-inbound-queue-ordering/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G08.md`와 `CODE_REVIEW-cloud-G08.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로 이동한다.

## 계획 대비 변경 사항

- **몽키패치를 통한 asyncio gateway sleep(0) 지연 회귀 검증 추가**: `pytest` 테스트 환경에서 `monkeypatch` 피스처를 주입하여 `proto_socket.communicator.asyncio.sleep`이 `0`초 지연을 유도할 때 강제로 50ms 동안 지연된 비동기 yield 조건(`mock_sleep`)을 발생시켰습니다. 이로써 비동기 게이트웨이 파싱/배포 태스크가 지연 중일 때 `close()`를 호출하는 임계 Concurrency Race 시나리오를 온전히 실증하고 영구적인 회귀 검증 방어막을 구축했습니다.
- **체크리스트 정합성 동기화**: `PLAN-cloud-G08.md`의 `plan=3` 계획 명세서의 순서 및 텍스트 명세와 100% 일치하도록 `CODE_REVIEW-cloud-G08.md` 의 완료 여부 테이블 및 구현 체크리스트를 완전히 동기화했습니다.

## 주요 설계 결정

1. **`monkeypatch` 기반의 Concurrency 지연 강제 재현 (`test_gateway_close_lifecycle_in_flight` 강화)**:
   - 타이밍이나 OS 퀀텀 차이에 기인하여 불규칙하게 패스할 수 있는 기본 스케줄러 한계를 확실히 우회하고자, 테스트용 로컬 후크인 `monkeypatch`를 활용하여 비동기 게이트웨이 내부의 `await asyncio.sleep(0)` 시점에 물리적인 대기(50ms)를 강제 주입했습니다.
   - 메인 스레드에서 패킷 인젝션 직후 바로 `close()`를 구동하더라도, 게이트웨이 태스크(`_process_and_enqueue`)가 `_gateway_tasks` 관리 셋에 추적되어 있는 상태에서 지연 완료를 보장하게 됨으로써, `close()` 시 gather 대기에 걸리게 유도했습니다.
   - `close()` 완료 후에는 추가 대기 없이 즉시 `qsize == 0`, `receive_task.done()`, `_gateway_tasks` 비었음, 리스너가 유실 없이 해당 패킷을 정상 배포했음을 철저히 단언(assert)하도록 하였습니다.

## 사용자 리뷰 요청

_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다._

- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음

## 리뷰어를 위한 체크포인트

- 지연 close race 테스트가 실제로 scheduler 지연 조건을 만든 뒤 close를 호출하는지 확인한다.
- active review checklist가 active plan과 일치하는지 확인한다.
- 코드 동작 변경이 불필요하게 추가되지 않았는지 확인한다.

## 검증 결과

### REVIEW_REVIEW_REVIEW_API 중간 검증
```
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0 -- /bin/python3
cachedir: .pytest_cache
rootdir: /config/workspace/proto-socket/python
configfile: pyproject.toml
plugins: asyncio-1.3.0
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None,
 asyncio_default_test_loop_scope=function
collecting ...
collected 20 items
test/test_communicator.py::test_add_listener_exclusivity
test/test_communicator.py::test_add_listener_exclusivity PASSED          [  5%]
test/test_communicator.py::test_send_and_receive PASSED                  [ 10%]
test/test_communicator.py::test_send_request_response
test/test_communicator.py::test_send_request_response PASSED             [ 15%]
test/test_communicator.py::test_nonce_wraps_after_int32_max_without_emitting_zero PASSED [ 20%]
test/test_communicator.py::test_send_request_nonce_wraps_at_int32_max
test/test_communicator.py::test_send_request_nonce_wraps_at_int32_max PASSED [ 25%]
test/test_communicator.py::test_shutdown PASSED                          [ 30%]
test/test_communicator.py::test_shutdown_public_method PASSED            [ 35%]
test/test_communicator.py::test_inbound_queue_fifo_order PASSED          [ 40%]
test/test_communicator.py::test_slow_request_handler_response_fifo
test/test_communicator.py::test_slow_request_handler_response_fifo PASSED [ 45%]
test/test_communicator.py::test_close_cancels_pending_receive
test/test_communicator.py::test_close_cancels_pending_receive PASSED     [ 50%]
test/test_communicator.py::test_inbound_backpressure_on_heavy_load
test/test_communicator.py::test_inbound_backpressure_on_heavy_load PASSED [ 55%]
test/test_communicator.py::test_graceful_close_drains_in_flight
test/test_communicator.py::test_graceful_close_drains_in_flight PASSED   [ 60%]
test/test_communicator.py::test_worker_gateway_reorder_and_dispatch
test/test_communicator.py::test_worker_gateway_reorder_and_dispatch PASSED [ 65%]
test/test_communicator.py::test_worker_gateway_asyncio_mode
test/test_communicator.py::test_worker_gateway_asyncio_mode PASSED       [ 70%]
test/test_communicator.py::test_worker_gateway_fallback_small_packet
test/test_communicator.py::test_worker_gateway_fallback_small_packet PASSED [ 75%]
test/test_communicator.py::test_worker_gateway_process_mode
test/test_communicator.py::test_worker_gateway_process_mode PASSED       [ 80%]
test/test_communicator.py::test_worker_gateway_out_of_order_completion
test/test_communicator.py::test_worker_gateway_out_of_order_completion PASSED [ 85%]
test/test_communicator.py::test_process_gateway_parse_failure_drop
test/test_communicator.py::test_process_gateway_parse_failure_drop PASSED [ 90%]
test/test_communicator.py::test_gateway_close_lifecycle_in_flight
test/test_communicator.py::test_gateway_close_lifecycle_in_flight PASSED [ 95%]
test/test_communicator.py::test_queue_full_ordering_and_close_cleanup
test/test_communicator.py::test_queue_full_ordering_and_close_cleanup PASSED [100%]
============================== 20 passed in 0.68s ==============================
```

### 최종 검증
```
RUN proto sync: tools/check_proto_sync.sh
RUN unit Dart: dart pub get && dart test && dart compile js test/browser_ws_impo
rt_compile.dart -o /tmp/proto_socket_browser_ws_import_compile.js
RUN unit Go: go test ./...
RUN unit Kotlin: ./gradlew test
RUN unit Python: python3 -m pytest -q
RUN unit TypeScript: npm run check && npm test
RUN cross Go->Dart: go run ./crosstest/go_dart.go
RUN cross Go->Kotlin: go run ./crosstest/go_kotlin.go
RUN cross Go->Python: go run ./crosstest/go_python.go
RUN cross Go->TypeScript: go run ./crosstest/go_typescript.go
RUN cross Dart->Go: dart run crosstest/dart_go.dart
RUN cross Dart->Kotlin: dart run crosstest/dart_kotlin.dart
RUN cross Dart->Python: dart run crosstest/dart_python.dart
RUN cross Dart->TypeScript: dart run crosstest/dart_typescript.dart
RUN cross Kotlin->Dart: ./gradlew run -PmainClass=com.tokilabs.proto_socket.cros
stest.KotlinDartKt
RUN cross Kotlin->Go: ./gradlew run -PmainClass=com.tokilabs.proto_socket.crosst
est.KotlinGoKt
RUN cross Kotlin->Python: ./gradlew run -PmainClass=com.tokilabs.proto_socket.cr
osstest.KotlinPythonKt
RUN cross Kotlin->TypeScript: ./gradlew run -PmainClass=com.tokilabs.proto_socke
t.crosstest.KotlinTypescriptKt
RUN cross Python->Dart: python3 crosstest/python_dart.py
RUN cross Python->Go: python3 crosstest/python_go.py
RUN cross Python->Kotlin: python3 crosstest/python_kotlin.py
RUN cross Python->TypeScript: python3 crosstest/python_typescript.py
RUN cross TypeScript->Dart: ./node_modules/.bin/tsx crosstest/typescript_dart.ts
RUN cross TypeScript->Go: ./node_modules/.bin/tsx crosstest/typescript_go.ts
RUN cross TypeScript->Kotlin: ./node_modules/.bin/tsx crosstest/typescript_kotli
n.ts
RUN cross TypeScript->Python: ./node_modules/.bin/tsx crosstest/typescript_pytho
n.ts
RUN remote web Dart.io->Dart.web: dart run crosstest/dart_web.dart
RUN remote web Go->Dart.web: go run ./crosstest/go_dart_web.go
RUN remote web Kotlin->Dart.web: ./gradlew run -PmainClass=com.tokilabs.proto_so
cket.crosstest.KotlinDartWebKt
RUN remote web Python->Dart.web: python3 crosstest/python_dart_web.py
RUN remote web TypeScript->Dart.web: ./node_modules/.bin/tsx crosstest/typescrip
t_dart_web.ts
**Proto 동기화**
| 검사 | 명령 | 결과 |
|---|---|---|
| schema sync | `tools/check_proto_sync.sh` | PASS |

**동일언어**
| 언어 | 명령 | 결과 |
|---|---|---|
| Dart | `dart pub get && dart test && dart compile js test/browser_ws_import_co
mpile.dart -o /tmp/proto_socket_browser_ws_import_compile.js` | PASS |
| Go | `go test ./...` | PASS |
| Kotlin | `./gradlew test` | PASS |
| Python | `python3 -m pytest -q` | PASS |
| TypeScript | `npm run check && npm test` | PASS |

**언어 PASS 매트릭스**
| 서버 \ 클라이언트 | Dart.io | Dart.web | Dart.web(WSS) | Go | Kotlin | Python | TypeS
cript |
|---|---|---|---|---|---|---|---|
| Dart.io | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Go | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Kotlin | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| Python | PASS | PASS | PASS | PASS | PASS | PASS | PASS |
| TypeScript | PASS | PASS | PASS | PASS | PASS | PASS | PASS |

**크로스테스트 상세**
| 방향 | 결과 | PASS scenarios | Expected | FAIL lines |
|---|---:|---:|---:|---:|
| Go -> Dart.io | PASS | 16 | 16 | 0 |
| Go -> Kotlin | PASS | 16 | 16 | 0 |
| Go -> Python | PASS | 16 | 16 | 0 |
| Go -> TypeScript | PASS | 16 | 16 | 0 |
| Dart.io -> Go | PASS | 16 | 16 | 0 |
| Dart.io -> Kotlin | PASS | 16 | 16 | 0 |
| Dart.io -> Python | PASS | 16 | 16 | 0 |
| Dart.io -> TypeScript | PASS | 16 | 16 | 0 |
| Kotlin -> Dart.io | PASS | 16 | 16 | 0 |
| Kotlin -> Go | PASS | 16 | 16 | 0 |
| Kotlin -> Python | PASS | 16 | 16 | 0 |
| Kotlin -> TypeScript | PASS | 16 | 16 | 0 |
| Python -> Dart.io | PASS | 16 | 16 | 0 |
| Python -> Go | PASS | 16 | 16 | 0 |
| Python -> Kotlin | PASS | 16 | 16 | 0 |
| Python -> TypeScript | PASS | 16 | 16 | 0 |
| TypeScript -> Dart.io | PASS | 16 | 16 | 0 |
| TypeScript -> Go | PASS | 16 | 16 | 0 |
| TypeScript -> Kotlin | PASS | 16 | 16 | 0 |
| TypeScript -> Python | PASS | 16 | 16 | 0 |
| Dart.io -> Dart.web | PASS | 2 | 2 | 0 |
| Dart.io -> Dart.web(WSS) | PASS | 2 | 2 | 0 |
| Go -> Dart.web | PASS | 2 | 2 | 0 |
| Go -> Dart.web(WSS) | PASS | 2 | 2 | 0 |
| Kotlin -> Dart.web | PASS | 2 | 2 | 0 |
| Kotlin -> Dart.web(WSS) | PASS | 2 | 2 | 0 |
| Python -> Dart.web | PASS | 2 | 2 | 0 |
| Python -> Dart.web(WSS) | PASS | 2 | 2 | 0 |
| TypeScript -> Dart.web | PASS | 2 | 2 | 0 |
| TypeScript -> Dart.web(WSS) | PASS | 2 | 2 | 0 |

로그 디렉터리: `/tmp/proto-socket-matrix.rdmeef`
결과 기록 파일: `agent-test/runs/20260602-062949-proto-socket-full-matrix.md`
```

### whitespace 검증
```
$ git diff --check
(아무런 whitespace 오류가 검출되지 않고 완전히 깨끗하게 통과되었습니다.)
```

## 코드리뷰 결과

- 종합 판정: PASS
- 차원별 평가:
  - correctness: Pass
  - completeness: Pass
  - test coverage: Pass
  - API contract: Pass
  - code quality: Pass
  - plan deviation: Pass
  - verification trust: Pass
- 발견된 문제: 없음
- 다음 단계: PASS이므로 active plan/review를 로그로 아카이브하고 `complete.log` 작성 후 task 디렉터리를 archive로 이동한다.
