nomadcode/agent-task/m-proto-socket-infrastructure-communication-rail/13+11,12_client_diagnostics/PLAN-cloud-G07.md

14 KiB

Plan - API Client Proto-Socket Diagnostics

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

CODE_REVIEW-cloud-G07.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 반드시 채운다. 구현 후 검증을 실행하고 active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 최종 판정, log rename, complete.log, archive 이동은 code-review-skill 전용이다. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌로 막히면 review stub의 사용자 리뷰 요청 섹션에 정확한 근거와 재개 조건을 채우고 멈춘다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.

배경

마일스톤의 마지막 남은 기능 Task는 connection id, protocol version, channel name, error code를 로그와 디버그 표면에서 확인 가능하게 하는 것이다. Core가 diagnostics meta를 보내면 Flutter client는 연결 상태와 최근 channel/error 정보를 비밀 없이 보여줘야 한다. 이 subtask는 contracts와 core diagnostics가 완료된 뒤 client lifecycle, task service, workspace 화면, Flutter tests를 닫는다.

사용자 리뷰 요청 흐름

구현 중 차단 사유는 active review stub의 사용자 리뷰 요청 섹션에 기록한다. 이 섹션은 agent-ops/skills/common/_templates/implementation-user-review-request-section.md를 기준으로 하며, code-review가 검증 후 실제 USER_REVIEW.md 작성 여부를 결정한다.

Roadmap Targets

  • Milestone: agent-roadmap/phase/workflow-core/milestones/proto-socket-infrastructure-communication-rail.md
  • Task ids:
    • diagnostics: connection id, protocol version, channel name, error code를 로그와 디버그 표면에서 확인할 수 있게 한다.
  • Completion mode: check-on-pass

분석 결과

읽은 파일

  • agent-ops/rules/project/rules.md
  • agent-ops/rules/private/rules.md
  • agent-ops/rules/common/rules-roadmap.md
  • agent-ops/skills/common/router.md
  • agent-ops/skills/common/plan/SKILL.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-ops/rules/project/domain/core/rules.md
  • agent-ops/rules/project/domain/contracts/rules.md
  • agent-test/local/rules.md
  • agent-test/local/mobile-smoke.md
  • agent-test/local/core-smoke.md
  • agent-test/local/contracts-smoke.md
  • apps/client/pubspec.yaml
  • apps/client/analysis_options.yaml
  • apps/client/lib/src/app/bootstrap.dart
  • apps/client/lib/src/app/nomadcode_client_app.dart
  • apps/client/lib/src/integrations/proto_socket/proto_socket_client.dart
  • apps/client/lib/src/integrations/proto_socket/proto_socket_endpoint_config.dart
  • apps/client/lib/src/integrations/proto_socket/proto_socket_envelope.dart
  • apps/client/lib/src/integrations/proto_socket/proto_socket_lifecycle.dart
  • apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart
  • apps/client/lib/src/features/workspaces/domain/project_workspace.dart
  • apps/client/lib/src/features/workspaces/domain/workspace_task.dart
  • apps/client/lib/src/features/workspaces/presentation/workspace_home_page.dart
  • apps/client/test/integrations/proto_socket_endpoint_config_test.dart
  • apps/client/test/integrations/proto_socket_envelope_test.dart
  • apps/client/test/integrations/proto_socket_lifecycle_test.dart
  • apps/client/test/integrations/proto_socket_task_service_test.dart
  • apps/client/test/widget_test.dart
  • packages/contracts/notes/flutter-core-api-candidates.md
  • services/core/internal/protosocket/server.go
  • services/core/internal/protosocket/events.go
  • services/core/internal/protosocket/tasks_test.go

테스트 환경 규칙

test_env=local로 판단했고 agent-test/local/rules.md를 읽었다. 이 파일은 로컬 테스트 금지를 명시하므로 현 세션에서는 검증 명령을 실행하지 않는다. 적용 profile은 mobile-smoke이며 mobile 변경의 필수 검증은 cd apps/client && flutter test, analyzer 영향이 있으므로 cd apps/client && flutter analyze --no-fatal-infos도 필요하다. apps/client../../../proto-socket/dart../../../nexo/packages/messaging_flutter path dependency가 있어 후속 환경에 sibling workspace가 필요하다.

테스트 커버리지 공백

  • lifecycle diagnostics stream/snapshot: 기존 proto_socket_lifecycle_test.dart는 state와 lastError만 검증한다. diagnostics snapshot 테스트 추가 필요.
  • task response/error diagnostics capture: 기존 proto_socket_task_service_test.dart는 error mapping만 검증한다. response meta/error code를 diagnostics sink에 기록하는 테스트 추가 필요.
  • UI debug surface: 기존 widget_test.dart는 service task rendering과 connection lifecycle만 검증한다. connection id/protocol/channel/error code display 테스트 추가 필요.

심볼 참조

none. 기존 public symbol rename/remove 없이 optional diagnostics API를 추가한다.

분할 판단

split decision policy를 평가했다. 이 subtask는 13+11,12_client_diagnostics이며 predecessor는 11_contracts_diagnostics, 12+11_core_diagnostics다. 현재 두 predecessor 모두 아직 complete.log가 없으므로 구현은 둘 다 PASS된 뒤 시작해야 한다.

범위 결정 근거

Flutter client diagnostics, debug surface, Flutter tests만 수정한다. Core response/event meta 구현은 12+11_core_diagnostics 범위다. Project Workspace Management UX 전체 완성, workspace metadata API, external provider integration, Mattermost push native 로직은 범위에서 제외한다.

빌드 등급

cloud-G07: client lifecycle, service boundary, UI rendering, protocol diagnostics를 함께 다루고 predecessor output에 의존하므로 cloud lane이 적합하다.

구현 체크리스트

  • 11_contracts_diagnostics12+11_core_diagnostics가 PASS되어 각 complete.log가 생겼는지 확인하고 경로를 review stub에 기록한다.
  • ProtoSocketLifecycle 또는 dedicated diagnostics controller가 connection state, connection id, protocol version, recent channel/action/error code를 비밀 없이 유지하게 한다.
  • ProtoSocketTaskService가 response/error envelope meta를 diagnostics sink에 전달하고 기존 error mapping을 유지한다.
  • WorkspaceHomePage 또는 app shell에 compact debug surface를 추가해 connection id, protocol version, channel, error code를 확인할 수 있게 한다.
  • Flutter tests로 endpoint 설정, reconnect/failure lifecycle, task service diagnostics, widget debug surface를 검증한다.
  • cd apps/client && flutter test를 허용된 원격/검증 환경에서 실행한다.
  • cd apps/client && flutter analyze --no-fatal-infos를 허용된 원격/검증 환경에서 실행한다.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

의존 관계 및 구현 순서

이 directory name은 13+11,12_client_diagnostics이므로 predecessor는 같은 task group의 11_*, 12+11_* subtasks다. agent-task/m-proto-socket-infrastructure-communication-rail/11_contracts_diagnostics/complete.logagent-task/m-proto-socket-infrastructure-communication-rail/12+11_core_diagnostics/complete.log 또는 matching archive complete.log가 모두 생긴 뒤 구현을 시작한다.

[API-1] Client Diagnostics State

문제

apps/client/lib/src/integrations/proto_socket/proto_socket_lifecycle.dart는 state와 lastError만 보관하고, connection id/protocol/channel/error code를 소비할 diagnostics state가 없다. apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart는 response/error envelope를 받은 뒤 diagnostics sink에 전달하지 않는다.

Before:

31	class ProtoSocketLifecycle {
32	  final ProtoSocketConnector _connector;
33	  final StreamController<ProtoSocketConnectionState> _stateController =
34	      StreamController<ProtoSocketConnectionState>.broadcast();
...
43	  ProtoSocketConnectionState get state => _state;
44	  Stream<ProtoSocketConnectionState> get stateStream => _stateController.stream;
45	  Object? get lastError => _lastError;
46	  ProtoSocketTransport? get transport => _transport;

해결 방법

작은 value object를 추가한다. 새 파일을 만들 경우 apps/client/lib/src/integrations/proto_socket/proto_socket_diagnostics.dart에 두고, lifecycle은 diagnostics getter와 broadcast stream을 제공한다. Task service에는 optional void Function(ProtoSocketEnvelope envelope) onEnvelope 또는 diagnostics sink를 주입해 response/error meta를 기록한다.

After:

class ProtoSocketDiagnostics {
  final ProtoSocketConnectionState state;
  final String? connectionId;
  final String? protocolVersion;
  final String? channel;
  final String? action;
  final String? errorCode;
}

Stream<ProtoSocketDiagnostics> get diagnosticsStream => _diagnosticsController.stream;
void recordEnvelope(ProtoSocketEnvelope envelope) { ... }

수정 파일 및 체크리스트

  • apps/client/lib/src/integrations/proto_socket/proto_socket_diagnostics.dart: diagnostics value/sanitizer 추가.
  • apps/client/lib/src/integrations/proto_socket/proto_socket_lifecycle.dart: diagnostics state/stream/recording 추가.
  • apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart: response/error envelope를 diagnostics sink에 전달.
  • apps/client/test/integrations/proto_socket_lifecycle_test.dart: state/failure/envelope diagnostics 테스트 추가.
  • apps/client/test/integrations/proto_socket_task_service_test.dart: meta/error code recording 테스트 추가.

테스트 작성

proto_socket_lifecycle_test.dart는 connect/fail/disconnect 시 diagnostics state가 바뀌는지 검증한다. proto_socket_task_service_test.dart는 response meta의 connection_id, protocol_version, channel, action과 error envelope의 error.code가 sink에 전달되는지 검증한다.

중간 검증

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

기대 결과: 관련 Flutter tests PASS. 명령은 허용된 원격/검증 환경에서 실행한다.

[API-2] Workspace Debug Surface

문제

apps/client/lib/src/app/nomadcode_client_app.dart는 task service만 page에 연결하고 diagnostics는 전달하지 않는다. apps/client/lib/src/features/workspaces/presentation/workspace_home_page.dart는 task section과 error UI만 있고 connection diagnostics surface가 없다.

Before:

121	      final taskService = ProtoSocketTaskService(transport);
122	      setState(() {
123	        _taskLoader = (_) => taskService.listTasks();
124	        _connectedByThisWidget = startedHere;
125	      });

해결 방법

App state가 lifecycle diagnostics stream을 구독해 WorkspaceHomePage에 snapshot을 넘긴다. Workspace details 상단 또는 ACTIVE TASKS 근처에 compact diagnostics row를 추가한다. 화면에는 connected/failed, conn-*, protocol version, recent channel/action, optional error_code만 표시하고 payload/auth/error message 원문은 표시하지 않는다.

After:

_diagnosticsSub = lifecycle.diagnosticsStream.listen((next) {
  if (mounted) setState(() => _protoSocketDiagnostics = next);
});

return WorkspaceHomePage(
  loadTasks: _taskLoader,
  protoSocketDiagnostics: _protoSocketDiagnostics,
);

수정 파일 및 체크리스트

  • apps/client/lib/src/app/nomadcode_client_app.dart: diagnostics stream 구독/해제와 page 전달 추가.
  • apps/client/lib/src/features/workspaces/presentation/workspace_home_page.dart: compact debug surface 추가.
  • apps/client/test/widget_test.dart: connected diagnostics와 error code surface 테스트 추가.

테스트 작성

widget_test.dart에 lifecycle diagnostics fake 또는 direct diagnostics prop을 사용해 connection id/protocol/channel/error code가 보이고 secret/payload text는 보이지 않는지 검증한다.

중간 검증

cd apps/client && flutter test test/widget_test.dart

기대 결과: widget tests PASS. 명령은 허용된 원격/검증 환경에서 실행한다.

수정 파일 요약

파일 항목
apps/client/lib/src/integrations/proto_socket/proto_socket_diagnostics.dart API-1
apps/client/lib/src/integrations/proto_socket/proto_socket_lifecycle.dart API-1
apps/client/lib/src/integrations/proto_socket/proto_socket_task_service.dart API-1
apps/client/lib/src/app/nomadcode_client_app.dart API-2
apps/client/lib/src/features/workspaces/presentation/workspace_home_page.dart API-2
apps/client/test/integrations/proto_socket_lifecycle_test.dart API-1
apps/client/test/integrations/proto_socket_task_service_test.dart API-1
apps/client/test/widget_test.dart API-2

최종 검증

cd apps/client && flutter test
cd apps/client && flutter analyze --no-fatal-infos

기대 결과: Flutter tests PASS, analyzer는 fatal 없이 종료한다. path dependency가 없으면 review stub에 실제 차단 출력을 기록한다. 명령은 허용된 원격/검증 환경에서 실행한다.

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