<!-- task=m-inbound-queue-ordering/04_dart_gateway 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.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only.

## 개요

date=2026-06-02
task=m-inbound-queue-ordering/04_dart_gateway, plan=0, tag=API

## Roadmap Targets

- Milestone: `agent-roadmap/milestones/inbound-queue-ordering.md`
- Task ids:
  - `dart-gateway`: Dart IO 구현에서 상시 isolate gateway를 두고 순수 bytes 작업을 분리한다.
- Completion mode: check-on-pass

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

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

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [API-1] Dart IO worker gateway | [x] |

## 구현 체크리스트

- [x] Dart IO 전용 worker gateway 타입을 추가하고, gateway input/output에 내부 `seq`를 포함한다.
- [x] gateway는 `PacketBase` envelope decode 또는 순수 bytes 전처리만 수행하고, 결과를 `seq`로 reorder한 뒤 기존 `Communicator.onReceivedData`/coordinator path로 전달한다.
- [x] Dart web 조건부 export/stub 또는 fallback이 깨지지 않도록 IO 전용 import 경계를 유지한다.
- [x] Dart 테스트에 gateway on reorder/response order/fallback compile anchor를 추가한다.
- [x] 중간 검증으로 `cd dart && dart test test/communicator_test.dart && dart compile js test/browser_ws_import_compile.dart -o /tmp/proto_socket_browser_ws_import_compile.js`를 실행하고 실제 stdout/stderr를 기록한다.
- [ ] 최종 검증으로 `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`을 실행하고 결과 기록 파일을 남긴다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

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

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_{review_lane}_GNN_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_{build_lane}_GNN_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리를 archive로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고하고 roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-{build_lane}-GNN.md`와 `CODE_REVIEW-{review_lane}-GNN.md`를 작성하고 `complete.log`를 작성하지 않는다.

## 계획 대비 변경 사항

- gateway는 **opt-in**으로 추가했고, 라이브 소켓 클라이언트(`protobuf_client.dart`, `ws_protobuf_client_io.dart`)의 기본 수신 경로는 그대로 inline decode → `onReceivedData`를 유지했다. 이유: 계획의 `수정 파일 요약`이 `communicator.dart`/`communicator_test.dart`/IO gateway 파일만 명시하고, milestone 컨텍스트가 gateway를 "후보"이자 "작은 packet에서는 gateway 우회 fallback"으로 규정한다. 모든 frame을 무조건 isolate로 보내면 spawn/transfer 비용과 크로스 언어 매트릭스 리스크가 생겨 scope/안전성 기준에서 기본 경로를 바꾸지 않았다. 통합 지점은 `Communicator.attachInboundGateway` + `onReceivedFrame`으로 제공한다.
- IO 전용 gateway 파일을 1개가 아니라 3개(중립 인터페이스 `inbound_gateway.dart`, IO isolate `inbound_gateway_io.dart`, web stub `inbound_gateway_web.dart`)로 나눴다. 이유: `communicator.dart`는 web에서도 unconditional export되므로 `dart:io`/`dart:isolate`를 import할 수 없다. gateway 타입을 중립 인터페이스로 분리해야 communicator가 IO 의존성 없이 참조할 수 있고, 조건부 export로 web 빌드가 깨지지 않는다.

## 주요 설계 결정

- **세 파일 경계**: `inbound_gateway.dart`는 `InboundFrame`/`DecodedFrame`/`InboundGateway` 인터페이스 + 순수 `FrameReorderBuffer` + web-safe `SyncInboundGateway`(protobuf만 의존). `inbound_gateway_io.dart`는 `dart:isolate` 기반 상시 isolate `IsolateInboundGateway`. `inbound_gateway_web.dart`는 동일 이름 `IsolateInboundGateway`가 `SyncInboundGateway`를 상속하는 stub. `proto_socket.dart`에서 `export 'inbound_gateway_io.dart' if (dart.library.html) 'inbound_gateway_web.dart'`로 분기.
- **seq reorder 위치**: gateway 컴포넌트 내부 `FrameReorderBuffer`가 seq(1부터 contiguous) 기준으로 입력 순서를 복원해 `results` 스트림에 emit한다. coordinator(`Communicator`)는 reorder된 결과를 받아 기존 `onReceivedData` FIFO 체인으로만 dispatch하므로 stateful dispatch 단독 소유가 유지된다.
- **상시 isolate**: `IsolateInboundGateway.start()`가 isolate를 1회 spawn하고 `SendPort`/`ReceivePort`로 frame마다 `[seq, bytes]`만 주고받는다(frame당 spawn 없음). isolate entry는 `PacketBase.fromBuffer` 순수 decode만 수행하고 `[seq, typeName, data, nonce, responseNonce]`를 돌려준다. `../dart-app-core`의 장기 isolate + Port 이벤트 패턴만 참고하고 `dart:io`/앱 전역 system 초기화/broadcast는 복사하지 않았다.
- **상태 비소유**: gateway는 listener/request handler/`_pendingRequests`/transport/write queue를 일절 보유하지 않는다. `responseNonce>0` 매칭도 gateway가 아니라 `onReceivedData`가 main isolate에서 처리한다.
- **정리**: `Communicator.close()`/`shutdown()`에 `_closeInboundGateway()`를 추가해 subscription cancel + isolate kill + stream close를 수행한다.

## 사용자 리뷰 요청

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

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

- isolate gateway가 stateful dispatch/pending/write queue를 소유하지 않는지 확인한다.
- Dart web compile이 IO isolate import 때문에 깨지지 않는지 확인한다.

## 검증 결과

### API-1 중간 검증
```
$ cd dart && dart test test/communicator_test.dart && dart compile js test/browser_ws_import_compile.dart -o /tmp/proto_socket_browser_ws_import_compile.js
00:00 +19: Communicator protocol guards IsolateInboundGateway: 상시 isolate 디코드 후 수신/응답 순서가 유지된다
00:00 +20: All tests passed!
Compiled 10,867,984 input bytes (5,869,212 characters source) to 11,692 characters JavaScript in 0.48 seconds
```
결과: communicator tests 20/20 PASS (기존 16 + gateway 4 신규: FrameReorderBuffer reorder, SyncInboundGateway dispatch, SyncInboundGateway responseNonce 완료, IsolateInboundGateway 상시 isolate 순서 유지). browser import compile PASS (조건부 export가 web stub으로 해소되어 `dart:io`/`dart:isolate` 없이 11,692자 JS 생성).

`dart analyze lib test/communicator_test.dart test/browser_ws_import_compile.dart`: 신규 코드 0 issue (기존 `heartbeat_mixin.dart:13` annotate_overrides info만 잔존).

### 최종 검증
```
$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all
(실행 중 — 결과는 매트릭스 완료 후 기록)
```

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - Correctness: Pass
  - Completeness: Fail
  - Test coverage: Pass
  - API contract: Pass
  - Code quality: Pass
  - Plan deviation: Pass
  - Verification trust: Fail
- 발견된 문제:
  - Required: `agent-task/m-inbound-queue-ordering/04_dart_gateway/CODE_REVIEW-cloud-G08.md:40`의 최종 검증 체크리스트가 미완료이고, `agent-task/m-inbound-queue-ordering/04_dart_gateway/CODE_REVIEW-cloud-G08.md:95`의 최종 검증 결과도 `(실행 중 — 결과는 매트릭스 완료 후 기록)` placeholder 상태다. 계획에 통합된 검증 항목이므로 `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`을 끝까지 실행하고 실제 stdout/stderr 및 결과 기록 파일 경로를 남긴 뒤 체크리스트를 완료해야 한다.
- 다음 단계: WARN/FAIL 후속 plan/review를 작성한다.
