nomadcode/agent-task/m-proto-socket-infrastructure-communication-rail/02+01_task_service/PLAN-cloud-G06.md
toki 88674917de feat: proto socket infrastructure communication rail implementation
- Add proto socket client and envelope implementations
- Add proto socket lifecycle integration tests
- Add task service PLAN and CODE_REVIEW documents
- Add workspace integration PLAN and CODE_REVIEW documents
- Update bootstrap with proto socket integration
- Update pubspec dependencies and lock file
- Update Flutter core API candidates documentation
- Update workflow core milestone tracking
2026-05-30 21:12:37 +09:00

9.8 KiB

Plan - API Proto-Socket Task Service

이 파일을 읽는 구현 에이전트에게

이 plan의 구현이 끝나면 active CODE_REVIEW-*-G??.md에서 구현 에이전트 소유 섹션을 실제 구현 내용, 검증 출력, 계획 대비 변경 사항으로 채워야 한다. 최종 archive, complete.log, 리뷰 판정은 code-review-skill 전용이다. 구현 중 사용자만 결정할 수 있는 범위 변경, 사용자 소유 외부 환경/secret 준비, 또는 안전한 진행을 막는 scope 충돌이 있으면 review stub의 사용자 리뷰 요청 섹션에 정확한 결정과 근거를 남기고 멈춘다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 메울 수 있는 검증 공백만으로는 사용자 리뷰 요청을 만들지 않는다.

배경

Core task channel은 task.create, task.list, task.get, task.enqueue, task.status.changed를 proto-socket envelope로 제공한다. Flutter client는 transport가 생긴 뒤에도 task 도메인 모델과 request parsing 경계가 없으면 화면에서 mock data를 대체할 수 없다. 이 작업은 UI를 바꾸지 않고 client service 경계만 만든다.

사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 사용자 리뷰 요청 섹션에 기록한다. code-review가 해당 요청을 검증하고 실제 USER_REVIEW.md 작성 여부를 결정한다.

분석 결과

읽은 파일

  • agent-roadmap/current.md
  • agent-roadmap/phase/workflow-core/PHASE.md
  • agent-roadmap/phase/workflow-core/milestones/proto-socket-infrastructure-communication-rail.md
  • agent-ops/rules/project/domain/mobile/rules.md
  • agent-test/local/mobile-smoke.md
  • apps/client/lib/src/integrations/proto_socket/proto_socket_lifecycle.dart
  • apps/client/lib/src/features/workspaces/domain/project_workspace.dart
  • apps/client/lib/src/features/workspaces/presentation/workspace_home_page.dart
  • apps/client/test/widget_test.dart
  • packages/contracts/notes/flutter-core-api-candidates.md
  • services/core/internal/protosocket/tasks.go

테스트 커버리지 공백

  • No existing Flutter test covers task channel request creation.
  • No existing Flutter test covers Core error envelope mapping to a client exception.
  • Widget tests use mockProjectWorkspaces only; they do not exercise task service consumption.

심볼 참조

  • No renamed or removed symbols planned.
  • New service should depend on the ProtoSocketTransport produced by 01_client_transport.

분할 판단

Split policy was evaluated before writing files. This subtask depends on 01_client_transport because it needs ProtoSocketEnvelope and ProtoSocketTransport. UI integration remains in 03+02_workspace_integration so service parsing can be reviewed independently.

범위 결정 근거

This task does not change WorkspaceHomePage rendering or app bootstrap. It does not create Core APIs, new REST endpoints, or persistence. It only creates a Flutter task channel client and tests using fake transport envelopes.

빌드 등급

Build lane cloud-G06, review lane cloud-G06: protocol response parsing and error mapping with moderate blast radius, but no UI or platform runner changes.

구현 체크리스트

  • [API-1] Add client task models matching the implemented Core task channel response shape.
  • [API-2] Add ProtoSocketTaskService that calls task.list, task.get, task.enqueue, and optional task.create through ProtoSocketTransport.
  • [API-3] Add task channel service tests for success, missing payload, and error envelope mapping.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

[API-1] Task Models

문제

The workspace domain model only has ProjectWorkspace and a mock count at apps/client/lib/src/features/workspaces/domain/project_workspace.dart:3-18. The Core task channel returns full task maps described in packages/contracts/notes/flutter-core-api-candidates.md:97-108.

해결 방법

Add apps/client/lib/src/features/workspaces/domain/workspace_task.dart.

Before (apps/client/lib/src/features/workspaces/domain/project_workspace.dart:3-18):

class ProjectWorkspace {
  final String id;
  final String name;
  final String description;
  final ProjectStatus status;
  final String codeServerUrl;
  final int tasksCount;
}

After:

class WorkspaceTask {
  final String id;
  final String title;
  final String status;
  final String source;
  final String? error;

  const WorkspaceTask({
    required this.id,
    required this.title,
    required this.status,
    required this.source,
    this.error,
  });

  factory WorkspaceTask.fromMap(Map<String, Object?> map) {
    return WorkspaceTask(
      id: map['id'] as String? ?? '',
      title: map['title'] as String? ?? 'Untitled task',
      status: map['status'] as String? ?? 'unknown',
      source: map['source'] as String? ?? '',
      error: map['error'] as String?,
    );
  }
}

수정 파일 및 체크리스트

  • Add apps/client/lib/src/features/workspaces/domain/workspace_task.dart.
  • Keep model tolerant of missing optional fields returned by partial task maps.

테스트 작성

Cover WorkspaceTask.fromMap in the service test file, using a full map and a minimal map.

중간 검증

cd apps/client && flutter test test/integrations/proto_socket_task_service_test.dart

Expected: task model tests pass.

[API-2] Task Channel Service

문제

Core registers task actions at services/core/internal/protosocket/tasks.go:32-36, but Flutter has no client API for sending those actions through the transport.

해결 방법

Add apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart.

Before (services/core/internal/protosocket/tasks.go:32-36):

dispatcher.Register("task.create", c.handleCreate)
dispatcher.Register("task.list", c.handleList)
dispatcher.Register("task.get", c.handleGet)
dispatcher.Register("task.enqueue", c.handleEnqueue)

After:

class ProtoSocketTaskService {
  final ProtoSocketTransport _transport;

  ProtoSocketTaskService(this._transport);

  Future<List<WorkspaceTask>> listTasks({int limit = 20}) async {
    final response = await _transport.sendRequest(
      ProtoSocketEnvelope(
        id: _newMessageId(),
        type: 'request',
        channel: 'task',
        action: 'task.list',
        payload: {'limit': limit},
      ),
    );
    _throwIfError(response);
    final rawTasks = response.payload['tasks'];
    if (rawTasks is! List) return const [];
    return rawTasks
        .whereType<Map>()
        .map((item) => WorkspaceTask.fromMap(Map<String, Object?>.from(item)))
        .toList(growable: false);
  }
}

Also add getTask, enqueueTask, and createTask only if their signatures stay thin wrappers around the implemented Core actions. Do not invent workspace/project metadata APIs.

수정 파일 및 체크리스트

  • Add apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart.
  • Add ProtoSocketTaskException with code, message, and retryable.
  • Use the Core action names exactly: task.list, task.get, task.enqueue, task.create.

테스트 작성

Write fake transport tests for:

  • listTasks sends {limit} and parses tasks.
  • enqueueTask returns the updated task from payload.task.
  • error envelope task.not_found throws ProtoSocketTaskException.
  • malformed success payload returns empty list or throws a service exception consistently; choose one and document in test name.

중간 검증

cd apps/client && flutter test test/integrations/proto_socket_task_service_test.dart

Expected: all task service tests pass.

[API-3] Service Test Coverage

문제

Without service-level tests, later UI work could silently depend on mock data or incorrectly shaped envelopes.

해결 방법

Add apps/client/test/integrations/proto_socket_task_service_test.dart with a fake ProtoSocketTransport that records requests and returns queued ProtoSocketEnvelope responses. Do not use network sockets.

수정 파일 및 체크리스트

  • Add fake transport fixture.
  • Assert outgoing envelope type, channel, action, and payload.
  • Assert error envelope mapping includes retryable.

테스트 작성

This item is the test implementation for API-1 and API-2.

중간 검증

cd apps/client && flutter test test/integrations/proto_socket_task_service_test.dart

Expected: all task service tests pass.

의존 관계 및 구현 순서

Directory dependency 02+01_task_service means implementation must start only after agent-task/m-proto-socket-infrastructure-communication-rail/01_client_transport/complete.log exists.

수정 파일 요약

파일 항목
apps/client/lib/src/features/workspaces/domain/workspace_task.dart API-1
apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart API-2
apps/client/test/integrations/proto_socket_task_service_test.dart API-1, API-2, API-3

최종 검증

test -f agent-task/m-proto-socket-infrastructure-communication-rail/01_client_transport/complete.log
cd apps/client && flutter test test/integrations/proto_socket_task_service_test.dart
cd apps/client && flutter analyze --no-fatal-infos

Expected: predecessor complete.log exists; task service tests pass; analyzer has no fatal issues. Cached Flutter test output is acceptable only if no implementation files changed after the run.

모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.