<!-- task=m-gito-branch-event-creation-sync-bridge/01_event_client plan=0 tag=GITO_EVENT_CLIENT -->

# Plan: Gito Branch Event Client

## 메타
- Milestone: `gito-branch-event-creation-sync-bridge`
- Build grade: cloud-G07
- Mode: implementation
- Scope: Core가 Gito proto-socket `branch.updated` 이벤트를 소비할 수 있는 계약/클라이언트/필터 계층을 추가한다.

## Roadmap Targets
- `agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/gito-branch-event-creation-sync-bridge.md`
- Task IDs:
  - `[contract-consume]`
  - `[core-client]`
  - `[branch-filter]`
- Completion mode: check-on-pass

## 문제 요약
현재 `Milestone Work Item Creation Sync` 구현은 `EnqueueRoadmapCreationSync` 이후의 worker/orchestrator 경로는 존재하지만, Gito `branch.updated` 이벤트를 Core가 받아 enqueue 후보로 넘기는 백엔드 소비자가 없다.

확인된 코드 레벨 근거:
- [services/core/internal/config/config.go](/config/workspace/nomadcode/services/core/internal/config/config.go:8): Core 설정에 Gito proto-socket endpoint/repo/branch consumer 설정이 없다.
- [services/core/internal/scheduler/roadmap_sync_jobs.go](/config/workspace/nomadcode/services/core/internal/scheduler/roadmap_sync_jobs.go:18): creation sync job은 내부 develop-scan handoff가 enqueue한다고 가정하지만, 해당 handoff의 Gito 이벤트 입력이 없다.
- [packages/contracts/notes/flutter-core-api-candidates.md](/config/workspace/nomadcode/packages/contracts/notes/flutter-core-api-candidates.md:164): 현재 문서는 Flutter client wakeup 소비를 설명하며, Core backend bridge와 Plane/roadmap mutation 책임을 분리해 적어야 한다.

## 관련 계약
- Provider: `/config/workspace/gito/agent-contract/provided/gito-forgejo-branch-events-v1.md`
- Consumed protocol:
  - `event.subscribe`
  - `branch.updated`
  - filter: `repo_id`, `branch`
  - `changed_files`는 wakeup 힌트이며, 실제 target branch revision 검증은 후속 브리지에서 수행한다.

## 구현 계획

### 1. 계약 소비 메모 보강
- [packages/contracts/notes/flutter-core-api-candidates.md](/config/workspace/nomadcode/packages/contracts/notes/flutter-core-api-candidates.md:164)에 Core backend consumer 메모를 추가한다.
- 기존 Flutter client wakeup 설명은 유지한다.
- Core backend bridge는 다음을 명시한다.
  - Gito 제공 계약 `gito.forgejo-branch-events.v1` 소비.
  - `branch.updated`는 enqueue wakeup으로만 사용.
  - `changed_files` 자체를 신뢰해 동기화하지 않고 target branch revision 확인은 backend bridge 책임.

### 2. Core 이벤트 DTO/파서 추가
- 새 패키지 후보: `services/core/internal/gitoevents`
- `events.go`
  - `SubscribeRequest`
  - `ChangedFile`
  - `BranchUpdatedEvent`
  - `BuildSubscribeEnvelope(repoID, branch string) protosocket.Envelope`
  - `DecodeBranchUpdatedEnvelope(env protosocket.Envelope) (BranchUpdatedEvent, error)`
  - `IsTarget(repoID, branch string) bool`
  - `MilestoneChangedFiles() []ChangedFile`
- 기존 [services/core/internal/protosocket/envelope.go](/config/workspace/nomadcode/services/core/internal/protosocket/envelope.go:8)의 `Envelope`와 `ProtocolVersion`을 사용한다.

### 3. Core proto-socket event client seam 추가
- `client.go`
  - `Transport` interface: connect/read/write/close를 테스트 가능하게 분리.
  - `Runner` 또는 `Client`: 시작 시 `event.subscribe` 전송, 이후 `branch.updated` envelope를 handler로 전달.
  - wrong channel/action, wrong repo/branch, malformed payload는 handler로 넘기지 않고 관찰 가능한 error/log path로 처리.
- production transport는 이미 의존 중인 `nhooyr.io/websocket`과 `git.toki-labs.com/toki/proto-socket/go` 계열을 우선 검토한다. 새 의존성은 추가하지 않는다.

### 4. 설정 추가
- [services/core/internal/config/config.go](/config/workspace/nomadcode/services/core/internal/config/config.go:8)
  - `GitoProtoSocketURL`
  - `GitoRepoID`
  - `GitoBranch`
  - `GitoBranchEventsEnabled` 또는 endpoint 기반 enable 판정
- 기본값:
  - endpoint empty이면 disabled.
  - branch는 비어 있으면 `develop`.
  - repo id는 명시 설정 없이는 subscribe하지 않는다.

### 5. 테스트
- `services/core/internal/gitoevents/events_test.go`
  - Gito 계약 fixture로 `event.subscribe` payload 검증.
  - `branch.updated` fixture parse 검증.
  - wrong action/channel reject.
  - wrong repo/branch reject.
  - milestone markdown path filter 검증.
- `services/core/internal/gitoevents/client_test.go`
  - fake transport가 subscribe envelope를 받는지 검증.
  - fake event stream이 handler로 `BranchUpdatedEvent`를 전달하는지 검증.
- `services/core/internal/config/config_test.go`
  - env load/default/disabled 동작 검증.

## 완료 조건
- Core 내부에 Gito branch event client와 parser가 있고, 후속 enqueue bridge가 typed event를 받을 수 있다.
- Core 설정으로 endpoint/repo/branch를 제어할 수 있다.
- Flutter client wakeup 문서와 Core backend bridge 책임이 계약 메모에서 구분된다.
- 아래 검증이 통과한다.
  - `cd services/core && go test -count=1 ./internal/gitoevents ./internal/config ./internal/protosocket`
  - `cd services/core && go test -count=1 ./...`
  - `cd services/core && go vet ./...`
  - `git diff --check`

## 구현 후 사용자 리뷰 요청

아래 내용을 포함해 사용자 리뷰를 요청한다.

```markdown
## 사용자 리뷰 요청

- 구현 요약:
  - Core Gito branch event client/DTO/filter 계층 추가
  - Gito 제공 계약 소비 메모 보강
  - 설정 및 테스트 추가
- 확인 요청:
  - Gito endpoint/repo_id/branch 설정명이 운영 환경에 맞는지
  - `branch.updated`를 wakeup-only로 소비하고 revision 검증을 후속 bridge에서 수행하는 분리가 맞는지
```
