diff --git a/agent-roadmap/milestones/protocol-evolution-compatibility.md b/agent-roadmap/milestones/protocol-evolution-compatibility.md index 9b0778c..c1a1dde 100644 --- a/agent-roadmap/milestones/protocol-evolution-compatibility.md +++ b/agent-roadmap/milestones/protocol-evolution-compatibility.md @@ -18,25 +18,29 @@ ## 확정된 결정 -- package 이름은 dot-separated lowercase로 강제한다. +- package 이름은 lowercase snake_case segment를 dot으로 연결한 형태로 강제한다. +- Canonical proto package 문자열은 `proto_socket`으로 둔다. - wire `typeName`은 canonical proto package를 포함한 `.` full proto name으로 둔다. +- built-in/common message의 canonical wire identity는 `proto_socket.PacketBase`, `proto_socket.HeartBeat`, `proto_socket.TestData` 형태다. - descriptor/native metadata에서 full name을 얻을 수 있는 언어는 해당 값을 우선 사용한다. - TypeScript는 현재 수동 codec 구조를 유지하고, `MessageType.typeName` static metadata를 full proto name으로 정렬한다. - 기존 simple name wire value는 송신 기본값으로 유지하지 않고, legacy receive alias로만 보존한다. +- 이 마일스톤의 구현 완료 범위는 현재 사용 가능 구현체인 Dart, Go, Kotlin, Python, TypeScript로 둔다. C#과 Swift는 이후 포팅 시 동일 규칙을 따라야 하는 승계 대상이다. ## 구현 잠금 -- 상태: 잠금 -- 결정 필요: - - [ ] Canonical proto package의 정확한 문자열을 확정한다. 현재 canonical `proto/message_common.proto`에는 `package` 선언이 없으므로, 예: `proto_socket` 또는 `tokilabs.proto_socket` 중 어느 값을 wire identity 기준으로 삼을지 결정한다. +- 상태: 해제 +- 결정 필요: 없음 ## 범위 - `typeName` canonical 값을 proto full name으로 정렬한다. -- Go, Kotlin, Dart, Python, C#, Swift는 가능한 경우 protobuf descriptor/native metadata에서 full name을 얻는다. +- Canonical `proto/message_common.proto`에 `package proto_socket;`을 추가하고, 언어별 proto copy와 generated binding을 동기화한다. +- Go, Kotlin, Dart, Python은 가능한 경우 protobuf descriptor/native metadata에서 full name을 얻는다. - TypeScript는 현재 수동 codec의 `MessageType.typeName` static metadata를 full name으로 정렬한다. -- 기존 simple name 기반 소비자를 위해 수신 parser map에는 full name과 legacy simple name alias를 함께 등록한다. -- `PacketBase` wire field 구조는 유지하고, 필요한 확장은 새 optional message 또는 capability convention으로 검토한다. +- 기존 simple name 기반 소비자를 위해 수신 type registry에는 full name과 legacy simple name alias를 함께 등록한다. +- alias는 parser lookup뿐 아니라 listener/request handler routing, response type matching, pending request expected type 비교까지 동일하게 적용한다. +- `PacketBase` wire field 구조는 유지하고, 필요한 확장은 새 optional message 또는 capability convention으로 설계한다. - 표준 오류 응답, nonce overflow 경계, receive ordering/backpressure 문서와 테스트를 보강한다. ## 기능 @@ -45,18 +49,19 @@ wire message identity를 full proto name으로 정렬하고, legacy simple name 수신 호환성을 유지한다. -- [ ] [pkg-rule] Proto package naming rule을 문서화한다. package는 dot-separated lowercase만 허용하고, 언어별 namespace/package option은 wire identity와 분리한다. -- [ ] [fullname-type] 각 언어의 `typeNameOf()` 또는 message metadata를 full proto name 기준으로 정렬한다. descriptor/native metadata를 우선 사용하고, TypeScript는 static metadata를 사용한다. -- [ ] [legacy-alias] 수신 parser map에 full name과 simple name alias를 함께 등록하되, simple alias 충돌 시 초기화 실패로 처리한다. -- [ ] [fullname-tests] full name 송수신, simple name legacy 수신, alias 충돌 감지에 대한 동일 언어 및 크로스 언어 테스트를 추가한다. 검증: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all` +- [ ] [pkg-rule] Proto package naming rule을 `PROTOCOL.md`, `VERSIONING.md`, `PORTING_GUIDE.md`에 문서화한다. package는 lowercase snake_case segment를 dot으로 연결한 형태만 허용하고, 언어별 namespace/package option은 wire identity와 분리한다. common proto의 package는 `proto_socket`으로 둔다. +- [ ] [proto-package-sync] Canonical `proto/message_common.proto`에 `package proto_socket;`을 추가하고 언어별 proto copy와 generated binding을 동기화한다. 검증: `tools/check_proto_sync.sh` +- [ ] [fullname-type] 각 사용 가능 언어의 `typeNameOf()` 또는 message metadata를 full proto name 기준으로 정렬한다. descriptor/native metadata를 우선 사용하되, Python은 `DESCRIPTOR.full_name`, TypeScript는 static metadata를 사용한다. common proto의 기대값은 `proto_socket.`이다. +- [ ] [legacy-alias] 수신 type registry에 full name과 simple name alias를 함께 등록하되, parser lookup, listener/request handler routing, response type matching, pending expected type 비교가 같은 alias 규칙을 사용하게 한다. simple alias 충돌 시 초기화 실패로 처리한다. +- [ ] [fullname-tests] full name 송수신, simple name legacy 수신, request/response alias 호환, alias 충돌 감지에 대한 동일 언어 및 크로스 언어 테스트를 추가한다. 검증: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all` ### Epic: [evolution] 진화 안전장치 현재 `PacketBase`의 단순성을 유지하면서, future protocol capability를 안전하게 추가할 수 있는 경계를 만든다. -- [ ] [hello-cap] `ProtoSocketHello` 또는 동등한 비차단 capability message 후보를 설계한다. 구버전 peer가 모르면 무시할 수 있는 경로로 둔다. -- [ ] [std-error] `ProtoSocketError` 또는 동등한 표준 오류 응답 convention을 설계한다. request handler 실패가 timeout만으로 보이지 않게 하되, 구버전 peer와의 mismatch 처리를 문서화한다. -- [ ] [nonce-boundary] nonce wrap 시 pending request nonce와 충돌하지 않도록 경계 정책과 테스트를 보강한다. +- [ ] [hello-cap] `ProtoSocketHello` 또는 동등한 비차단 capability message 후보를 문서화한다. 구버전 peer가 모르면 무시할 수 있는 경로로 두고, 이 마일스톤에서 필수 handshake로 승격하지 않는다. +- [ ] [std-error] `ProtoSocketError` 또는 동등한 표준 오류 응답 convention을 문서화한다. 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 보장과 구분한다. ## 완료 리뷰 @@ -75,12 +80,13 @@ wire message identity를 full proto name으로 정렬하고, legacy simple name - 기존 `PacketBase` 필드를 제거하거나 번호를 바꾸지 않는다. - full name 송신 기본값 전환 전에 legacy simple name 수신 호환성을 제거하지 않는다. - TypeScript에 full protobuf reflection runtime을 강제 도입하지 않는다. +- C#과 Swift 포트를 이 Milestone의 완료 조건으로 삼지 않는다. - package registry 릴리즈 정책을 이 Milestone에서 확정하지 않는다. ## 작업 컨텍스트 -- 관련 경로: `PROTOCOL.md`, `VERSIONING.md`, `PORTING_GUIDE.md`, `proto/message_common.proto`, `dart/lib/src/communicator.dart`, `go/communicator.go`, `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`, `python/proto_socket/communicator.py`, `typescript/src/packets/message_common_pb.ts`, `tools/` +- 관련 경로: `PROTOCOL.md`, `VERSIONING.md`, `PORTING_GUIDE.md`, `proto/message_common.proto`, `dart/lib/src/communicator.dart`, `go/communicator.go`, `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`, `python/proto_socket/communicator.py`, `typescript/src/communicator.ts`, `typescript/src/packets/message_common_pb.ts`, `tools/` - 표준선(선택): native descriptor/full name 추출을 우선하고, descriptor가 없는 런타임만 static metadata fallback을 쓴다. 기존 simple name wire value는 legacy receive alias로 유지한다. - 선행 작업: 프로토콜 기준선 - 후속 작업: 필요 시 protocol `0.2` 또는 `1.0` compatibility release planning -- 확인 필요: Canonical proto package 문자열 +- 확인 필요: 없음